mirror of
https://github.com/neovim/neovim.git
synced 2025-09-18 09:18:19 +00:00
refactor(extmarks): use a more efficient representation
marktree.c was originally constructed as a "generic" datatype, to make the prototyping of its internal logic as simple as possible and also as the usecases for various kinds of extmarks/decorations was not yet decided. As a consequence of this, various extra indirections and allocations was needed to use marktree to implement extmarks (ns/id pairs) and decorations of different kinds (some which is just a single highlight id, other an allocated list of virtual text/lines) This change removes a lot of indirection, by making Marktree specialized for the usecase. In particular, the namespace id and mark id is stored directly, instead of the 64-bit global id particular to the Marktree struct. This removes the two maps needed to convert between global and per-ns ids. Also, "small" decorations are stored inline, i.e. those who doesn't refer to external heap memory anyway. That is highlights (with priority+flags) are stored inline, while virtual text, which anyway occurs a lot of heap allocations, do not. (previously a hack was used to elide heap allocations for highlights with standard prio+flags) TODO(bfredl): the functionaltest-lua CI version of gcc is having severe issues with uint16_t bitfields, so splitting up compound assignments and redundant casts are needed. Clean this up once we switch to a working compiler version.
This commit is contained in:
@@ -85,12 +85,12 @@ const char *describe_ns(NS ns_id)
|
||||
}
|
||||
|
||||
// Is the Namespace in use?
|
||||
static bool ns_initialized(uint64_t ns)
|
||||
static bool ns_initialized(uint32_t ns)
|
||||
{
|
||||
if (ns < 1) {
|
||||
return false;
|
||||
}
|
||||
return ns < (uint64_t)next_namespace_id;
|
||||
return ns < (uint32_t)next_namespace_id;
|
||||
}
|
||||
|
||||
|
||||
@@ -111,27 +111,27 @@ static Array extmark_to_array(ExtmarkInfo extmark, bool id, bool add_dict)
|
||||
PUT(dict, "end_col", INTEGER_OBJ(extmark.end_col));
|
||||
}
|
||||
|
||||
if (extmark.decor) {
|
||||
Decoration *decor = extmark.decor;
|
||||
if (decor->hl_id) {
|
||||
String name = cstr_to_string((const char *)syn_id2name(decor->hl_id));
|
||||
PUT(dict, "hl_group", STRING_OBJ(name));
|
||||
}
|
||||
if (kv_size(decor->virt_text)) {
|
||||
Array chunks = ARRAY_DICT_INIT;
|
||||
for (size_t i = 0; i < decor->virt_text.size; i++) {
|
||||
Array chunk = ARRAY_DICT_INIT;
|
||||
VirtTextChunk *vtc = &decor->virt_text.items[i];
|
||||
ADD(chunk, STRING_OBJ(cstr_to_string(vtc->text)));
|
||||
if (vtc->hl_id > 0) {
|
||||
ADD(chunk,
|
||||
STRING_OBJ(cstr_to_string((const char *)syn_id2name(vtc->hl_id))));
|
||||
}
|
||||
ADD(chunks, ARRAY_OBJ(chunk));
|
||||
Decoration *decor = &extmark.decor;
|
||||
if (decor->hl_id) {
|
||||
String name = cstr_to_string((const char *)syn_id2name(decor->hl_id));
|
||||
PUT(dict, "hl_group", STRING_OBJ(name));
|
||||
}
|
||||
if (kv_size(decor->virt_text)) {
|
||||
Array chunks = ARRAY_DICT_INIT;
|
||||
for (size_t i = 0; i < decor->virt_text.size; i++) {
|
||||
Array chunk = ARRAY_DICT_INIT;
|
||||
VirtTextChunk *vtc = &decor->virt_text.items[i];
|
||||
ADD(chunk, STRING_OBJ(cstr_to_string(vtc->text)));
|
||||
if (vtc->hl_id > 0) {
|
||||
ADD(chunk,
|
||||
STRING_OBJ(cstr_to_string((const char *)syn_id2name(vtc->hl_id))));
|
||||
}
|
||||
PUT(dict, "virt_text", ARRAY_OBJ(chunks));
|
||||
ADD(chunks, ARRAY_OBJ(chunk));
|
||||
}
|
||||
PUT(dict, "virt_text", ARRAY_OBJ(chunks));
|
||||
}
|
||||
|
||||
if (decor->hl_id || kv_size(decor->virt_text)) {
|
||||
PUT(dict, "priority", INTEGER_OBJ(decor->priority));
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!ns_initialized((uint64_t)ns_id)) {
|
||||
if (!ns_initialized((uint32_t)ns_id)) {
|
||||
api_set_error(err, kErrorTypeValidation, "Invalid ns_id");
|
||||
return rv;
|
||||
}
|
||||
@@ -191,7 +191,7 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
|
||||
}
|
||||
|
||||
|
||||
ExtmarkInfo extmark = extmark_from_id(buf, (uint64_t)ns_id, (uint64_t)id);
|
||||
ExtmarkInfo extmark = extmark_from_id(buf, (uint32_t)ns_id, (uint32_t)id);
|
||||
if (extmark.row < 0) {
|
||||
return rv;
|
||||
}
|
||||
@@ -252,7 +252,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!ns_initialized((uint64_t)ns_id)) {
|
||||
if (!ns_initialized((uint32_t)ns_id)) {
|
||||
api_set_error(err, kErrorTypeValidation, "Invalid ns_id");
|
||||
return rv;
|
||||
}
|
||||
@@ -310,7 +310,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
|
||||
}
|
||||
|
||||
|
||||
ExtmarkInfoArray marks = extmark_get(buf, (uint64_t)ns_id, l_row, l_col,
|
||||
ExtmarkInfoArray marks = extmark_get(buf, (uint32_t)ns_id, l_row, l_col,
|
||||
u_row, u_col, (int64_t)limit, reverse);
|
||||
|
||||
for (size_t i = 0; i < kv_size(marks); i++) {
|
||||
@@ -417,14 +417,14 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!ns_initialized((uint64_t)ns_id)) {
|
||||
if (!ns_initialized((uint32_t)ns_id)) {
|
||||
api_set_error(err, kErrorTypeValidation, "Invalid ns_id");
|
||||
goto error;
|
||||
}
|
||||
|
||||
uint64_t id = 0;
|
||||
uint32_t id = 0;
|
||||
if (opts->id.type == kObjectTypeInteger && opts->id.data.integer > 0) {
|
||||
id = (uint64_t)opts->id.data.integer;
|
||||
id = (uint32_t)opts->id.data.integer;
|
||||
} else if (HAS_KEY(opts->id)) {
|
||||
api_set_error(err, kErrorTypeValidation, "id is not a positive integer");
|
||||
goto error;
|
||||
@@ -628,20 +628,6 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
col2 = 0;
|
||||
}
|
||||
|
||||
Decoration *d = NULL;
|
||||
|
||||
if (ephemeral) {
|
||||
d = &decor;
|
||||
} else if (kv_size(decor.virt_text) || kv_size(decor.virt_lines)
|
||||
|| decor.priority != DECOR_PRIORITY_BASE
|
||||
|| decor.hl_eol) {
|
||||
// TODO(bfredl): this is a bit sketchy. eventually we should
|
||||
// have predefined decorations for both marks/ephemerals
|
||||
d = xcalloc(1, sizeof(*d));
|
||||
*d = decor;
|
||||
} else if (decor.hl_id) {
|
||||
d = decor_hl(decor.hl_id);
|
||||
}
|
||||
|
||||
// TODO(bfredl): synergize these two branches even more
|
||||
if (ephemeral && decor_state.buf == buf) {
|
||||
@@ -652,12 +638,8 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
goto error;
|
||||
}
|
||||
|
||||
extmark_set(buf, (uint64_t)ns_id, &id, (int)line, (colnr_T)col, line2, col2,
|
||||
d, right_gravity, end_right_gravity, kExtmarkNoUndo);
|
||||
|
||||
if (kv_size(decor.virt_lines)) {
|
||||
redraw_buf_line_later(buf, MIN(buf->b_ml.ml_line_count, line+1+(decor.virt_lines_above?0:1)));
|
||||
}
|
||||
extmark_set(buf, (uint32_t)ns_id, &id, (int)line, (colnr_T)col, line2, col2,
|
||||
&decor, right_gravity, end_right_gravity, kExtmarkNoUndo);
|
||||
}
|
||||
|
||||
return (Integer)id;
|
||||
@@ -682,23 +664,23 @@ Boolean nvim_buf_del_extmark(Buffer buffer, Integer ns_id, Integer id, Error *er
|
||||
if (!buf) {
|
||||
return false;
|
||||
}
|
||||
if (!ns_initialized((uint64_t)ns_id)) {
|
||||
if (!ns_initialized((uint32_t)ns_id)) {
|
||||
api_set_error(err, kErrorTypeValidation, "Invalid ns_id");
|
||||
return false;
|
||||
}
|
||||
|
||||
return extmark_del(buf, (uint64_t)ns_id, (uint64_t)id);
|
||||
return extmark_del(buf, (uint32_t)ns_id, (uint32_t)id);
|
||||
}
|
||||
|
||||
uint64_t src2ns(Integer *src_id)
|
||||
uint32_t src2ns(Integer *src_id)
|
||||
{
|
||||
if (*src_id == 0) {
|
||||
*src_id = nvim_create_namespace((String)STRING_INIT);
|
||||
}
|
||||
if (*src_id < 0) {
|
||||
return UINT64_MAX;
|
||||
return (((uint32_t)1) << 31) - 1;
|
||||
} else {
|
||||
return (uint64_t)(*src_id);
|
||||
return (uint32_t)(*src_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -753,7 +735,7 @@ Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, In
|
||||
col_end = MAXCOL;
|
||||
}
|
||||
|
||||
uint64_t ns = src2ns(&ns_id);
|
||||
uint32_t ns = src2ns(&ns_id);
|
||||
|
||||
if (!(line < buf->b_ml.ml_line_count)) {
|
||||
// safety check, we can't add marks outside the range
|
||||
@@ -773,10 +755,13 @@ Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, In
|
||||
end_line++;
|
||||
}
|
||||
|
||||
Decoration decor = DECORATION_INIT;
|
||||
decor.hl_id = hl_id;
|
||||
|
||||
extmark_set(buf, ns, NULL,
|
||||
(int)line, (colnr_T)col_start,
|
||||
end_line, (colnr_T)col_end,
|
||||
decor_hl(hl_id), true, false, kExtmarkNoUndo);
|
||||
&decor, true, false, kExtmarkNoUndo);
|
||||
return ns_id;
|
||||
}
|
||||
|
||||
@@ -808,7 +793,7 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start,
|
||||
if (line_end < 0 || line_end > MAXLNUM) {
|
||||
line_end = MAXLNUM;
|
||||
}
|
||||
extmark_clear(buf, (ns_id < 0 ? 0 : (uint64_t)ns_id),
|
||||
extmark_clear(buf, (ns_id < 0 ? 0 : (uint32_t)ns_id),
|
||||
(int)line_start, 0,
|
||||
(int)line_end-1, MAXCOL);
|
||||
}
|
||||
|
Reference in New Issue
Block a user