diff --git a/ChangeLog b/ChangeLog index e91a7c647..c02440d6c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2013-02-11 Paulo Andrade + + * include/lightning/jit_private.h, lib/jit_note.c, lib/lightning.c: + Store all annotation information in the mmap'ed area reserved for + read only data. This adds code to not allocate memory for jit_note_t + objects, and to relocate jit_line_t objects and its contents after + calculating annotation information. The jit_line_t objects are + relocated because it is not possible to always calculate before + hand data layout because note information may be extended or + redundant entries removed, as well as allowed to be added in + non sequential order. + A bug was also corrected in _jit_set_note, that was causing it + to allocate new jit_line_t objects when not needed. It was still + working correctly, but allocating way more memory than required. + 2013-02-05 Paulo Andrade *include/lightning.h, lib/lightning.c: Add the new jit_live code diff --git a/include/lightning/jit_private.h b/include/lightning/jit_private.h index 202fc67f5..a708a3d74 100644 --- a/include/lightning/jit_private.h +++ b/include/lightning/jit_private.h @@ -319,10 +319,16 @@ struct jit_state { } pool; jit_node_t *list; struct { - jit_note_t *ptr; - jit_node_t *head; /* first note node */ - jit_node_t *tail; /* linked list insertion */ - jit_word_t length; + jit_note_t *ptr; + jit_node_t *head; /* first note node */ + jit_node_t *tail; /* linked list insertion */ + jit_word_t length; + + /* fields to store temporary state information */ + jit_word_t size; + jit_node_t *name; + jit_node_t *note; + jit_uint8_t *base; } note; #if __arm__ # if DISASSEMBLER diff --git a/lib/jit_note.c b/lib/jit_note.c index 29bdc3f55..13ead7f95 100644 --- a/lib/jit_note.c +++ b/lib/jit_note.c @@ -60,8 +60,11 @@ _jit_name(jit_state_t *_jit, char *name) _jit->note.tail->link = node; _jit->note.tail = node; } - - return (node); + ++_jit->note.length; + _jit->note.size += sizeof(jit_note_t); + /* remember previous note is invalid due to name change */ + _jit->note.note = NULL; + return (_jit->note.name = node); } jit_node_t * @@ -81,8 +84,14 @@ _jit_note(jit_state_t *_jit, char *name, int line) _jit->note.tail->link = node; _jit->note.tail = node; } - - return (node); + if (_jit->note.note == NULL || + (name == NULL && _jit->note.note != NULL) || + (name != NULL && _jit->note.note == NULL) || + (name != NULL && _jit->note.note != NULL && + strcmp(name, (char *)_jit->data.ptr + _jit->note.note->v.n->u.w))) + _jit->note.size += sizeof(jit_line_t); + _jit->note.size += sizeof(jit_int32_t) * 2; + return (_jit->note.note = node); } void @@ -90,6 +99,14 @@ _jit_annotate(jit_state_t *_jit) { jit_node_t *node; jit_note_t *note; + jit_line_t *line; + jit_word_t length; + jit_word_t note_offset; + jit_word_t line_offset; + + /* initialize pointers in mmaped data area */ + _jit->note.ptr = (jit_note_t *)_jit->note.base; + _jit->note.length = 0; note = NULL; for (node = _jit->note.head; node; node = node->link) { @@ -105,6 +122,43 @@ _jit_annotate(jit_state_t *_jit) /* last note */ if (note) note->size = _jit->pc.uc - note->code; + + /* annotations may be very complex with conditions to extend + * or ignore redudant notes, as well as add entries to earlier + * notes, so, relocate the information to the data buffer, + * with likely over allocated reserved space */ + + /* relocate jit_line_t objects */ + for (note_offset = 0; note_offset < _jit->note.length; note_offset++) { + note = _jit->note.ptr + note_offset; + length = sizeof(jit_line_t) * note->length; + assert(_jit->note.base + length < _jit->data.ptr + _jit->data.length); + memcpy(_jit->note.base, note->lines, length); + free(note->lines); + note->lines = (jit_line_t *)_jit->note.base; + _jit->note.base += length; + } + + /* relocate offset and line number information */ + for (note_offset = 0; note_offset < _jit->note.length; note_offset++) { + note = _jit->note.ptr + note_offset; + for (line_offset = 0; line_offset < note->length; line_offset++) { + line = note->lines + line_offset; + length = sizeof(jit_int32_t) * line->length; + assert(_jit->note.base + length < + _jit->data.ptr + _jit->data.length); + memcpy(_jit->note.base, line->linenos, length); + free(line->linenos); + line->linenos = (jit_int32_t *)_jit->note.base; + _jit->note.base += length; + assert(_jit->note.base + length < + _jit->data.ptr + _jit->data.length); + memcpy(_jit->note.base, line->offsets, length); + free(line->offsets); + line->offsets = (jit_int32_t *)_jit->note.base; + _jit->note.base += length; + } + } } void @@ -115,6 +169,9 @@ _jit_set_note(jit_state_t *_jit, jit_note_t *note, jit_int32_t index; index = line_insert_index(note, offset); + if (note->length && index == note->length && + note->lines[index - 1].file == file) + --index; if (index >= note->length || note->lines[index].file != file) new_line(index, note, file, lineno, offset); else { @@ -190,26 +247,16 @@ _new_note(jit_state_t *_jit, jit_uint8_t *code, char *name) jit_note_t *note; jit_note_t *prev; - if (_jit->note.ptr == NULL) { - prev = NULL; - _jit->note.ptr = malloc(sizeof(jit_note_t) * 8); - } - else { - if ((_jit->note.length & 7) == 7) - _jit->note.ptr = realloc(_jit->note.ptr, sizeof(jit_note_t) * - (_jit->note.length + 9)); + if (_jit->note.length) { prev = _jit->note.ptr + _jit->note.length - 1; - } - if (prev) { assert(code >= prev->code); prev->size = code - prev->code; } - note = _jit->note.ptr + _jit->note.length; + note = (jit_note_t *)_jit->note.base; + _jit->note.base += sizeof(jit_note_t); ++_jit->note.length; note->code = code; note->name = name; - note->lines = NULL; - note->length = note->size = 0; return (note); } diff --git a/lib/lightning.c b/lib/lightning.c index 2486e51cf..a408cf9f0 100644 --- a/lib/lightning.c +++ b/lib/lightning.c @@ -531,6 +531,11 @@ jit_new_state(void) sizeof(jit_data_info_t)); #endif + /* allocate at most one extra note in case jit_name() is + * never called, or called after adding at least one note */ + _jit->note.length = 1; + _jit->note.size = sizeof(jit_note_t); + return (_jit); } @@ -1045,6 +1050,7 @@ _jit_patch_at(jit_state_t *_jit, jit_node_t *instr, jit_node_t *label) void _jit_optimize(jit_state_t *_jit) { + jit_uint8_t *ptr; jit_bool_t jump; jit_int32_t mask; jit_node_t *node; @@ -1151,22 +1157,29 @@ _jit_optimize(jit_state_t *_jit) } } - /* create read only data buffer */ - if ((_jit->data.length = (_jit->data.offset + 4095) & -4096)) { - jit_uint8_t *ptr; + /* ensure it is aligned */ + _jit->data.offset = (_jit->data.offset + 7) & -8; - ptr = mmap(NULL, _jit->data.length, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, -1, 0); - assert(ptr != MAP_FAILED); - memcpy(ptr, _jit->data.ptr, _jit->data.offset); - free(_jit->data.ptr); - _jit->data.ptr = ptr; - for (offset = 0; offset < _jit->data.size; offset++) { - for (node = _jit->data.table[offset]; node; node = node->next) { - node->flag |= jit_flag_patch; - node->u.w = (jit_word_t)(_jit->data.ptr + node->u.w); - } + /* create read only data buffer */ + _jit->data.length = (_jit->data.offset + + /* reserve space for annotations */ + _jit->note.size + 4095) & -4096; + ptr = mmap(NULL, _jit->data.length, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + assert(ptr != MAP_FAILED); + memcpy(ptr, _jit->data.ptr, _jit->data.offset); + free(_jit->data.ptr); + _jit->data.ptr = ptr; + + /* to be filled with note contents once offsets are known */ + _jit->note.base = ptr + _jit->data.offset; + memset(_jit->note.base, 0, _jit->data.length - _jit->data.offset); + + for (offset = 0; offset < _jit->data.size; offset++) { + for (node = _jit->data.table[offset]; node; node = node->next) { + node->flag |= jit_flag_patch; + node->u.w = (jit_word_t)(_jit->data.ptr + node->u.w); } } }