[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Help-smalltalk] faster startup - the end :-)
From: |
Paolo Bonzini |
Subject: |
[Help-smalltalk] faster startup - the end :-) |
Date: |
Thu, 28 Dec 2006 19:09:38 +0100 |
User-agent: |
Thunderbird 1.5.0.9 (Macintosh/20061207) |
Ok, we are done. With this patch, we avoid doing useless work to fill
the primitive table, and the last 10% separating GNU Smalltalk from Ruby
(more or less) is covered. I may give a try at removing the final
allInstancesDo: call upon quit, but that's faster quit (not faster
startup!).
Anyway, now hello world is 4-5 times faster than when I started.
Paolo
* looking for address@hidden/smalltalk--devo--2.2--patch-227 to compare with
* comparing to address@hidden/smalltalk--devo--2.2--patch-227
M libgst/ChangeLog
M libgst/genpr-parse.c
M libgst/genpr-parse.h
M libgst/interp.h
M libgst/dict.c
M libgst/save.c
M libgst/dict.h
M libgst/genpr-parse.y
* modified files
--- orig/libgst/ChangeLog
+++ mod/libgst/ChangeLog
@@ -1,5 +1,18 @@
2006-12-28 Paolo Bonzini <address@hidden>
+ * libgst/dict.c: Change _gst_init_dictionary_on_image_load to be
+ whether the primitive table's checksum is ok. If it is, just copy
+ the default primitive table just like in _gst_init_dictionary.
+ * libgst/dict.h: Adjust for above change.
+ * libgst/genpr-parse.y: Compute MD5 of DEF_FIL as checksum and
+ print it.
+ * libgst/interp.h: Declare _gst_primitives_md5.
+ * libgst/save.c: Save its contents, and compare it to pass the new flag
+ to _gst_init_dictionary_on_image_load. Move checks from load_snapshot
+ to load_file_version.
+
+2006-12-28 Paolo Bonzini <address@hidden>
+
* libgst/gstpriv.h: Remove F_FREE.
* libgst/oop.c: Remove loops setting flags to F_FREE. Set flags to 0
instead of F_FREE elsewhere.
--- orig/libgst/dict.c
+++ mod/libgst/dict.c
@@ -1223,7 +1223,7 @@ create_class (const class_definition *ci
mst_Boolean
-_gst_init_dictionary_on_image_load (size_t numOOPs)
+_gst_init_dictionary_on_image_load (mst_Boolean prim_table_matches)
{
const class_definition *ci;
@@ -1259,7 +1259,12 @@ _gst_init_dictionary_on_image_load (size
/* Important: this is called *after* _gst_init_symbols
fills in _gst_vm_primitives_symbol! */
- prepare_primitive_numbers_table ();
+ if (prim_table_matches)
+ memcpy (_gst_primitive_table, _gst_default_primitive_table,
+ sizeof (_gst_primitive_table));
+ else
+ prepare_primitive_numbers_table ();
+
init_runtime_objects ();
return (true);
}
--- orig/libgst/dict.h
+++ mod/libgst/dict.h
@@ -603,10 +603,10 @@ extern void _gst_set_oop_bytes (OOP byte
extern void _gst_free_cobject (OOP cObjOOP)
ATTRIBUTE_HIDDEN;
-/* Loads the contents of the global variable from the Smalltalk
- dictionary after NUMOOPS objects have been loaded from an
- image. */
-extern mst_Boolean _gst_init_dictionary_on_image_load (size_t numOOPs)
+/* Loads the contents of the global variables from the Smalltalk dictionary
+ after an image has been restored. PRIM_TABLE_MATCHES if true if the
+ table of primitives is already set up correctly. */
+extern mst_Boolean _gst_init_dictionary_on_image_load (mst_Boolean
prim_table_matches)
ATTRIBUTE_HIDDEN;
/* Transforms a primitive name into a primitive index, looking up
--- orig/libgst/genpr-parse.c
+++ mod/libgst/genpr-parse.c
@@ -89,6 +89,7 @@
#line 52 "genpr-parse.y"
#include "genprims.h"
+#include "md5.h"
/* This program finds declarations of the form:
@@ -169,14 +170,14 @@ static string_list *current_ids;
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
-#line 117 "genpr-parse.y"
+#line 118 "genpr-parse.y"
{
Filament *fil;
char *text;
int id;
}
/* Line 193 of yacc.c. */
-#line 180 "../../libgst/genpr-parse.c"
+#line 181 "../../libgst/genpr-parse.c"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
@@ -189,7 +190,7 @@ typedef union YYSTYPE
/* Line 216 of yacc.c. */
-#line 193 "../../libgst/genpr-parse.c"
+#line 194 "../../libgst/genpr-parse.c"
#ifdef short
# undef short
@@ -479,9 +480,9 @@ static const yytype_int8 yyrhs[] =
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 140, 140, 139, 148, 154, 153, 166, 171, 177,
- 182, 188, 196, 201, 210, 213, 220, 219, 232, 236,
- 241, 240
+ 0, 141, 141, 140, 149, 155, 154, 167, 172, 178,
+ 183, 189, 197, 202, 211, 214, 221, 220, 233, 237,
+ 242, 241
};
#endif
@@ -1402,27 +1403,27 @@ yyreduce:
switch (yyn)
{
case 2:
-#line 140 "genpr-parse.y"
+#line 141 "genpr-parse.y"
{
filprintf (stmt_fil, "#line %d \"prims.def\"\n{", yylineno);
}
break;
case 3:
-#line 144 "genpr-parse.y"
+#line 145 "genpr-parse.y"
{
free_data ();
}
break;
case 4:
-#line 148 "genpr-parse.y"
+#line 149 "genpr-parse.y"
{
}
break;
case 5:
-#line 154 "genpr-parse.y"
+#line 155 "genpr-parse.y"
{
current_id = 0;
current_func_name = strdup ((yyvsp[(2) - (2)].text));
@@ -1432,13 +1433,13 @@ yyreduce:
break;
case 6:
-#line 161 "genpr-parse.y"
+#line 162 "genpr-parse.y"
{
}
break;
case 7:
-#line 167 "genpr-parse.y"
+#line 168 "genpr-parse.y"
{
gen_prim_id (current_func_name, (yyvsp[(1) - (2)].id), (yyvsp[(2) -
(2)].text));
free ((yyvsp[(2) - (2)].text));
@@ -1446,27 +1447,27 @@ yyreduce:
break;
case 8:
-#line 172 "genpr-parse.y"
+#line 173 "genpr-parse.y"
{
}
break;
case 9:
-#line 178 "genpr-parse.y"
+#line 179 "genpr-parse.y"
{
(yyval.id) = strtoul ((yyvsp[(2) - (2)].text), NULL, 10);
}
break;
case 10:
-#line 182 "genpr-parse.y"
+#line 183 "genpr-parse.y"
{
(yyval.id) = current_id--;
}
break;
case 11:
-#line 189 "genpr-parse.y"
+#line 190 "genpr-parse.y"
{
(yyval.text) = fildelete ((yyvsp[(2) - (3)].fil));
strupr ((yyval.text));
@@ -1474,7 +1475,7 @@ yyreduce:
break;
case 12:
-#line 197 "genpr-parse.y"
+#line 198 "genpr-parse.y"
{
(yyval.fil) = filnew ("PRIM_", 5);
filcat ((yyval.fil), (yyvsp[(1) - (1)].text));
@@ -1482,7 +1483,7 @@ yyreduce:
break;
case 13:
-#line 202 "genpr-parse.y"
+#line 203 "genpr-parse.y"
{
(yyval.fil) = (yyvsp[(1) - (3)].fil);
filcat ((yyval.fil), " | PRIM_");
@@ -1491,26 +1492,26 @@ yyreduce:
break;
case 14:
-#line 211 "genpr-parse.y"
+#line 212 "genpr-parse.y"
{
}
break;
case 15:
-#line 214 "genpr-parse.y"
+#line 215 "genpr-parse.y"
{
}
break;
case 16:
-#line 220 "genpr-parse.y"
+#line 221 "genpr-parse.y"
{
(yyval.text) = strdup((yyvsp[(2) - (2)].text));
}
break;
case 17:
-#line 224 "genpr-parse.y"
+#line 225 "genpr-parse.y"
{
gen_prim_id ((yyvsp[(3) - (5)].text), (yyvsp[(4) - (5)].id),
(yyvsp[(5) - (5)].text));
free ((yyvsp[(3) - (5)].text));
@@ -1519,14 +1520,14 @@ yyreduce:
break;
case 18:
-#line 233 "genpr-parse.y"
+#line 234 "genpr-parse.y"
{
filprintf (stmt_fil, "%d", (yyvsp[(2) - (2)].id));
}
break;
case 20:
-#line 241 "genpr-parse.y"
+#line 242 "genpr-parse.y"
{
(yyval.id) = lookup_prim_id ((yyvsp[(3) - (3)].text));
if ((yyval.id) == NOT_FOUND)
@@ -1535,7 +1536,7 @@ yyreduce:
break;
case 21:
-#line 247 "genpr-parse.y"
+#line 248 "genpr-parse.y"
{
(yyval.id) = (yyvsp[(4) - (5)].id);
literal_fil = stmt_fil;
@@ -1544,7 +1545,7 @@ yyreduce:
/* Line 1267 of yacc.c. */
-#line 1548 "../../libgst/genpr-parse.c"
+#line 1549 "../../libgst/genpr-parse.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -1758,7 +1759,7 @@ yyreturn:
}
-#line 253 "genpr-parse.y"
+#line 254 "genpr-parse.y"
void
@@ -1865,12 +1866,16 @@ void
output()
{
char *proto, *stmt, *def;
+ unsigned int md5[16 / sizeof (int)];
+
gen_proto ("VMpr_HOLE");
proto = fildelete (proto_fil);
stmt = fildelete (stmt_fil);
def = fildelete (def_fil);
+ md5_buffer (def, strlen (def), md5);
+
printf ("%s\n"
"%s\n"
"intptr_t\n"
@@ -1884,6 +1889,8 @@ output()
" PRIM_FAILED;\n"
"}\n"
"\n"
+ "int _gst_primitives_md5[4] = { 0x%x, 0x%x, 0x%x, 0x%x };\n"
+ "\n"
"void\n"
"_gst_init_primitives()\n"
"{\n"
@@ -1898,7 +1905,10 @@ output()
" _gst_default_primitive_table[i].func = VMpr_HOLE;\n"
" }\n"
"}\n"
- "\n", proto, stmt, def, prim_no + 1);
+ "\n",
+ proto, stmt,
+ md5[0], md5[1], md5[2], md5[3],
+ def, prim_no + 1);
free (proto);
free (stmt);
--- orig/libgst/genpr-parse.h
+++ mod/libgst/genpr-parse.h
@@ -60,7 +60,7 @@
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
-#line 117 "genpr-parse.y"
+#line 118 "genpr-parse.y"
{
Filament *fil;
char *text;
--- orig/libgst/genpr-parse.y
+++ mod/libgst/genpr-parse.y
@@ -51,6 +51,7 @@
%{
#include "genprims.h"
+#include "md5.h"
/* This program finds declarations of the form:
@@ -356,12 +357,16 @@ void
output()
{
char *proto, *stmt, *def;
+ unsigned int md5[16 / sizeof (int)];
+
gen_proto ("VMpr_HOLE");
proto = fildelete (proto_fil);
stmt = fildelete (stmt_fil);
def = fildelete (def_fil);
+ md5_buffer (def, strlen (def), md5);
+
printf ("%s\n"
"%s\n"
"intptr_t\n"
@@ -375,6 +380,8 @@ output()
" PRIM_FAILED;\n"
"}\n"
"\n"
+ "int _gst_primitives_md5[4] = { 0x%x, 0x%x, 0x%x, 0x%x };\n"
+ "\n"
"void\n"
"_gst_init_primitives()\n"
"{\n"
@@ -389,7 +396,10 @@ output()
" _gst_default_primitive_table[i].func = VMpr_HOLE;\n"
" }\n"
"}\n"
- "\n", proto, stmt, def, prim_no + 1);
+ "\n",
+ proto, stmt,
+ md5[0], md5[1], md5[2], md5[3],
+ def, prim_no + 1);
free (proto);
free (stmt);
--- orig/libgst/interp.h
+++ mod/libgst/interp.h
@@ -542,6 +542,11 @@ prim_table_entry;
#define PRIM_RETURN_SMALL_INTEGER 0x0100 /* 31 or 63 bits */
#define PRIM_RETURN_SMALL_SMALLINTEGER 0x0300 /* 30 or 62 bits */
+/* The checksum of the table of primitive numbers. Right now it is an MD5,
+ computed from part of the C source code of prims.inl. We compare it when
+ loading an image, to avoid having to reload the primitive table. */
+extern int _gst_primitives_md5[4];
+
/* The table of functions that implement the primitives. */
extern prim_table_entry _gst_primitive_table[NUM_PRIMITIVES];
extern prim_table_entry _gst_default_primitive_table[NUM_PRIMITIVES];
--- orig/libgst/save.c
+++ mod/libgst/save.c
@@ -112,6 +112,7 @@ typedef struct save_file_header
size_t space_grow_rate;
size_t num_free_oops;
intptr_t ot_base;
+ int prim_table_md5[4]; /* checksum for the primitive table */
}
save_file_header;
@@ -212,8 +213,8 @@ static void save_file_version (int image
/* This function loads into HEADERP the header of the image file
without checking its validity.
This data is loaded from the IMAGEFD file descriptor. */
-static void load_file_version (int imageFd,
- save_file_header * headerp);
+static mst_Boolean load_file_version (int imageFd,
+ save_file_header * headerp);
/* This function walks the OOP table and converts all the relative
addresses for the instance variables to absolute ones. */
@@ -423,6 +424,8 @@ save_file_version (int imageFd, struct s
headerp->grow_threshold_percent = _gst_mem.grow_threshold_percent;
headerp->space_grow_rate = _gst_mem.space_grow_rate;
headerp->ot_base = (intptr_t) _gst_mem.ot_base;
+ memcpy (&headerp->prim_table_md5, _gst_primitives_md5, sizeof
(_gst_primitives_md5));
+
buffer_write (imageFd, headerp, sizeof (save_file_header));
}
@@ -451,34 +454,11 @@ mst_Boolean
load_snapshot (int imageFd)
{
save_file_header header;
+ int prim_table_matches;
buffer_read_init (imageFd, READ_BUFFER_SIZE);
- load_file_version (imageFd, &header);
- if (strcmp (header.signature, SIGNATURE))
- return (false);
-
- /* different sizeof(PTR) not supported */
- if (FLAG_CHANGED (header.flags, SLOT_SIZE_FLAG))
- return (false);
-
- if UNCOMMON ((wrong_endianness =
- FLAG_CHANGED (header.flags, ENDIANNESS_FLAG)))
- {
- header.oopTableSize = BYTE_INVERT (header.oopTableSize);
- header.edenSpaceSize = BYTE_INVERT (header.edenSpaceSize);
- header.survSpaceSize = BYTE_INVERT (header.survSpaceSize);
- header.oldSpaceSize = BYTE_INVERT (header.oldSpaceSize);
- header.big_object_threshold = BYTE_INVERT (header.big_object_threshold);
- header.grow_threshold_percent = BYTE_INVERT
(header.grow_threshold_percent);
- header.space_grow_rate = BYTE_INVERT (header.space_grow_rate);
- header.version = BYTE_INVERT (header.version);
- header.num_free_oops = BYTE_INVERT (header.num_free_oops);
- header.ot_base = BYTE_INVERT (header.ot_base);
- }
-
- /* check for version mismatch; if so this image file is invalid */
- if (header.version > VERSION_REQUIRED)
- return (false);
+ if (!load_file_version (imageFd, &header))
+ return false;
#ifdef SNAPSHOT_TRACE
printf ("After loading header: %lld\n", file_pos + buf_pos);
@@ -510,7 +490,9 @@ load_snapshot (int imageFd)
if (ot_delta)
restore_all_pointer_slots ();
- if (_gst_init_dictionary_on_image_load (num_used_oops))
+ prim_table_matches = !memcmp (header.prim_table_md5, _gst_primitives_md5,
+ sizeof (_gst_primitives_md5));
+ if (_gst_init_dictionary_on_image_load (prim_table_matches))
{
#ifdef SNAPSHOT_TRACE
_gst_dump_oop_table ();
@@ -521,19 +503,47 @@ load_snapshot (int imageFd)
return (false);
}
-void
+mst_Boolean
load_file_version (int imageFd,
save_file_header * headerp)
{
buffer_read (imageFd, headerp, sizeof (save_file_header));
+ if (strcmp (headerp->signature, SIGNATURE))
+ return (false);
+
+ /* different sizeof(PTR) not supported */
+ if (FLAG_CHANGED (headerp->flags, SLOT_SIZE_FLAG))
+ return (false);
+
+ if UNCOMMON ((wrong_endianness =
+ FLAG_CHANGED (headerp->flags, ENDIANNESS_FLAG)))
+ {
+ headerp->oopTableSize = BYTE_INVERT (headerp->oopTableSize);
+ headerp->edenSpaceSize = BYTE_INVERT (headerp->edenSpaceSize);
+ headerp->survSpaceSize = BYTE_INVERT (headerp->survSpaceSize);
+ headerp->oldSpaceSize = BYTE_INVERT (headerp->oldSpaceSize);
+ headerp->big_object_threshold = BYTE_INVERT
(headerp->big_object_threshold);
+ headerp->grow_threshold_percent = BYTE_INVERT
(headerp->grow_threshold_percent);
+ headerp->space_grow_rate = BYTE_INVERT (headerp->space_grow_rate);
+ headerp->version = BYTE_INVERT (headerp->version);
+ headerp->num_free_oops = BYTE_INVERT (headerp->num_free_oops);
+ headerp->ot_base = BYTE_INVERT (headerp->ot_base);
+ headerp->prim_table_md5[0] = BYTE_INVERT (headerp->prim_table_md5[0]);
+ headerp->prim_table_md5[1] = BYTE_INVERT (headerp->prim_table_md5[1]);
+ headerp->prim_table_md5[2] = BYTE_INVERT (headerp->prim_table_md5[2]);
+ headerp->prim_table_md5[3] = BYTE_INVERT (headerp->prim_table_md5[3]);
+ }
+
+ /* check for version mismatch; if so this image file is invalid */
+ if (headerp->version > VERSION_REQUIRED)
+ return (false);
+
+ return (true);
}
void
load_oop_table (int imageFd)
{
- OOP oop;
- int i;
-
/* Load in the valid OOP slots from previous dump. The others are already
initialized to free (0). */
buffer_read (imageFd, _gst_mem.ot, sizeof (struct oop_s) * num_used_oops);
- [Help-smalltalk] faster startup - the end :-),
Paolo Bonzini <=