From: Dmitry Antipov Date: Wed, 2 Jul 2014 03:26:19 +0000 (+0400) Subject: Shrink Lisp_Sub_Char_Table by preferring C integers to Lisp_Objects. X-Git-Tag: emacs-25.0.90~2636^2~73^2~14 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=477daa5b533af8f62c9b6893e2d522b93d9c2853;p=emacs.git Shrink Lisp_Sub_Char_Table by preferring C integers to Lisp_Objects. * lisp.h (struct Lisp_Sub_Char_Table): Use C integers for depth and min_char slots. Adjust comment. (enum char_table_specials): Rename from CHAR_TABLE_STANDARD_SLOTS. Add SUB_CHAR_TABLE_OFFSET member. (make_uninit_sub_char_table): New function. * alloc.c (mark_char_table): Add extra argument to denote char table subtype. Adjust to match new layout of sub char-table. (mark_object): Always mark sub char-tables with mark_char_table. * chartab.c (make_sub_char_table, copy_sub_char_table) (sub_char_table_ref, sub_char_table_ref_and_range, sub_char_table_set) (sub_char_table_set_range, optimize_sub_char_table, map_sub_char_table) (map_sub_char_table_for_charset, uniprop_table_uncompress): All related users changed. * lread.c (read1): Adjust to match new layout of sub char-table. --- diff --git a/src/ChangeLog b/src/ChangeLog index 7eb789ca341..3df37a69527 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,21 @@ +2014-07-02 Dmitry Antipov + + Shrink Lisp_Sub_Char_Table by preferring C integers to Lisp_Objects. + * lisp.h (struct Lisp_Sub_Char_Table): Use C integers for depth and + min_char slots. Adjust comment. + (enum char_table_specials): Rename from CHAR_TABLE_STANDARD_SLOTS. + Add SUB_CHAR_TABLE_OFFSET member. + (make_uninit_sub_char_table): New function. + * alloc.c (mark_char_table): Add extra argument to denote char table + subtype. Adjust to match new layout of sub char-table. + (mark_object): Always mark sub char-tables with mark_char_table. + * chartab.c (make_sub_char_table, copy_sub_char_table) + (sub_char_table_ref, sub_char_table_ref_and_range, sub_char_table_set) + (sub_char_table_set_range, optimize_sub_char_table, map_sub_char_table) + (map_sub_char_table_for_charset, uniprop_table_uncompress): + All related users changed. + * lread.c (read1): Adjust to match new layout of sub char-table. + 2014-07-02 Stefan Monnier * keymap.c (get_keyelt): Simplify. diff --git a/src/alloc.c b/src/alloc.c index e2213db853d..6eb2e756ed1 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -5958,14 +5958,15 @@ mark_vectorlike (struct Lisp_Vector *ptr) symbols. */ static void -mark_char_table (struct Lisp_Vector *ptr) +mark_char_table (struct Lisp_Vector *ptr, enum pvec_type pvectype) { int size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; - int i; + /* Consult the Lisp_Sub_Char_Table layout before changing this. */ + int i, idx = (pvectype == PVEC_SUB_CHAR_TABLE ? SUB_CHAR_TABLE_OFFSET : 0); eassert (!VECTOR_MARKED_P (ptr)); VECTOR_MARK (ptr); - for (i = 0; i < size; i++) + for (i = idx; i < size; i++) { Lisp_Object val = ptr->contents[i]; @@ -5974,7 +5975,7 @@ mark_char_table (struct Lisp_Vector *ptr) if (SUB_CHAR_TABLE_P (val)) { if (! VECTOR_MARKED_P (XVECTOR (val))) - mark_char_table (XVECTOR (val)); + mark_char_table (XVECTOR (val), PVEC_SUB_CHAR_TABLE); } else mark_object (val); @@ -6320,7 +6321,8 @@ mark_object (Lisp_Object arg) break; case PVEC_CHAR_TABLE: - mark_char_table (ptr); + case PVEC_SUB_CHAR_TABLE: + mark_char_table (ptr, (enum pvec_type) pvectype); break; case PVEC_BOOL_VECTOR: @@ -7218,7 +7220,7 @@ The time is in seconds as a floating point value. */); union { enum CHARTAB_SIZE_BITS CHARTAB_SIZE_BITS; - enum CHAR_TABLE_STANDARD_SLOTS CHAR_TABLE_STANDARD_SLOTS; + enum char_table_specials char_table_specials; enum char_bits char_bits; enum CHECK_LISP_OBJECT_TYPE CHECK_LISP_OBJECT_TYPE; enum DEFAULT_HASH_SIZE DEFAULT_HASH_SIZE; diff --git a/src/chartab.c b/src/chartab.c index 4d4e6381b19..3906ad30b37 100644 --- a/src/chartab.c +++ b/src/chartab.c @@ -140,15 +140,11 @@ the char-table has no extra slot. */) static Lisp_Object make_sub_char_table (int depth, int min_char, Lisp_Object defalt) { - Lisp_Object table; - int size = (PSEUDOVECSIZE (struct Lisp_Sub_Char_Table, contents) - + chartab_size[depth]); - - table = Fmake_vector (make_number (size), defalt); - XSETPVECTYPE (XVECTOR (table), PVEC_SUB_CHAR_TABLE); - XSUB_CHAR_TABLE (table)->depth = make_number (depth); - XSUB_CHAR_TABLE (table)->min_char = make_number (min_char); + int i; + Lisp_Object table = make_uninit_sub_char_table (depth, min_char); + for (i = 0; i < chartab_size[depth]; i++) + XSUB_CHAR_TABLE (table)->contents[i] = defalt; return table; } @@ -172,8 +168,8 @@ char_table_ascii (Lisp_Object table) static Lisp_Object copy_sub_char_table (Lisp_Object table) { - int depth = XINT (XSUB_CHAR_TABLE (table)->depth); - int min_char = XINT (XSUB_CHAR_TABLE (table)->min_char); + int depth = XSUB_CHAR_TABLE (table)->depth; + int min_char = XSUB_CHAR_TABLE (table)->min_char; Lisp_Object copy = make_sub_char_table (depth, min_char, Qnil); int i; @@ -220,10 +216,8 @@ static Lisp_Object sub_char_table_ref (Lisp_Object table, int c, bool is_uniprop) { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); - int depth = XINT (tbl->depth); - int min_char = XINT (tbl->min_char); Lisp_Object val; - int idx = CHARTAB_IDX (c, depth, min_char); + int idx = CHARTAB_IDX (c, tbl->depth, tbl->min_char); val = tbl->contents[idx]; if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (val)) @@ -265,8 +259,7 @@ sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to, Lisp_Object defalt, bool is_uniprop) { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); - int depth = XINT (tbl->depth); - int min_char = XINT (tbl->min_char); + int depth = tbl->depth, min_char = tbl->min_char; int chartab_idx = CHARTAB_IDX (c, depth, min_char), idx; Lisp_Object val; @@ -402,8 +395,7 @@ static void sub_char_table_set (Lisp_Object table, int c, Lisp_Object val, bool is_uniprop) { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); - int depth = XINT ((tbl)->depth); - int min_char = XINT ((tbl)->min_char); + int depth = tbl->depth, min_char = tbl->min_char; int i = CHARTAB_IDX (c, depth, min_char); Lisp_Object sub; @@ -458,8 +450,7 @@ sub_char_table_set_range (Lisp_Object table, int from, int to, Lisp_Object val, bool is_uniprop) { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); - int depth = XINT ((tbl)->depth); - int min_char = XINT ((tbl)->min_char); + int depth = tbl->depth, min_char = tbl->min_char; int chars_in_block = chartab_chars[depth]; int i, c, lim = chartab_size[depth]; @@ -689,9 +680,8 @@ static Lisp_Object optimize_sub_char_table (Lisp_Object table, Lisp_Object test) { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); - int depth = XINT (tbl->depth); + int i, depth = tbl->depth; Lisp_Object elt, this; - int i; bool optimizable; elt = XSUB_CHAR_TABLE (table)->contents[0]; @@ -778,8 +768,8 @@ map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); - depth = XINT (tbl->depth); - min_char = XINT (tbl->min_char); + depth = tbl->depth; + min_char = tbl->min_char; max_char = min_char + chartab_chars[depth - 1] - 1; } else @@ -973,12 +963,10 @@ map_sub_char_table_for_charset (void (*c_function) (Lisp_Object, Lisp_Object), unsigned from, unsigned to) { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); - int depth = XINT (tbl->depth); - int c, i; + int i, c = tbl->min_char, depth = tbl->depth; if (depth < 3) - for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth]; - i++, c += chartab_chars[depth]) + for (i = 0; i < chartab_size[depth]; i++, c += chartab_chars[depth]) { Lisp_Object this; @@ -1000,7 +988,7 @@ map_sub_char_table_for_charset (void (*c_function) (Lisp_Object, Lisp_Object), } } else - for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth]; i++, c ++) + for (i = 0; i < chartab_size[depth]; i++, c++) { Lisp_Object this; unsigned code; @@ -1147,8 +1135,7 @@ static Lisp_Object uniprop_table_uncompress (Lisp_Object table, int idx) { Lisp_Object val = XSUB_CHAR_TABLE (table)->contents[idx]; - int min_char = (XINT (XSUB_CHAR_TABLE (table)->min_char) - + chartab_chars[2] * idx); + int min_char = XSUB_CHAR_TABLE (table)->min_char + chartab_chars[2] * idx; Lisp_Object sub = make_sub_char_table (3, min_char, Qnil); const unsigned char *p, *pend; diff --git a/src/lisp.h b/src/lisp.h index fb832b80940..3c4845ec79b 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -1407,10 +1407,11 @@ gc_aset (Lisp_Object array, ptrdiff_t idx, Lisp_Object val) sense to handle a char-table with type struct Lisp_Vector. An element of a char table can be any Lisp objects, but if it is a sub char-table, we treat it a table that contains information of a - specific range of characters. A sub char-table has the same - structure as a vector. A sub char table appears only in an element - of a char-table, and there's no way to access it directly from - Emacs Lisp program. */ + specific range of characters. A sub char-table is like a vector but + with two integer fields between the header and Lisp data, which means + that it has to be marked with some precautions (see mark_char_table + in alloc.c). A sub char-table appears only in an element of a char-table, + and there's no way to access it directly from Emacs Lisp program. */ enum CHARTAB_SIZE_BITS { @@ -1465,10 +1466,10 @@ struct Lisp_Sub_Char_Table contains 32 elements, and each element covers 128 characters. A sub char-table of depth 3 contains 128 elements, and each element is for one character. */ - Lisp_Object depth; + int depth; /* Minimum character covered by the sub char-table. */ - Lisp_Object min_char; + int min_char; /* Use set_sub_char_table_contents to set this. */ Lisp_Object contents[FLEXIBLE_ARRAY_MEMBER]; @@ -1539,12 +1540,16 @@ struct Lisp_Subr const char *doc; }; -/* This is the number of slots that every char table must have. This - counts the ordinary slots and the top, defalt, parent, and purpose - slots. */ -enum CHAR_TABLE_STANDARD_SLOTS +enum char_table_specials { - CHAR_TABLE_STANDARD_SLOTS = PSEUDOVECSIZE (struct Lisp_Char_Table, extras) + /* This is the number of slots that every char table must have. This + counts the ordinary slots and the top, defalt, parent, and purpose + slots. */ + CHAR_TABLE_STANDARD_SLOTS = PSEUDOVECSIZE (struct Lisp_Char_Table, extras), + + /* This is an index of first Lisp_Object field in Lisp_Sub_Char_Table + when the latter is treated as an ordinary Lisp_Vector. */ + SUB_CHAR_TABLE_OFFSET = PSEUDOVECSIZE (struct Lisp_Sub_Char_Table, contents) }; /* Return the number of "extra" slots in the char table CT. */ @@ -3723,6 +3728,20 @@ make_uninit_vector (ptrdiff_t size) return v; } +/* Like above, but special for sub char-tables. */ + +INLINE Lisp_Object +make_uninit_sub_char_table (int depth, int min_char) +{ + int slots = SUB_CHAR_TABLE_OFFSET + chartab_size[depth]; + Lisp_Object v = make_uninit_vector (slots); + + XSETPVECTYPE (XVECTOR (v), PVEC_SUB_CHAR_TABLE); + XSUB_CHAR_TABLE (v)->depth = depth; + XSUB_CHAR_TABLE (v)->min_char = min_char; + return v; +} + extern struct Lisp_Vector *allocate_pseudovector (int, int, enum pvec_type); #define ALLOCATE_PSEUDOVECTOR(typ,field,tag) \ ((typ*) \ diff --git a/src/lread.c b/src/lread.c index f252993207d..639d574ac6b 100644 --- a/src/lread.c +++ b/src/lread.c @@ -2619,21 +2619,38 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) c = READCHAR; if (c == '[') { - Lisp_Object tmp; - int depth; - ptrdiff_t size; + /* Sub char-table can't be read as a regular + vector because of a two C integer fields. */ + Lisp_Object tbl, tmp = read_list (1, readcharfun); + ptrdiff_t size = XINT (Flength (tmp)); + int i, depth, min_char; + struct Lisp_Cons *cell; - tmp = read_vector (readcharfun, 0); - size = ASIZE (tmp); if (size == 0) - error ("Invalid size char-table"); - if (! RANGED_INTEGERP (1, AREF (tmp, 0), 3)) - error ("Invalid depth in char-table"); - depth = XINT (AREF (tmp, 0)); + error ("Zero-sized sub char-table"); + + if (! RANGED_INTEGERP (1, XCAR (tmp), 3)) + error ("Invalid depth in sub char-table"); + depth = XINT (XCAR (tmp)); if (chartab_size[depth] != size - 2) - error ("Invalid size char-table"); - XSETPVECTYPE (XVECTOR (tmp), PVEC_SUB_CHAR_TABLE); - return tmp; + error ("Invalid size in sub char-table"); + cell = XCONS (tmp), tmp = XCDR (tmp), size--; + free_cons (cell); + + if (! RANGED_INTEGERP (0, XCAR (tmp), MAX_CHAR)) + error ("Invalid minimum character in sub-char-table"); + min_char = XINT (XCAR (tmp)); + cell = XCONS (tmp), tmp = XCDR (tmp), size--; + free_cons (cell); + + tbl = make_uninit_sub_char_table (depth, min_char); + for (i = 0; i < size; i++) + { + XSUB_CHAR_TABLE (tbl)->contents[i] = XCAR (tmp); + cell = XCONS (tmp), tmp = XCDR (tmp); + free_cons (cell); + } + return tbl; } invalid_syntax ("#^^"); } diff --git a/src/print.c b/src/print.c index 9050a0cb773..9b3620765a8 100644 --- a/src/print.c +++ b/src/print.c @@ -1968,7 +1968,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) Otherwise we'll make a line extremely long, which results in slow redisplay. */ if (SUB_CHAR_TABLE_P (obj) - && XINT (XSUB_CHAR_TABLE (obj)->depth) == 3) + && XSUB_CHAR_TABLE (obj)->depth == 3) PRINTCHAR ('\n'); PRINTCHAR ('#'); PRINTCHAR ('^');