faster startup 9/n - reinstate symbols faster

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

faster startup 9/n - reinstate symbols faster

Paolo Bonzini
To gain ~10% more (of course, 10% now being much less than 10% when I
started!) we can avoid doing hash table walks to find symbols at image
load time.  Instead, we group all symbols together at the beginning of
the OOP table.

This brings several headaches:
- each symbol is actually two objects, a Symbol and a SymLink.  It's
easier if we break symbol creation in two (creating Symbols as soon as
possible, and the SymLinks only after we've created the system classes).

- there were two tables of symbols, one for the various _gst_*_symbol
variables and one for the table of builtin selectors.  It's easier if
symbols only appear in one table.

- _gst_intern_string is called in a lot more places; in particular, to
initialize the Smalltalk dictionary and to set up the table of
primitives.  It still accounts for ~10% of startup time, and we can get
rid of it relatively easily.  The Smalltalk dictionary's keys can be
placed in _gst_*_symbol global variables, while the table of primitives
should be checksummed in some way.

Paolo

006-12-28  Paolo Bonzini  <[hidden email]>
 
        * libgst/builtins.gperf: Remove _COLON from the enum for special
        bytecodes.
        * libgst/byte.def: Likewise.
        * libgst/vm.def: Likewise.
        * libgst/xlat.c: Likewise.

        * libgst/comp.c: Remove the possibility to inline #perform:.

        * libgst/byte.c: Turn _gst_builtin_selectors into an array of
        structs (instead of pointers).
        * libgst/opt.c: Likewise.
        * libgst/sym.c: Likewise.
        * libgst/vm.def: Use _gst_builtin_selectors instead of symbols
        defined in sym.c (not slower with the change above).
        * libgst/xlat.c: Only store the opcode in special_send_bytecodes and
        use _gst_builtin_selectors for the other pieces of information.

        * libgst/dict.c: Don't reload the _gst_*_class variables unless
        necessary.  Pass the class to identity_dictionary_new and adjust the
        sole caller, _gst_valid_class_method_dictionary.  Split the
        creation of symbols in two parts (creating symbols, and populating
        the symbol table with SymLink objects); call _gst_restore_symbols
        when loading the image.  Remove _gst_directed_message_new_args.
        * libgst/interp.c: Remove commented out code to start call-ins through
        Process>>#startExecution:.
        * libgst/sym.c: Remove symbols for the special selectors.  New
        functions alloc_symbol_oop and alloc_symlink to support two-phase
        creation of symbols in the image.  Add _gst_smalltalk_namespace_symbol.
        New functions intern_string_fast and _gst_restore_symbols to support
        fast reloading of symbols when loading the image.
        * libgst/sym.h: Adjust for changes to sym.c.

        * libgst/genvm-parse.y: Add const qualifier to yyprint.


--- orig/libgst/builtins.gperf
+++ mod/libgst/builtins.gperf
@@ -47,13 +47,13 @@ struct builtin_selector { int offset; OO
 *;                   NULL, 1,        TIMES_SPECIAL
 /;                   NULL, 1,        DIVIDE_SPECIAL
 \\;               NULL, 1,        REMAINDER_SPECIAL
-bitXor:;             NULL, 1,        BIT_XOR_COLON_SPECIAL
-bitShift:;           NULL, 1,        BIT_SHIFT_COLON_SPECIAL
+bitXor:;             NULL, 1,        BIT_XOR_SPECIAL
+bitShift:;           NULL, 1,        BIT_SHIFT_SPECIAL
 //;                 NULL, 1,        INTEGER_DIVIDE_SPECIAL
-bitAnd:;             NULL, 1,        BIT_AND_COLON_SPECIAL
-bitOr:;             NULL, 1,        BIT_OR_COLON_SPECIAL
-at:;                 NULL, 1,        AT_COLON_SPECIAL
-at:put:;             NULL, 2,        AT_COLON_PUT_COLON_SPECIAL
+bitAnd:;             NULL, 1,        BIT_AND_SPECIAL
+bitOr:;             NULL, 1,        BIT_OR_SPECIAL
+at:;                 NULL, 1,        AT_SPECIAL
+at:put:;             NULL, 2,        AT_PUT_SPECIAL
 size;               NULL, 0,        SIZE_SPECIAL
 class;               NULL, 0,        CLASS_SPECIAL
 isNil;               NULL, 0,        IS_NIL_SPECIAL


--- orig/libgst/builtins.inl
+++ mod/libgst/builtins.inl
@@ -1187,7 +1187,7 @@ static struct builtin_selector _gst_buil
     {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str650,               NULL, 1,        NEW_COLON_SPECIAL},
     {-1,NULL,-1,-1}, {-1,NULL,-1,-1}, {-1,NULL,-1,-1},
 #line 55 "../../libgst/builtins.gperf"
-    {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str654,                 NULL, 1,        AT_COLON_SPECIAL},
+    {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str654,                 NULL, 1,        AT_SPECIAL},
 #line 265 "../../libgst/builtins.gperf"
     {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str655,       NULL, 0,       231},
     {-1,NULL,-1,-1}, {-1,NULL,-1,-1}, {-1,NULL,-1,-1},
@@ -1196,7 +1196,7 @@ static struct builtin_selector _gst_buil
     {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str660,           NULL, 0,       129},
     {-1,NULL,-1,-1}, {-1,NULL,-1,-1},
 #line 51 "../../libgst/builtins.gperf"
-    {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str663,           NULL, 1,        BIT_SHIFT_COLON_SPECIAL},
+    {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str663,           NULL, 1,        BIT_SHIFT_SPECIAL},
     {-1,NULL,-1,-1},
 #line 94 "../../libgst/builtins.gperf"
     {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str665,               NULL, 0,       60},
@@ -1259,7 +1259,7 @@ static struct builtin_selector _gst_buil
     {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str697,           NULL, 0,       197},
     {-1,NULL,-1,-1}, {-1,NULL,-1,-1},
 #line 50 "../../libgst/builtins.gperf"
-    {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str700,             NULL, 1,        BIT_XOR_COLON_SPECIAL},
+    {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str700,             NULL, 1,        BIT_XOR_SPECIAL},
 #line 68 "../../libgst/builtins.gperf"
     {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str701,     NULL, 1,       34},
     {-1,NULL,-1,-1},
@@ -1355,7 +1355,7 @@ static struct builtin_selector _gst_buil
 #line 85 "../../libgst/builtins.gperf"
     {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str768,           NULL, 1,       51},
 #line 53 "../../libgst/builtins.gperf"
-    {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str769,             NULL, 1,        BIT_AND_COLON_SPECIAL},
+    {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str769,             NULL, 1,        BIT_AND_SPECIAL},
     {-1,NULL,-1,-1}, {-1,NULL,-1,-1}, {-1,NULL,-1,-1},
 #line 274 "../../libgst/builtins.gperf"
     {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str773,       NULL, 2,       240},
@@ -1416,7 +1416,7 @@ static struct builtin_selector _gst_buil
     {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str816,           NULL, 0,       57},
     {-1,NULL,-1,-1}, {-1,NULL,-1,-1},
 #line 54 "../../libgst/builtins.gperf"
-    {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str819,             NULL, 1,        BIT_OR_COLON_SPECIAL},
+    {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str819,             NULL, 1,        BIT_OR_SPECIAL},
     {-1,NULL,-1,-1},
 #line 287 "../../libgst/builtins.gperf"
     {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str821,             NULL, 1,       253},
@@ -1451,7 +1451,7 @@ static struct builtin_selector _gst_buil
     {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str852,         NULL, 1,       255},
     {-1,NULL,-1,-1},
 #line 56 "../../libgst/builtins.gperf"
-    {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str854,             NULL, 2,        AT_COLON_PUT_COLON_SPECIAL},
+    {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str854,             NULL, 2,        AT_PUT_SPECIAL},
     {-1,NULL,-1,-1},
 #line 78 "../../libgst/builtins.gperf"
     {(int)(long)&((struct _gst_builtin_selectors_names_t *)0)->_gst_builtin_selectors_names_str856,           NULL, 0,       44},


--- orig/libgst/byte.c
+++ mod/libgst/byte.c
@@ -369,12 +369,12 @@ _gst_print_bytecode_name (gst_uchar * bp
 
     SEND_ARITH {
       printf ("%s\tsend arithmetic message %O\n", prefix,
-      _gst_builtin_selectors[n]->symbol);
+      _gst_builtin_selectors[n].symbol);
       prefix = pref;
     }
     SEND_SPECIAL {
       printf ("%s\tsend special message %O\n", prefix,
-      _gst_builtin_selectors[n + 16]->symbol);
+      _gst_builtin_selectors[n + 16].symbol);
       prefix = pref;
     }
 
@@ -385,7 +385,7 @@ _gst_print_bytecode_name (gst_uchar * bp
 
     SEND_IMMEDIATE {
       printf ("%s\tsend special message %O%s\n", prefix,
-      _gst_builtin_selectors[n]->symbol,
+      _gst_builtin_selectors[n].symbol,
       super ? " to super" : "");
       prefix = pref;
     }


--- orig/libgst/byte.def
+++ mod/libgst/byte.def
@@ -165,13 +165,13 @@ INVALID (opcode, arg);
   dispatch SEND_ARITH (10);
 }
 
-/* BIT_XOR_COLON_SPECIAL(*) */
+/* BIT_XOR_SPECIAL(*) */
 11 {
   extract opcode (8), arg_lsb (8);
   dispatch SEND_ARITH (11);
 }
 
-/* BIT_SHIFT_COLON_SPECIAL(*) */
+/* BIT_SHIFT_SPECIAL(*) */
 12 {
   extract opcode (8), arg_lsb (8);
   dispatch SEND_ARITH (12);
@@ -183,25 +183,25 @@ INVALID (opcode, arg);
   dispatch SEND_ARITH (13);
 }
 
-/* BIT_AND_COLON_SPECIAL(*) */
+/* BIT_AND_SPECIAL(*) */
 14 {
   extract opcode (8), arg_lsb (8);
   dispatch SEND_ARITH (14);
 }
 
-/* BIT_OR_COLON_SPECIAL(*) */
+/* BIT_OR_SPECIAL(*) */
 15 {
   extract opcode (8), arg_lsb (8);
   dispatch SEND_ARITH (15);
 }
 
-/* AT_COLON_SPECIAL(*) */
+/* AT_SPECIAL(*) */
 16 {
   extract opcode (8), arg_lsb (8);
   dispatch SEND_SPECIAL (0);
 }
 
-/* AT_COLON_PUT_COLON_SPECIAL(*) */
+/* AT_PUT_SPECIAL(*) */
 17 {
   extract opcode (8), arg_lsb (8);
   dispatch SEND_SPECIAL (1);
@@ -701,7 +701,7 @@ INVALID (opcode, arg);
 }
 
 /* PUSH_INTEGER(*)
-   AT_COLON_SPECIAL(0) */
+   AT_SPECIAL(0) */
 91 {
   extract opcode (8), arg_lsb (8);
   dispatch PUSH_INTEGER (arg | arg_lsb);
@@ -726,7 +726,7 @@ INVALID (opcode, arg);
 }
 
 /* PUSH_TEMPORARY_VARIABLE(*)
-   AT_COLON_SPECIAL(0) */
+   AT_SPECIAL(0) */
 94 {
   extract opcode (8), arg_lsb (8);
   dispatch PUSH_TEMPORARY_VARIABLE (arg | arg_lsb);
@@ -1030,7 +1030,7 @@ INVALID (opcode, arg);
 }
 
 /* PUSH_TEMPORARY_VARIABLE(*)
-   AT_COLON_PUT_COLON_SPECIAL(0) */
+   AT_PUT_SPECIAL(0) */
 130 {
   extract opcode (8), arg_lsb (8);
   dispatch PUSH_TEMPORARY_VARIABLE (arg | arg_lsb);
@@ -1373,7 +1373,7 @@ INVALID (opcode, arg);
 }
 
 /* PUSH_INTEGER(*)
-   BIT_AND_COLON_SPECIAL(0) */
+   BIT_AND_SPECIAL(0) */
 169 {
   extract opcode (8), arg_lsb (8);
   dispatch PUSH_INTEGER (arg | arg_lsb);
@@ -1423,7 +1423,7 @@ INVALID (opcode, arg);
 }
 
 /* PUSH_LIT_CONSTANT(*)
-   AT_COLON_PUT_COLON_SPECIAL(0) */
+   AT_PUT_SPECIAL(0) */
 175 {
   extract opcode (8), arg_lsb (8);
   dispatch PUSH_LIT_CONSTANT (arg | arg_lsb);
@@ -1915,7 +1915,7 @@ INVALID (opcode, arg);
 
 /* PUSH_LIT_CONSTANT(*)
    PUSH_TEMPORARY_VARIABLE(0)
-   AT_COLON_PUT_COLON_SPECIAL(0) */
+   AT_PUT_SPECIAL(0) */
 230 {
   extract opcode (8), arg_lsb (8);
   dispatch PUSH_LIT_CONSTANT (arg | arg_lsb);
@@ -1924,7 +1924,7 @@ INVALID (opcode, arg);
 }
 
 /* PUSH_INTEGER(*)
-   AT_COLON_PUT_COLON_SPECIAL(0) */
+   AT_PUT_SPECIAL(0) */
 231 {
   extract opcode (8), arg_lsb (8);
   dispatch PUSH_INTEGER (arg | arg_lsb);


--- orig/libgst/byte.h
+++ mod/libgst/byte.h
@@ -67,14 +67,14 @@ enum {
   TIMES_SPECIAL = 8,
   DIVIDE_SPECIAL = 9,
   REMAINDER_SPECIAL = 10,
-  BIT_XOR_COLON_SPECIAL = 11,
-  BIT_SHIFT_COLON_SPECIAL = 12,
+  BIT_XOR_SPECIAL = 11,
+  BIT_SHIFT_SPECIAL = 12,
   INTEGER_DIVIDE_SPECIAL = 13,
-  BIT_AND_COLON_SPECIAL = 14,
-  BIT_OR_COLON_SPECIAL = 15,
+  BIT_AND_SPECIAL = 14,
+  BIT_OR_SPECIAL = 15,
 
-  AT_COLON_SPECIAL = 16,
-  AT_COLON_PUT_COLON_SPECIAL = 17,
+  AT_SPECIAL = 16,
+  AT_PUT_SPECIAL = 17,
   SIZE_SPECIAL = 18,
   CLASS_SPECIAL = 19,
   IS_NIL_SPECIAL = 20,


--- orig/libgst/comp.c
+++ mod/libgst/comp.c
@@ -69,15 +69,6 @@
    output for correctness.  */
 /* #define VERIFY_COMPILED_METHODS */
 
-/* Define this to inline #perform: with a constant selector.  It is
-   disabled because it removes some error checking.  For example, it
-   allows one to compile "self perform: #yourself with: 1", after
-   which the compiler thinks that the stack is balanced, when in
-   fact it is not (because #yourself is a SEND_IMMEDIATE selector);
-   or even worse, "self perform: #this:that: with: 1", where the stack
-   upon entry to #this:that: is confused beyond any recognition.  */
-/* #define INLINE_PERFORM */
-
 #define LITERAL_VEC_CHUNK_SIZE 32
 
 
@@ -185,13 +176,6 @@ static mst_Boolean compile_to_by_do (tre
      tree_node by,
      tree_node block);
 
-/* Special case compilation of #perform: and friends with a constant
-   selector (in case of #perform:withArguments:, the arguments must be
-   a constant array or an array constructor).  This is done especially
-   for the Java translator, but is always good, so why not?  */
-static mst_Boolean compile_perform (OOP selectorOOP,
-    tree_node expr);
-
 /* Special case compilation of a #and: or #or: boolean operation; very
    similar to compile_if_statement.  EXPR is a node for the entire
    keyword message send.  Returns true if byte codes were emitted,
@@ -1407,15 +1391,6 @@ compile_keyword_expr (tree_node expr)
     expr->v_expr.expression->v_list.next->v_list.next->v_list.value))
  return;
     }
-  else if (selector == _gst_perform_symbol
-   || selector == _gst_perform_with_symbol
-   || selector == _gst_perform_with_with_symbol
-   || selector == _gst_perform_with_with_with_symbol
-   || selector == _gst_perform_with_arguments_symbol)
-    {
-      if (compile_perform (selector, expr))
- return;
-    }
 
   numArgs = list_length (expr->v_expr.expression);
 
@@ -1423,46 +1398,6 @@ compile_keyword_expr (tree_node expr)
   compile_send (expr, selector, numArgs);
 }
 
-mst_Boolean
-compile_perform (OOP selectorOOP,
- tree_node expr)
-{
-#ifdef INLINE_PERFORM
-  tree_node selector = expr->v_expr.expression->v_list.value;
-  tree_node args = expr->v_expr.expression->v_list.next;
-  int i;
-
-  /* We inline only if the selector is a symbol... */
-  if (selector->nodeType != TREE_CONST_EXPR
-      || selector->v_const.constType != CONST_OOP
-      || OOP_CLASS (selector->v_const.val.oopVal) != _gst_symbol_class)
-    return false;
-
-  /* ... and in case of perform:withArguments:, if the list of arguments
-     is a constant array or an array constructor.  */
-  if (selectorOOP == _gst_perform_with_arguments_symbol)
-    {
-      if (args->nodeType != TREE_ARRAY_CONSTRUCTOR
-          || !(args->nodeType == TREE_CONST_EXPR
-       && args->v_const.constType == CONST_ARRAY))
- return false;
-
-      /* dive into the list of members of the array. */
-      args = args->v_const.val.aVal;
-    }
-      
-  /* compile the values now */
-  for (i = 0; args; i++, args = args->v_list.next)
-    compile_statement (args->v_list.value);
-
-  /* and send the selector */
-  compile_send (expr, selector->v_const.val.oopVal, i);
-
-  return true;
-#else
-  return false;
-#endif
-}
 
 void
 compile_send (tree_node expr,


--- orig/libgst/dict.c
+++ mod/libgst/dict.c
@@ -64,7 +64,8 @@ typedef struct class_definition
   OOP *classVar;
   OOP *superClassPtr;
   intptr_t instanceSpec;
-  char numFixedFields;
+  mst_Boolean reloadAddress;
+  int numFixedFields;
   const char *name;
   const char *instVarNames;
   const char *classVarNames;
@@ -191,8 +192,10 @@ static ssize_t identity_dictionary_find_
 static size_t identity_dictionary_find_key_or_nil (OOP identityDictionaryOOP,
    OOP keyOOP);
 
-/* Create a new instance of IdentityDictionary and answer it.  */
-static OOP identity_dictionary_new (int size);
+/* Create a new instance of CLASSOOP (an IdentityDictionary subclass)
+   and answer it.  */
+static OOP identity_dictionary_new (OOP classOOP,
+    int size);
 
 /* Create a new instance of Namespace with the given SIZE, NAME and
    superspace (SUPERSPACEOOP).  */
@@ -283,11 +286,11 @@ static const char *feature_strings[] = {
 
 static const class_definition class_info[] = {
   {&_gst_object_class, &_gst_nil_oop,
-   ISP_FIXED, 0,
+   ISP_FIXED, true, 0,
    "Object", NULL, "Dependencies FinalizableObjects", "VMPrimitives" },
 
   {&_gst_object_memory_class, &_gst_object_class,
-   ISP_FIXED, 34,
+   ISP_FIXED, true, 34,
    "ObjectMemory", "bytesPerOOP bytesPerOTE "
    "edenSize survSpaceSize oldSpaceSize fixedSpaceSize "
    "edenUsedBytes survSpaceUsedBytes oldSpaceUsedBytes "
@@ -301,404 +304,396 @@ static const class_definition class_info
    "allocFailures allocMatches allocSplits allocProbes", NULL, NULL },
 
   {&_gst_message_class, &_gst_object_class,
-   ISP_FIXED, 2,
+   ISP_FIXED, true, 2,
    "Message", "selector args", NULL, NULL },
 
   {&_gst_directed_message_class, &_gst_message_class,
-   ISP_FIXED, 1,
+   ISP_FIXED, false, 1,
    "DirectedMessage", "receiver", NULL, NULL },
 
   {&_gst_magnitude_class, &_gst_object_class,
-   ISP_FIXED, 0,
+   ISP_FIXED, false, 0,
    "Magnitude", NULL, NULL, NULL },
 
   {&_gst_char_class, &_gst_magnitude_class,
-   ISP_FIXED, 1,
+   ISP_FIXED, true, 1,
    "Character", "codePoint", "Table UpperTable LowerTable", NULL },
 
   {&_gst_unicode_character_class, &_gst_char_class,
-   ISP_FIXED, 0,
+   ISP_FIXED, true, 0,
    "UnicodeCharacter", NULL, NULL, NULL },
 
   {&_gst_time_class, &_gst_magnitude_class,
-   ISP_FIXED, 1,
+   ISP_FIXED, false, 1,
    "Time", "seconds",
    "SecondClockAdjustment ClockOnStartup", NULL },
 
   {&_gst_date_class, &_gst_magnitude_class,
-   ISP_FIXED, 4,
+   ISP_FIXED, false, 4,
    "Date", "days day month year",
    "DayNameDict MonthNameDict", NULL },
 
   {&_gst_number_class, &_gst_magnitude_class,
-   ISP_FIXED, 0,
+   ISP_FIXED, false, 0,
    "Number", NULL, NULL, NULL },
 
   {&_gst_float_class, &_gst_number_class,
-   ISP_UCHAR, 0,
+   ISP_UCHAR, true, 0,
    "Float", NULL, NULL, "CSymbols" },
 
   {&_gst_floatd_class, &_gst_float_class,
-   ISP_UCHAR, 0,
+   ISP_UCHAR, true, 0,
    "FloatD", NULL, NULL, "CSymbols" },
 
   {&_gst_floate_class, &_gst_float_class,
-   ISP_UCHAR, 0,
+   ISP_UCHAR, true, 0,
    "FloatE", NULL, NULL, "CSymbols" },
 
   {&_gst_floatq_class, &_gst_float_class,
-   ISP_UCHAR, 0,
+   ISP_UCHAR, true, 0,
    "FloatQ", NULL, NULL, "CSymbols" },
 
   {&_gst_fraction_class, &_gst_number_class,
-   ISP_FIXED, 2,
+   ISP_FIXED, false, 2,
    "Fraction", "numerator denominator", "Zero One", NULL },
 
   {&_gst_integer_class, &_gst_number_class,
-   ISP_FIXED, 0,
+   ISP_FIXED, true, 0,
    "Integer", NULL, NULL, "CSymbols" },
 
   {&_gst_small_integer_class, &_gst_integer_class,
-   ISP_FIXED, 0,
+   ISP_FIXED, true, 0,
    "SmallInteger", NULL, NULL, NULL },
 
   {&_gst_large_integer_class, &_gst_integer_class, /* these four
    classes
    added by */
-   ISP_UCHAR, 0, /* pb Sep 10 18:06:49 1998 */
+   ISP_UCHAR, true, 0, /* pb Sep 10 18:06:49 1998 */
    "LargeInteger", NULL,
    "Zero One ZeroBytes OneBytes LeadingZeros TrailingZeros", NULL },
 
   {&_gst_large_positive_integer_class, &_gst_large_integer_class,
-   ISP_UCHAR, 0,
+   ISP_UCHAR, true, 0,
    "LargePositiveInteger", NULL, NULL, NULL },
 
   {&_gst_large_zero_integer_class, &_gst_large_positive_integer_class,
-   ISP_UCHAR, 0,
+   ISP_UCHAR, true, 0,
    "LargeZeroInteger", NULL, NULL, NULL },
 
   {&_gst_large_negative_integer_class, &_gst_large_integer_class,
-   ISP_UCHAR, 0,
+   ISP_UCHAR, true, 0,
    "LargeNegativeInteger", NULL, NULL, NULL },
 
   {&_gst_lookup_key_class, &_gst_magnitude_class,
-   ISP_FIXED, 1,
+   ISP_FIXED, false, 1,
    "LookupKey", "key", NULL, NULL },
 
   {&_gst_association_class, &_gst_lookup_key_class,
-   ISP_FIXED, 1,
+   ISP_FIXED, true, 1,
    "Association", "value", NULL, NULL },
 
   {&_gst_homed_association_class, &_gst_association_class,
-   ISP_FIXED, 1,
+   ISP_FIXED, false, 1,
    "HomedAssociation", "environment", NULL, NULL },
 
   {&_gst_variable_binding_class, &_gst_homed_association_class,
-   ISP_FIXED, 0,
+   ISP_FIXED, true, 0,
    "VariableBinding", NULL, NULL, NULL },
 
   {&_gst_link_class, &_gst_object_class,
-   ISP_FIXED, 1,
+   ISP_FIXED, false, 1,
    "Link", "nextLink", NULL, NULL },
 
   {&_gst_process_class, &_gst_link_class,
-   ISP_FIXED, 7,
+   ISP_FIXED, true, 7,
    "Process",
    "suspendedContext priority myList name unwindPoints interrupts interruptLock",
    NULL, NULL },
 
   {&_gst_callin_process_class, &_gst_process_class,
-   ISP_FIXED, 1,
+   ISP_FIXED, true, 1,
    "CallinProcess",
    "returnedValue",
    NULL, NULL },
 
   {&_gst_sym_link_class, &_gst_link_class,
-   ISP_FIXED, 1,
+   ISP_FIXED, true, 1,
    "SymLink", "symbol", NULL, NULL },
 
   {&_gst_collection_class, &_gst_object_class,
-   ISP_FIXED, 0,
+   ISP_FIXED, false, 0,
    "Collection", NULL, NULL, NULL },
 
   {&_gst_sequenceable_collection_class, &_gst_collection_class,
-   ISP_FIXED, 0,
+   ISP_FIXED, false, 0,
    "SequenceableCollection", NULL, NULL, NULL },
 
   {&_gst_linked_list_class, &_gst_sequenceable_collection_class,
-   ISP_FIXED, 2,
+   ISP_FIXED, false, 2,
    "LinkedList", "firstLink lastLink", NULL, NULL },
 
   {&_gst_semaphore_class, &_gst_linked_list_class,
-   ISP_FIXED, 2,
+   ISP_FIXED, true, 2,
    "Semaphore", "signals name", NULL, NULL },
 
   {&_gst_arrayed_collection_class, &_gst_sequenceable_collection_class,
-   ISP_POINTER, 0,
+   ISP_POINTER, false, 0,
    "ArrayedCollection", NULL, NULL, NULL },
 
   {&_gst_array_class, &_gst_arrayed_collection_class,
-   ISP_POINTER, 0,
+   ISP_POINTER, true, 0,
    "Array", NULL, NULL, NULL },
 
   {&_gst_character_array_class, &_gst_arrayed_collection_class,
-   ISP_ULONG, 0,
+   ISP_ULONG, false, 0,
    "CharacterArray", NULL, NULL, NULL },
 
   {&_gst_string_class, &_gst_character_array_class,
-   ISP_CHARACTER, 0,
+   ISP_CHARACTER, true, 0,
    "String", NULL, NULL, NULL },
 
   {&_gst_unicode_string_class, &_gst_character_array_class,
-   ISP_UTF32, 0,
+   ISP_UTF32, true, 0,
    "UnicodeString", NULL, NULL, NULL },
 
   {&_gst_symbol_class, &_gst_string_class,
-   ISP_CHARACTER, 0,
+   ISP_CHARACTER, true, 0,
    "Symbol", NULL, NULL, NULL },
 
   {&_gst_byte_array_class, &_gst_arrayed_collection_class,
-   ISP_UCHAR, 0,
+   ISP_UCHAR, true, 0,
    "ByteArray", NULL, NULL, "CSymbols" },
 
   {&_gst_compiled_code_class, &_gst_arrayed_collection_class,
-   ISP_UCHAR, 2,
+   ISP_UCHAR, false, 2,
    "CompiledCode", "literals header",
    NULL, NULL },
 
   {&_gst_compiled_block_class, &_gst_compiled_code_class,
-   ISP_UCHAR, 1,
+   ISP_UCHAR, true, 1,
    "CompiledBlock", "method",
    NULL, NULL },
 
   {&_gst_compiled_method_class, &_gst_compiled_code_class,
-   ISP_UCHAR, 1,
+   ISP_UCHAR, true, 1,
    "CompiledMethod", "descriptor ",
    NULL, NULL },
 
   {&_gst_interval_class, &_gst_arrayed_collection_class,
-   ISP_FIXED, 3,
+   ISP_FIXED, true, 3,
    "Interval", "start stop step", NULL, NULL },
 
   {&_gst_ordered_collection_class, &_gst_sequenceable_collection_class,
-   ISP_POINTER, 2,
+   ISP_POINTER, false, 2,
    "OrderedCollection", "firstIndex lastIndex", NULL, NULL },
 
   {&_gst_sorted_collection_class, &_gst_ordered_collection_class,
-   ISP_POINTER, 3,
+   ISP_POINTER, false, 3,
    "SortedCollection", "lastOrdered sorted sortBlock",
    "DefaultSortBlock",
    NULL },
 
   {&_gst_bag_class, &_gst_collection_class,
-   ISP_FIXED, 1,
+   ISP_FIXED, false, 1,
    "Bag", "contents", NULL, NULL },
 
   {&_gst_mapped_collection_class, &_gst_collection_class,
-   ISP_FIXED, 2,
+   ISP_FIXED, false, 2,
    "MappedCollection", "domain map", NULL, NULL },
 
   {&_gst_hashed_collection_class, &_gst_collection_class,
-   ISP_POINTER, 1,
+   ISP_POINTER, false, 1,
    "HashedCollection", "tally", NULL, NULL },
 
   {&_gst_set_class, &_gst_hashed_collection_class,
-   ISP_POINTER, 0,
+   ISP_POINTER, false, 0,
    "Set", NULL, NULL, NULL },
 
   {&_gst_identity_set_class, &_gst_set_class,
-   ISP_POINTER, 0,
+   ISP_POINTER, false, 0,
    "IdentitySet", NULL, NULL, NULL },
 
   {&_gst_dictionary_class, &_gst_hashed_collection_class,
-   ISP_POINTER, 0,
+   ISP_POINTER, true, 0,
    "Dictionary", NULL, NULL, NULL },
 
   {&_gst_lookup_table_class, &_gst_dictionary_class,
-   ISP_POINTER, 0,
+   ISP_POINTER, false, 0,
    "LookupTable", NULL, NULL, NULL },
 
   {&_gst_identity_dictionary_class, &_gst_lookup_table_class,
-   ISP_POINTER, 0,
+   ISP_POINTER, false, 0,
    "IdentityDictionary", NULL, NULL, NULL },
 
   {&_gst_method_dictionary_class, &_gst_lookup_table_class,
-   ISP_POINTER, 0,
+   ISP_POINTER, true, 0,
    "MethodDictionary", NULL, NULL, NULL },
 
   /* These five MUST have the same structure as dictionary; they're
      used interchangeably within the C portion of the system */
   {&_gst_binding_dictionary_class, &_gst_dictionary_class,
-   ISP_POINTER, 1,
+   ISP_POINTER, false, 1,
    "BindingDictionary", "environment", NULL, NULL },
 
   {&_gst_abstract_namespace_class, &_gst_binding_dictionary_class,
-   ISP_POINTER, 2,
+   ISP_POINTER, true, 2,
    "AbstractNamespace", "name subspaces", NULL, NULL },
 
   {&_gst_root_namespace_class, &_gst_abstract_namespace_class,
-   ISP_POINTER, 0,
+   ISP_POINTER, false, 0,
    "RootNamespace", NULL, NULL, NULL },
 
   {&_gst_namespace_class, &_gst_abstract_namespace_class,
-   ISP_POINTER, 0,
+   ISP_POINTER, true, 0,
    "Namespace", NULL, "Current", NULL },
 
   {&_gst_system_dictionary_class, &_gst_root_namespace_class,
-   ISP_POINTER, 0,
+   ISP_POINTER, false, 0,
    "SystemDictionary", NULL, NULL, NULL },
 
   {&_gst_stream_class, &_gst_object_class,
-   ISP_FIXED, 0,
+   ISP_FIXED, false, 0,
    "Stream", NULL, NULL, NULL },
 
   {&_gst_token_stream_class, &_gst_stream_class,
-   ISP_FIXED, 1,
+   ISP_FIXED, false, 1,
    "TokenStream", "charStream", NULL, NULL },
 
   {&_gst_positionable_stream_class, &_gst_stream_class,
-   ISP_FIXED, 4,
+   ISP_FIXED, false, 4,
    "PositionableStream", "collection ptr endPtr access", NULL, NULL },
 
   {&_gst_read_stream_class, &_gst_positionable_stream_class,
-   ISP_FIXED, 0,
+   ISP_FIXED, false, 0,
    "ReadStream", NULL, NULL, NULL },
 
   {&_gst_write_stream_class, &_gst_positionable_stream_class,
-   ISP_FIXED, 0,
+   ISP_FIXED, false, 0,
    "WriteStream", NULL, NULL, NULL },
 
   {&_gst_read_write_stream_class, &_gst_write_stream_class,
-   ISP_FIXED, 0,
+   ISP_FIXED, false, 0,
    "ReadWriteStream", NULL, NULL, NULL },
 
   {&_gst_byte_stream_class, &_gst_read_write_stream_class,
-   ISP_FIXED, 0,
+   ISP_FIXED, false, 0,
    "ByteStream", NULL, NULL, NULL },
 
   {&_gst_file_descriptor_class, &_gst_byte_stream_class,
-   ISP_FIXED, 5,
+   ISP_FIXED, true, 5,
    "FileDescriptor", "file name isPipe atEnd peek", NULL, NULL },
 
   {&_gst_file_stream_class, &_gst_file_descriptor_class,
-   ISP_FIXED, 2,
+   ISP_FIXED, true, 2,
    "FileStream", "writePtr writeEnd", "Verbose Record Includes", NULL },
 
   {&_gst_random_class, &_gst_stream_class,
-   ISP_FIXED, 1,
+   ISP_FIXED, false, 1,
    "Random", "seed", "Source", NULL },
 
   {&_gst_undefined_object_class, &_gst_object_class,
-   ISP_FIXED, 0,
+   ISP_FIXED, true, 0,
    "UndefinedObject", NULL, NULL, NULL },
 
   {&_gst_boolean_class, &_gst_object_class,
-   ISP_FIXED, 0,
+   ISP_FIXED, true, 0,
    "Boolean", NULL, NULL, NULL },
 
   {&_gst_false_class, &_gst_boolean_class,
-   ISP_FIXED, 1,
+   ISP_FIXED, true, 1,
    "False", "truthValue", NULL, NULL },
 
   {&_gst_true_class, &_gst_boolean_class,
-   ISP_FIXED, 1,
+   ISP_FIXED, true, 1,
    "True", "truthValue", NULL, NULL },
 
   {&_gst_processor_scheduler_class, &_gst_object_class,
-   ISP_FIXED, 6,
+   ISP_FIXED, false, 6,
    "ProcessorScheduler",
    "processLists activeProcess idleTasks processTimeslice gcSemaphore gcArray",
    NULL, NULL },
 
   {&_gst_delay_class, &_gst_object_class,
-   ISP_FIXED, 2,
+   ISP_FIXED, false, 2,
    "Delay", "resumptionTime isRelative",
    "Queue TimeoutSem MutexSem DelayProcess IdleProcess", NULL },
 
   {&_gst_shared_queue_class, &_gst_object_class,
-   ISP_FIXED, 3,
+   ISP_FIXED, false, 3,
    "SharedQueue", "queueSem valueReady queue", NULL, NULL },
 
   /* Change this, classDescription, or gst_class, and you must change
      the implementaion of new_metaclass some */
   {&_gst_behavior_class, &_gst_object_class,
-   ISP_FIXED, 5,
+   ISP_FIXED, true, 5,
    "Behavior",
    "superClass subClasses methodDictionary instanceSpec instanceVariables",
    NULL, NULL },
 
   {&_gst_class_description_class, &_gst_behavior_class,
-   ISP_FIXED, 0,
+   ISP_FIXED, true, 0,
    "ClassDescription", NULL, NULL, NULL },
 
   {&_gst_class_class, &_gst_class_description_class,
-   ISP_FIXED, 8,
+   ISP_FIXED, true, 8,
    "Class",
    "name comment category environment classVariables sharedPools "
    "securityPolicy pragmaHandlers",
    NULL, NULL },
 
   {&_gst_metaclass_class, &_gst_class_description_class,
-   ISP_FIXED, 1,
+   ISP_FIXED, true, 1,
    "Metaclass", "instanceClass", NULL, NULL },
 
   {&_gst_context_part_class, &_gst_object_class,
-   ISP_POINTER, 6,
+   ISP_POINTER, true, 6,
    "ContextPart", "parent nativeIP ip sp receiver method ",
    "UnwindPoints", NULL },
 
   {&_gst_method_context_class, &_gst_context_part_class,
-   ISP_POINTER, 1,
+   ISP_POINTER, true, 1,
    "MethodContext", "flags ", NULL, NULL },
 
   {&_gst_block_context_class, &_gst_context_part_class,
-   ISP_POINTER, 1,
+   ISP_POINTER, true, 1,
    "BlockContext", "outerContext ", NULL, NULL },
 
   {&_gst_block_closure_class, &_gst_object_class,
-   ISP_FIXED, 3,
+   ISP_FIXED, true, 3,
    "BlockClosure", "outerContext block receiver", NULL, NULL },
 
-
-/***********************************************************************
- *
- * End of Standard Smalltalk Class definitions.  The definitions below are
- * specific to GNU Smalltalk.
- *
- ***********************************************************************/
-
   {&_gst_permission_class, &_gst_object_class,
-   ISP_FIXED, 4,
+   ISP_FIXED, true, 4,
    "Permission", "name actions target positive", NULL, NULL },
 
   {&_gst_security_policy_class, &_gst_object_class,
-   ISP_FIXED, 2,
+   ISP_FIXED, true, 2,
    "SecurityPolicy", "dictionary owner", NULL, NULL },
 
   {&_gst_c_object_class, &_gst_object_class,
-   ISP_ULONG, 1, /* leave this this way */
+   ISP_ULONG, true, 1, /* leave this this way */
    "CObject", "type", NULL, "CSymbols" },
 
   {&_gst_c_type_class, &_gst_object_class,
-   ISP_FIXED, 1,
+   ISP_FIXED, true, 1,
    "CType", "cObjectType", NULL, NULL },
 
   {&_gst_c_func_descriptor_class, &_gst_object_class,
-   ISP_POINTER, 4,
+   ISP_POINTER, true, 4,
    "CFunctionDescriptor",
    "cFunction cFunctionName returnType numFixedArgs",
    NULL, NULL },
 
   {&_gst_memory_class, &_gst_object_class,
-   ISP_FIXED, 0,
+   ISP_FIXED, false, 0,
    "Memory", NULL, NULL, NULL },
 
   {&_gst_method_info_class, &_gst_object_class,
-   ISP_POINTER, 4,
+   ISP_POINTER, true, 4,
    "MethodInfo", "sourceCode category class selector", NULL, NULL },
 
   {&_gst_file_segment_class, &_gst_object_class,
-   ISP_FIXED, 3,
+   ISP_FIXED, true, 3,
    "FileSegment", "file startPos size", NULL, NULL }
 
 /* Classes not defined here (like Point/Rectangle/RunArray) are
@@ -749,7 +744,7 @@ init_proto_oops()
 
   smalltalkDictionary->objClass = _gst_system_dictionary_class;
   smalltalkDictionary->tally = FROM_INT(0);
-  smalltalkDictionary->name = _gst_intern_string ("Smalltalk");
+  smalltalkDictionary->name = _gst_smalltalk_namespace_symbol;
   smalltalkDictionary->superspace = _gst_nil_oop;
   smalltalkDictionary->subspaces = _gst_nil_oop;
   nil_fill (smalltalkDictionary->assoc,
@@ -776,9 +771,12 @@ _gst_init_dictionary (void)
   _gst_processor_oop = alloc_oop (NULL, _gst_mem.active_flag);
   _gst_symbol_table = alloc_oop (NULL, _gst_mem.active_flag);
 
+  _gst_init_symbols_pass1 ();
+
   create_classes_pass1 (class_info, sizeof (class_info) / sizeof (class_info[0]));
 
   init_proto_oops();
+  _gst_init_symbols_pass2 ();
   init_smalltalk_dictionary ();
 
   create_classes_pass2 (class_info, sizeof (class_info) / sizeof (class_info[0]));
@@ -787,7 +785,6 @@ _gst_init_dictionary (void)
  _gst_string_new (_gst_kernel_file_path));
 
   init_runtime_objects ();
-
   _gst_tenure_all_survivors ();
 }
 
@@ -998,8 +995,6 @@ init_smalltalk_dictionary (void)
   add_smalltalk ("Processor", _gst_processor_oop);
   add_smalltalk ("Features", featuresArrayOOP);
 
-  _gst_init_symbols ();
-
   /* Add subspaces */
   add_smalltalk ("CSymbols",
     namespace_new (32, "CSymbols", _gst_smalltalk_dictionary));
@@ -1240,27 +1235,27 @@ _gst_init_dictionary_on_image_load (size
       || IS_NIL (_gst_smalltalk_dictionary))
     return (false);
 
+  _gst_restore_symbols ();
+
   for (ci = class_info;
        ci < class_info + sizeof(class_info) / sizeof(class_definition);
        ci++)
-    {
-      *ci->classVar = dictionary_at (_gst_smalltalk_dictionary,
-     _gst_intern_string (ci->name));
-      if UNCOMMON (IS_NIL (*ci->classVar))
- return (false);
-    }
+    if (ci->reloadAddress)
+      {
+ *ci->classVar = dictionary_at (_gst_smalltalk_dictionary,
+       _gst_intern_string (ci->name));
+        if UNCOMMON (IS_NIL (*ci->classVar))
+  return (false);
+      }
 
   _gst_current_namespace =
-    dictionary_at (_gst_class_variable_dictionary
-   (_gst_namespace_class),
+    dictionary_at (_gst_class_variable_dictionary (_gst_namespace_class),
    _gst_intern_string ("Current"));
 
   _gst_c_object_type_ctype = dictionary_at (_gst_smalltalk_dictionary,
-    _gst_intern_string
-    ("CObjectType"));
+    _gst_intern_string ("CObjectType"));
 
   _gst_init_builtin_objects_classes ();
-  _gst_init_symbols ();
 
   /* Important: this is called *after* _gst_init_symbols
      fills in _gst_vm_primitives_symbol! */
@@ -1342,9 +1337,8 @@ _gst_valid_class_method_dictionary (OOP
     {
       OOP identDict;
       gst_object obj;
-      identDict = identity_dictionary_new (32);
+      identDict = identity_dictionary_new (_gst_method_dictionary_class, 32);
       obj = OOP_TO_OBJ (identDict);
-      obj->objClass = _gst_method_dictionary_class;
       class = (gst_class) OOP_TO_OBJ (class_oop);
       class->methodDictionary = identDict;
     }
@@ -1648,7 +1642,7 @@ identity_dictionary_find_key_or_nil (OOP
 }
 
 OOP
-identity_dictionary_new (int size)
+identity_dictionary_new (OOP classOOP, int size)
 {
   gst_identity_dictionary identityDictionary;
   OOP identityDictionaryOOP;
@@ -1656,8 +1650,7 @@ identity_dictionary_new (int size)
   size = new_num_fields (size);
 
   identityDictionary = (gst_identity_dictionary)
-    instantiate_with (_gst_identity_dictionary_class, size * 2,
-      &identityDictionaryOOP);
+    instantiate_with (classOOP, size * 2, &identityDictionaryOOP);
 
   identityDictionary->tally = FROM_INT (0);
   return (identityDictionaryOOP);
@@ -2022,24 +2015,6 @@ _gst_message_new_args (OOP selectorOOP,
 }
 
 OOP
-_gst_directed_message_new_args (OOP receiverOOP,
- OOP selectorOOP,
-        OOP argsArray)
-{
-  gst_directed_message dirMessage;
-  OOP dirMessageOOP;
-
-  dirMessage = (gst_directed_message) new_instance (_gst_directed_message_class,
-    &dirMessageOOP);
-
-  dirMessage->selector = selectorOOP;
-  dirMessage->args = argsArray;
-  dirMessage->receiver = receiverOOP;
-
-  return (dirMessageOOP);
-}
-
-OOP
 _gst_c_object_new_typed (PTR cObjPtr,
  OOP typeOOP)
 {


--- orig/libgst/dict.h
+++ mod/libgst/dict.h
@@ -466,13 +466,6 @@ extern OOP _gst_message_new_args (OOP se
   OOP argsArray)
   ATTRIBUTE_HIDDEN;
 
-/* Create a new DirectedMessage object for the given RECEIVER,
-   SELECTOR (a Symbol) and Array of arguments.  */
-extern OOP _gst_directed_message_new_args (OOP receiverOOP,
-   OOP selectorOOP,
-   OOP argsArray)
-  ATTRIBUTE_HIDDEN;
-
 /* Returns the name of CLASS_OOP (a Smalltalk Class) */
 extern OOP _gst_get_class_symbol (OOP class_oop)
   ATTRIBUTE_PURE


--- orig/libgst/genvm-parse.y
+++ mod/libgst/genvm-parse.y
@@ -91,7 +91,7 @@ typedef struct table_info {
 #define YYPRINT(fp, tok, val) yyprint (fp, tok, &val)
 
 static int filprintf (Filament *fil, const char *format, ...);
-static void yyprint (FILE *fp, int tok, YYSTYPE *val);
+static void yyprint (FILE *fp, int tok, const YYSTYPE *val);
 static void yyerror (const char *s);
 static operation_info *define_operation (const char *name);
 static void set_curr_op_stack (id_list *in, id_list *out);
@@ -297,7 +297,7 @@ c_code: c_code EXPR
 
 %%
 
-void yyprint (FILE *fp, int tok, YYSTYPE *val)
+void yyprint (FILE *fp, int tok, const YYSTYPE *val)
 {
   switch (tok)
     {


--- orig/libgst/interp.c
+++ mod/libgst/interp.c
@@ -2128,25 +2128,6 @@ _gst_nvmsg_send (OOP receiver,
   currentProcessOOP = get_active_process ();
   change_process_context (processOOP);
 
-#if 0
-  if (_gst_kernel_initialized)
-    {
-      gst_array argsArray;
-      OOP argsArrayOOP;
-      argsArray = new_instance_with (_gst_array_class, numArgs, &argsArrayOOP);
-      for (i = 0; i < sendArgs; i++)
-        argsArray->data[i] = args[i];
-
-      INC_ADD_OOP (argsArrayOOP);
-      dirMessageOOP = _gst_directed_message_new_args (receiver, sendSelector, argsArrayOOP);
-
-      receiver = _gst_process_class;
-      sendSelector = _gst_start_execution_symbol;
-      sendArgs = 1;
-      args = &dirMessageOOP;
-    }
-#endif
-
   PUSH_OOP (receiver);
   for (i = 0; i < sendArgs; i++)
     PUSH_OOP (args[i]);


--- orig/libgst/opt.c
+++ mod/libgst/opt.c
@@ -936,15 +936,15 @@ _gst_compute_stack_positions (gst_uchar
     }
 
     SEND_ARITH {
-      balance -= _gst_builtin_selectors[n]->numArgs;
+      balance -= _gst_builtin_selectors[n].numArgs;
     }
 
     SEND_IMMEDIATE {
-      balance -= super + _gst_builtin_selectors[n]->numArgs;
+      balance -= super + _gst_builtin_selectors[n].numArgs;
     }
 
             SEND_SPECIAL {
-      balance -= _gst_builtin_selectors[n + 16]->numArgs;
+      balance -= _gst_builtin_selectors[n + 16].numArgs;
     }
 
             INVALID {
@@ -1392,10 +1392,10 @@ _gst_verify_method (OOP methodOOP, int *
     }
 
     SEND_ARITH {
-      if (!_gst_builtin_selectors[n])
+      if (!_gst_builtin_selectors[n].symbol)
  return ("invalid immediate send");
 
-      balance -= _gst_builtin_selectors[n]->numArgs;
+      balance -= _gst_builtin_selectors[n].numArgs;
 
       /* Sends touch the new stack top, so they require an extra slot.  */
       if (curr_sp + balance < 1)
@@ -1403,10 +1403,10 @@ _gst_verify_method (OOP methodOOP, int *
     }
 
             SEND_SPECIAL {
-      if (!_gst_builtin_selectors[n + 16])
+      if (!_gst_builtin_selectors[n + 16].symbol)
  return ("invalid immediate send");
 
-      balance -= _gst_builtin_selectors[n + 16]->numArgs;
+      balance -= _gst_builtin_selectors[n + 16].numArgs;
 
       /* Sends touch the new stack top, so they require an extra slot.  */
       if (curr_sp + balance < 1)
@@ -1414,10 +1414,10 @@ _gst_verify_method (OOP methodOOP, int *
     }
 
             SEND_IMMEDIATE {
-      if (!_gst_builtin_selectors[n])
+      if (!_gst_builtin_selectors[n].symbol)
  return ("invalid immediate send");
 
-      balance -= super + _gst_builtin_selectors[n]->numArgs;
+      balance -= super + _gst_builtin_selectors[n].numArgs;
 
       /* Sends touch the new stack top, so they require an extra slot.  */
       if (curr_sp + balance < 1)
@@ -1726,11 +1726,11 @@ _gst_verify_method (OOP methodOOP, int *
     }
 
     SEND_ARITH {
-      sp -= _gst_builtin_selectors[n]->numArgs;
+      sp -= _gst_builtin_selectors[n].numArgs;
       sp[-1] = FROM_INT (VARYING);
     }
     SEND_SPECIAL {
-      sp -= _gst_builtin_selectors[n + 16]->numArgs;
+      sp -= _gst_builtin_selectors[n + 16].numArgs;
       sp[-1] = FROM_INT (VARYING);
     }
 
@@ -1769,7 +1769,7 @@ _gst_verify_method (OOP methodOOP, int *
     return (_gst_debug (), "Invalid send to super");
 
   last_used_literal = NULL;
-          sp -= super + _gst_builtin_selectors[n]->numArgs;
+          sp -= super + _gst_builtin_selectors[n].numArgs;
           if (super && sp[-1] != FROM_INT (SELF))
     return ("Invalid send to super");
 


--- orig/libgst/sym.c
+++ mod/libgst/sym.c
@@ -94,65 +94,41 @@ typedef struct symbol_info
 symbol_info;
 
 
+/* These variables hold various symbols needed mostly by the compiler
+   and the C interface.  It is important that these symbols are *not*
+   included in the builtin selectors list (builtins.gperf) because
+   of the way we create symbols in _gst_init_symbols_pass1.  */
+
 OOP _gst_and_symbol = NULL;
 OOP _gst_as_scaled_decimal_scale_symbol = NULL;
-OOP _gst_at_put_symbol = NULL;
-OOP _gst_at_symbol = NULL;
 OOP _gst_bad_return_error_symbol = NULL;
-OOP _gst_bit_and_symbol = NULL;
-OOP _gst_bit_or_symbol = NULL;
-OOP _gst_bit_shift_symbol = NULL;
-OOP _gst_bit_xor_symbol = NULL;
 OOP _gst_boolean_symbol = NULL;
 OOP _gst_byte_array_out_symbol = NULL;
 OOP _gst_byte_array_symbol = NULL;
 OOP _gst_c_object_ptr_symbol = NULL;
 OOP _gst_c_object_symbol = NULL;
 OOP _gst_char_symbol = NULL;
-OOP _gst_class_symbol = NULL;
-OOP _gst_divide_symbol = NULL;
 OOP _gst_does_not_understand_symbol = NULL;
 OOP _gst_double_symbol = NULL;
-OOP _gst_equal_symbol = NULL;
 OOP _gst_false_symbol = NULL;
 OOP _gst_float_symbol = NULL;
-OOP _gst_greater_equal_symbol = NULL;
-OOP _gst_greater_than_symbol = NULL;
 OOP _gst_if_false_if_true_symbol = NULL;
 OOP _gst_if_false_symbol = NULL;
 OOP _gst_if_true_if_false_symbol = NULL;
 OOP _gst_if_true_symbol = NULL;
 OOP _gst_int_symbol = NULL;
-OOP _gst_integer_divide_symbol = NULL;
-OOP _gst_is_nil_symbol = NULL;
-OOP _gst_java_as_int_symbol = NULL;
-OOP _gst_java_as_long_symbol = NULL;
-OOP _gst_less_equal_symbol = NULL;
-OOP _gst_less_than_symbol = NULL;
 OOP _gst_long_double_symbol = NULL;
 OOP _gst_long_symbol = NULL;
-OOP _gst_minus_symbol = NULL;
 OOP _gst_must_be_boolean_symbol = NULL;
-OOP _gst_new_colon_symbol = NULL;
 OOP _gst_nil_symbol = NULL;
-OOP _gst_not_equal_symbol = NULL;
-OOP _gst_not_nil_symbol = NULL;
 OOP _gst_or_symbol = NULL;
-OOP _gst_perform_symbol = NULL;
-OOP _gst_perform_with_symbol = NULL;
-OOP _gst_perform_with_with_symbol = NULL;
-OOP _gst_perform_with_with_with_symbol = NULL;
-OOP _gst_perform_with_arguments_symbol = NULL;
 OOP _gst_permission_symbol = NULL;
-OOP _gst_plus_symbol = NULL;
 OOP _gst_primitive_symbol = NULL;
-OOP _gst_remainder_symbol = NULL;
 OOP _gst_repeat_symbol = NULL;
-OOP _gst_same_object_symbol = NULL;
 OOP _gst_self_smalltalk_symbol = NULL;
 OOP _gst_self_symbol = NULL;
-OOP _gst_size_symbol = NULL;
 OOP _gst_smalltalk_symbol = NULL;
+OOP _gst_smalltalk_namespace_symbol = NULL;
 OOP _gst_start_execution_symbol = NULL;
 OOP _gst_string_out_symbol = NULL;
 OOP _gst_string_symbol = NULL;
@@ -161,9 +137,7 @@ OOP _gst_symbol_symbol = NULL;
 OOP _gst_symbol_out_symbol = NULL;
 OOP _gst_symbol_table = NULL;
 OOP _gst_terminate_symbol = NULL;
-OOP _gst_this_context_symbol = NULL;
 OOP _gst_times_repeat_symbol = NULL;
-OOP _gst_times_symbol = NULL;
 OOP _gst_to_by_do_symbol = NULL;
 OOP _gst_to_do_symbol = NULL;
 OOP _gst_true_symbol = NULL;
@@ -171,8 +145,6 @@ OOP _gst_uint_symbol = NULL;
 OOP _gst_ulong_symbol = NULL;
 OOP _gst_undeclared_symbol = NULL;
 OOP _gst_unknown_symbol = NULL;
-OOP _gst_value_colon_symbol = NULL;
-OOP _gst_value_symbol = NULL;
 OOP _gst_value_with_rec_with_args_symbol = NULL;
 OOP _gst_variadic_smalltalk_symbol = NULL;
 OOP _gst_variadic_symbol = NULL;
@@ -188,7 +160,7 @@ OOP _gst_while_true_symbol = NULL;
 OOP _gst_current_namespace = NULL;
 
 /* The list of selectors for the send immediate bytecode.  */
-struct builtin_selector *_gst_builtin_selectors[256] = {};
+struct builtin_selector _gst_builtin_selectors[256] = {};
 
 /* True if undeclared globals can be considered forward references.  */
 int _gst_use_undeclared = 0;
@@ -200,6 +172,15 @@ static mst_Boolean is_same_string (const
    OOP oop,
    int len);
 
+/* Allocate memory for a symbol of length LEN and whose contents are STR.
+   This function does not fill in the object's class because it is called
+   upon image loading, when the classes have not been initialized yet.  */
+static OOP alloc_symbol_oop (const char *str, int len);
+
+/* Link SYMBOLOOP into the symbol table (using the given hash table index),
+   and fill the class slot of the symbol.  */
+static OOP alloc_symlink (OOP symbolOOP, uintptr_t index);
+
 /* Answer whether C is considered a white space character in Smalltalk
    programs.  */
 static mst_Boolean is_white_space (char c);
@@ -268,64 +249,35 @@ static scope cur_scope = NULL;
 static const symbol_info sym_info[] = {
   {&_gst_and_symbol, "and:"},
   {&_gst_as_scaled_decimal_scale_symbol, "asScaledDecimal:scale:"},
-  {&_gst_at_put_symbol, "at:put:"},
-  {&_gst_at_symbol, "at:"},
   {&_gst_bad_return_error_symbol, "badReturnError"},
-  {&_gst_bit_and_symbol, "bitAnd:"},
-  {&_gst_bit_or_symbol, "bitOr:"},
-  {&_gst_bit_xor_symbol, "bitXor:"},
-  {&_gst_bit_shift_symbol, "bitShift:"},
   {&_gst_byte_array_symbol, "byteArray"},
   {&_gst_byte_array_out_symbol, "byteArrayOut"},
   {&_gst_boolean_symbol, "boolean"},
   {&_gst_char_symbol, "char"},
-  {&_gst_class_symbol, "class"},
   {&_gst_c_object_symbol, "cObject"},
   {&_gst_c_object_ptr_symbol, "cObjectPtr"},
-  {&_gst_divide_symbol, "/"},
   {&_gst_does_not_understand_symbol, "doesNotUnderstand:"},
   {&_gst_float_symbol, "float"},
   {&_gst_double_symbol, "double"},
-  {&_gst_equal_symbol, "="},
   {&_gst_false_symbol, "false"},
-  {&_gst_greater_equal_symbol, ">="},
-  {&_gst_greater_than_symbol, ">"},
   {&_gst_if_false_if_true_symbol, "ifFalse:ifTrue:"},
   {&_gst_if_false_symbol, "ifFalse:"},
   {&_gst_if_true_if_false_symbol, "ifTrue:ifFalse:"},
   {&_gst_if_true_symbol, "ifTrue:"},
-  {&_gst_integer_divide_symbol, "//"},
   {&_gst_int_symbol, "int"},
   {&_gst_uint_symbol, "uInt"},
-  {&_gst_is_nil_symbol, "isNil"},
-  {&_gst_java_as_int_symbol, "javaAsInt"},
-  {&_gst_java_as_long_symbol, "javaAsLong"},
-  {&_gst_less_equal_symbol, "<="},
-  {&_gst_less_than_symbol, "<"},
   {&_gst_long_double_symbol, "longDouble"},
   {&_gst_long_symbol, "long"},
   {&_gst_ulong_symbol, "uLong"},
-  {&_gst_minus_symbol, "-"},
   {&_gst_must_be_boolean_symbol, "mustBeBoolean"},
-  {&_gst_new_colon_symbol, "new:"},
   {&_gst_nil_symbol, "nil"},
-  {&_gst_not_equal_symbol, "~="},
-  {&_gst_not_nil_symbol, "notNil"},
   {&_gst_or_symbol, "or:"},
-  {&_gst_perform_symbol, "perform:"},
-  {&_gst_perform_with_symbol, "perform:with:"},
-  {&_gst_perform_with_with_symbol, "perform:with:with:"},
-  {&_gst_perform_with_with_with_symbol, "perform:with:with:with:"},
-  {&_gst_perform_with_arguments_symbol, "perform:withArguments:"},
-  {&_gst_plus_symbol, "+"},
   {&_gst_primitive_symbol, "primitive:"},
-  {&_gst_remainder_symbol, "\\\\"},
   {&_gst_repeat_symbol, "repeat"},
-  {&_gst_same_object_symbol, "=="},
   {&_gst_self_symbol, "self"},
   {&_gst_self_smalltalk_symbol, "selfSmalltalk"},
-  {&_gst_size_symbol, "size"},
   {&_gst_smalltalk_symbol, "smalltalk"},
+  {&_gst_smalltalk_namespace_symbol, "Smalltalk"},
   {&_gst_start_execution_symbol, "startExecution:"},
   {&_gst_string_out_symbol, "stringOut"},
   {&_gst_string_symbol, "string"},
@@ -333,18 +285,13 @@ static const symbol_info sym_info[] = {
   {&_gst_symbol_symbol, "symbol"},
   {&_gst_symbol_out_symbol, "symbolOut"},
   {&_gst_terminate_symbol, "__terminate"},
-  {&_gst_this_context_symbol, "thisContext"},
-  {&_gst_times_symbol, "*"},
   {&_gst_times_repeat_symbol, "timesRepeat:"},
   {&_gst_to_by_do_symbol, "to:by:do:"},
   {&_gst_to_do_symbol, "to:do:"},
   {&_gst_true_symbol, "true"},
   {&_gst_undeclared_symbol, "Undeclared"},
   {&_gst_unknown_symbol, "unknown"},
-  {&_gst_value_colon_symbol, "value:"},
-  {&_gst_value_with_rec_with_args_symbol,
-   "valueWithReceiver:withArguments:"},
-  {&_gst_value_symbol, "value"},
+  {&_gst_value_with_rec_with_args_symbol, "valueWithReceiver:withArguments:"},
   {&_gst_variadic_symbol, "variadic"},
   {&_gst_variadic_smalltalk_symbol, "variadicSmalltalk"},
   {&_gst_vm_primitives_symbol, "VMPrimitives"},
@@ -659,7 +606,7 @@ _gst_find_variable (symbol_entry * se,
       fill_symbol_entry (se, SCOPE_SPECIAL, true, symbol, NIL_INDEX, 0);
       return (true);
     }
-  else if (symbol == _gst_this_context_symbol)
+  else if (symbol == _gst_builtin_selectors[THIS_CONTEXT_SPECIAL].symbol)
     {
       fill_symbol_entry (se, SCOPE_SPECIAL, true, symbol,
  THIS_CONTEXT_INDEX, 0);
@@ -1070,19 +1017,41 @@ _gst_intern_string (const char *str)
   return (intern_counted_string (str, len));
 }
 
+static uintptr_t
+hash_symbol (const char *str, int len)
+{
+  uintptr_t index = scramble (_gst_hash_string (str, len));
+  return (index & (SYMBOL_TABLE_SIZE - 1)) + 1;
+}
+
+static OOP
+alloc_symlink (OOP symbolOOP, uintptr_t index)
+{
+  gst_symbol symbol;
+  sym_link link;
+  OOP linkOOP;
+
+  symbol = (gst_symbol) OOP_TO_OBJ (symbolOOP);
+  symbol->objClass = _gst_symbol_class;
+
+  link = (sym_link) new_instance (_gst_sym_link_class, &linkOOP);
+  link->nextLink = ARRAY_AT (_gst_symbol_table, index);
+  link->symbol = symbolOOP;
+  ARRAY_AT_PUT (_gst_symbol_table, index, linkOOP);
+
+  return (symbolOOP);
+}
+
 static OOP
 intern_counted_string (const char *str,
        int len)
 {
   uintptr_t index;
-  sym_link link;
-  gst_symbol symbol;
   OOP symbolOOP, linkOOP;
+  sym_link link;
   inc_ptr incPtr;
 
-  index = scramble (_gst_hash_string (str, len));
-  index = (index & (SYMBOL_TABLE_SIZE - 1)) + 1;
-
+  index = hash_symbol (str, len);
   for (linkOOP = ARRAY_AT (_gst_symbol_table, index); !IS_NIL (linkOOP);
        linkOOP = link->nextLink)
     {
@@ -1097,22 +1066,31 @@ intern_counted_string (const char *str,
 #endif
 
   incPtr = INC_SAVE_POINTER ();
-  symbol = (gst_symbol) new_instance_with (_gst_symbol_class,
-   len, &symbolOOP);
-
-  memcpy (symbol->symString, str, len);
-  symbolOOP->flags |= F_READONLY;
+  symbolOOP = alloc_symbol_oop (str, len);
   INC_ADD_OOP (symbolOOP);
 
-  link = (sym_link) new_instance (_gst_sym_link_class, &linkOOP);
-  link->nextLink = ARRAY_AT (_gst_symbol_table, index);
-  link->symbol = symbolOOP;
-  ARRAY_AT_PUT (_gst_symbol_table, index, linkOOP);
-
+  alloc_symlink (symbolOOP, index);
   INC_RESTORE_POINTER (incPtr);
+
   return (symbolOOP);
 }
 
+static OOP
+alloc_symbol_oop (const char *str, int len)
+{
+  int numBytes, alignedBytes;
+  gst_symbol symbol;
+  OOP symbolOOP;
+
+  numBytes = sizeof(gst_object_header) + len;
+  alignedBytes = ROUNDED_BYTES (numBytes);
+  symbol = (gst_symbol) _gst_alloc_obj (alignedBytes, &symbolOOP);
+  INIT_UNALIGNED_OBJECT (symbolOOP, alignedBytes - numBytes);
+
+  memcpy (symbol->symString, str, len);
+  symbolOOP->flags |= F_READONLY;
+  return symbolOOP;
+}
 
 static mst_Boolean
 is_same_string (const char *str,
@@ -1236,25 +1214,85 @@ _gst_selector_num_args (OOP symbolOOP)
     return (1);
 
   for (numArgs = 0; len;)
-    {
-      if (bytes[--len] == ':')
- {
-  numArgs++;
- }
-    }
+    if (bytes[--len] == ':')
+      numArgs++;
+
   return (numArgs);
 }
 
 #include "builtins.inl"
 
 void
-_gst_init_symbols (void)
+_gst_init_symbols_pass1 (void)
+{
+  const symbol_info *si;
+  struct builtin_selector *bs;
+
+  for (si = sym_info; si->symbolVar; si++)
+    *si->symbolVar = alloc_symbol_oop (si->value, strlen (si->value));
+
+  /* Complete gperf's generated table with each symbol's OOP,
+     and prepare a kind of reverse mapping from the 256 bytecodes
+     to the hash table entries.  */
+  for (bs = _gst_builtin_selectors_hash;
+       bs - _gst_builtin_selectors_hash <
+ sizeof (_gst_builtin_selectors_hash) / sizeof (_gst_builtin_selectors_hash[0]);
+       bs++)
+    if (bs->offset != -1)
+      {
+ const char *name = bs->offset + _gst_builtin_selectors_names;
+ bs->symbol = alloc_symbol_oop (name, strlen (name));
+        _gst_builtin_selectors[bs->bytecode] = *bs;
+      }
+}
+
+void
+_gst_init_symbols_pass2 (void)
+{
+  const symbol_info *si;
+  struct builtin_selector *bs;
+
+  for (si = sym_info; si->symbolVar; si++)
+    alloc_symlink (*si->symbolVar, hash_symbol (si->value, strlen (si->value)));
+
+  /* Complete gperf's generated table with each symbol's OOP,
+     and prepare a kind of reverse mapping from the 256 bytecodes
+     to the hash table entries.  */
+  for (bs = _gst_builtin_selectors_hash;
+       bs - _gst_builtin_selectors_hash <
+ sizeof (_gst_builtin_selectors_hash) / sizeof (_gst_builtin_selectors_hash[0]);
+       bs++)
+    if (bs->offset != -1)
+      {
+ const char *name = bs->offset + _gst_builtin_selectors_names;
+ alloc_symlink (bs->symbol, hash_symbol (name, strlen (name)));
+      }
+}
+
+static OOP
+intern_string_fast (const char *str, OOP *pTestOOP)
+{
+  int len = strlen (str);
+  OOP testOOP = *pTestOOP;
+
+  if (is_same_string (str, testOOP, len))
+    {
+      (*pTestOOP)++;
+      return testOOP;
+    }
+  else
+    return intern_counted_string (str, len);
+}
+
+void
+_gst_restore_symbols (void)
 {
   const symbol_info *si;
   struct builtin_selector *bs;
+  OOP currentOOP = _gst_symbol_table + 1;
 
   for (si = sym_info; si->symbolVar; si++)
-    *si->symbolVar = _gst_intern_string (si->value);
+    *si->symbolVar = intern_string_fast (si->value, &currentOOP);
 
   /* Complete gperf's generated table with each symbol's OOP,
      and prepare a kind of reverse mapping from the 256 bytecodes
@@ -1266,7 +1304,7 @@ _gst_init_symbols (void)
     if (bs->offset != -1)
       {
  const char *name = bs->offset + _gst_builtin_selectors_names;
- bs->symbol = _gst_intern_string (name);
-        _gst_builtin_selectors[bs->bytecode] = bs;
+ bs->symbol = intern_string_fast (name, &currentOOP);
+        _gst_builtin_selectors[bs->bytecode] = *bs;
       }
 }


--- orig/libgst/sym.h
+++ mod/libgst/sym.h
@@ -90,63 +90,34 @@ extern int _gst_use_undeclared
 
 extern OOP _gst_and_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_as_scaled_decimal_scale_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_at_put_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_at_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_bad_return_error_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_bit_and_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_bit_or_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_bit_shift_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_bit_xor_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_boolean_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_byte_array_out_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_byte_array_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_c_object_ptr_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_c_object_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_char_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_class_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_divide_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_does_not_understand_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_double_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_equal_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_false_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_float_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_greater_equal_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_greater_than_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_if_false_if_true_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_if_false_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_if_true_if_false_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_if_true_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_int_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_integer_divide_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_is_nil_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_java_as_int_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_java_as_long_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_less_equal_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_less_than_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_long_double_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_long_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_minus_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_must_be_boolean_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_new_colon_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_nil_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_not_equal_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_not_nil_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_or_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_perform_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_perform_with_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_perform_with_with_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_perform_with_with_with_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_perform_with_arguments_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_permission_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_plus_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_primitive_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_remainder_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_repeat_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_same_object_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_self_smalltalk_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_self_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_size_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_smalltalk_symbol ATTRIBUTE_HIDDEN;
+extern OOP _gst_smalltalk_namespace_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_start_execution_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_string_out_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_string_symbol ATTRIBUTE_HIDDEN;
@@ -156,7 +127,6 @@ extern OOP _gst_symbol_out_symbol ATTRIB
 extern OOP _gst_terminate_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_this_context_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_times_repeat_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_times_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_to_by_do_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_to_do_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_true_symbol ATTRIBUTE_HIDDEN;
@@ -164,8 +134,6 @@ extern OOP _gst_uint_symbol ATTRIBUTE_HI
 extern OOP _gst_ulong_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_undeclared_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_unknown_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_value_colon_symbol ATTRIBUTE_HIDDEN;
-extern OOP _gst_value_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_value_with_rec_with_args_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_variadic_smalltalk_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_variadic_symbol ATTRIBUTE_HIDDEN;
@@ -351,10 +319,22 @@ extern void _gst_print_symbols (void)
   ATTRIBUTE_HIDDEN;
 
 /* This routine initializes the variables containing the Symbols
-   known to the VM.  */
-extern void _gst_init_symbols (void)
+   known to the VM.  This one creates the symbol OOPs, which have to
+   be consecutive in order to speed up the load.  */
+extern void _gst_init_symbols_pass1 (void)
   ATTRIBUTE_HIDDEN;
 
+/* This one creates the SymLink OOPs for the Symbols previously
+   created.  */
+extern void _gst_init_symbols_pass2 (void)
+  ATTRIBUTE_HIDDEN;
+
+/* This routine reloads the variables containing the Symbols
+   known to the VM.  It is invocated upon image load.  */
+extern void _gst_restore_symbols (void)
+  ATTRIBUTE_HIDDEN;
+
+
 extern void _gst_check_symbol_chain (void)
   ATTRIBUTE_HIDDEN;
 
@@ -370,7 +350,7 @@ struct builtin_selector {
   int bytecode;
 };
 
-extern struct builtin_selector *_gst_builtin_selectors[256]
+extern struct builtin_selector _gst_builtin_selectors[256]
   ATTRIBUTE_HIDDEN;
 
 extern struct builtin_selector *_gst_lookup_builtin_selector (const char *str,


--- orig/libgst/vm.def
+++ mod/libgst/vm.def
@@ -232,7 +232,7 @@ operation PLUS_SPECIAL ( op1 op2 -- op )
   INTERP_BASIC_OP (op, op1, op2, iarg1 += iarg2, farg1 + farg2);
   PREPARE_STACK ();
   EXPORT_REGS ();
-  SEND_MESSAGE (_gst_plus_symbol, 1);
+  SEND_MESSAGE (_gst_builtin_selectors[PLUS_SPECIAL].symbol, 1);
   IMPORT_REGS ();
   FETCH (dispatch_vec);
 }
@@ -241,7 +241,7 @@ operation MINUS_SPECIAL ( op1 op2 -- op
   INTERP_BASIC_OP (op, op1, op2, iarg1 -= iarg2, farg1 - farg2);
   PREPARE_STACK ();
   EXPORT_REGS ();
-  SEND_MESSAGE (_gst_minus_symbol,