bytecodes.hpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.25 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00020 
00021 
00022 */
00023 
00024 // Bytecodes comprises the definition of all bytecodes
00025 // and provides utility functions working on bytecodes.
00026 //
00027 //
00028 // Naming conventions for send bytecodes;
00029 // basically they are coming in three forms:
00030 //
00031 // a) <send type>_send_<argument specification>
00032 // b) <send_type>_send_<argument specification>_pop
00033 // c) <name of predicted smi selector>
00034 //
00035 // <send_type> is one of:
00036 //
00037 // interpreted  monomorphic send to interpreted method
00038 // compiled     monomorphic send to compiled method
00039 // primitive    monomorphic send to primitive method
00040 // access       monomorphic send to access method
00041 // polymorphic  polymorphic send to interpreted or compiled method
00042 // megamorphic  megamorphic send to interpreted or compiled method
00043 //
00044 // <argument specification is one of:
00045 //
00046 // 0            receiver & 0 arguments on stack, normal send
00047 // 1            receiver & 1 argument  on stack, normal send
00048 // 2            receiver & 2 arguments on stack, normal send
00049 // n            receiver & n arguments on stack, normal send
00050 // self         no receiver, arguments on stack, normal send
00051 // super        no receiver, arguments on stack, super  send
00052 
00053 
00054 class Bytecodes: AllStatic {
00055  public:
00056   // Returns the bytecode set version number.
00057   // Must match the version number generated by the Digitalk system.
00058   static int version()  { return 2; }
00059 
00060   enum Format {         // Format of instruction: * means align to oop
00061     B,                  // {byte}
00062     BB,                 // {byte, byte}
00063     BBB,                // {byte, byte, byte}
00064     BBBB,               // {byte, byte, byte, byte}
00065     BBO,                // {byte, byte, *, oop}
00066     BBL,                // {byte, byte, *, long}
00067     BO,                 // {byte, *, oop}
00068     BOO,                // {byte, *, oop, oop}
00069     BLO,                // {byte, *, long, oop}
00070     BOL,                // {byte, *, oop, long}
00071     BLL,                // {byte, *, long, long}
00072     BL,                 // {byte, *, long}
00073     BLB,                // {byte, *, byte}
00074     BBOO,               // {byte, byte, *, oop, oop}
00075     BBLO,               // {byte, byte, *, long, oop}
00076     BOOLB,              // {byte, *, oop, oop, long, byte}
00077     BBS,                // {byte, byte = number of bytes to follow, {byte}*}
00078     UNDEF,              // for undefined codes
00079 
00080     number_of_formats
00081   };
00082 
00083   enum CodeType {       // Instruction classification
00084     local_access,       // loads & stores of temps and args
00085     instVar_access,     // loads & stores of instVars
00086     context_access,     // loads & stores of context temps
00087     classVar_access,    // loads & stores to class variables
00088     global_access,      // loads & stores to global variables
00089     new_closure,        // closure creation
00090     new_context,        // context creation
00091     control_struc,      // control structures (incl. local return)
00092     message_send,       // all sends
00093     nonlocal_return,    // non-local returns
00094     primitive_call,     // primitive calls
00095     dll_call,           // dll calls
00096     float_operation,    // float operations
00097     miscellaneous,      // for all other instructions
00098 
00099     number_of_code_types
00100   };
00101 
00102   enum ArgumentSpec {   // Argument specification for sends
00103     recv_0_args,        // recv & 0 arguments on stack
00104     recv_1_args,        // recv & 1 arguments on stack
00105     recv_2_args,        // recv & 2 arguments on stack
00106     recv_n_args,        // recv & n arguments on stack
00107     args_only,          // only arguments on stack
00108     no_args,            // for non-send instructions
00109 
00110     number_of_argument_specs
00111   };
00112 
00113   enum SendType {       // Send classification
00114     interpreted_send,   // interpreted monomorphic send
00115     compiled_send,      // compiled monomorphic send
00116     polymorphic_send,   // interpreted polymorphic send
00117     megamorphic_send,   // interpreted megamorphic send
00118     predicted_send,     // send to interpreted predicted method (method containing a predicted primitive call with own bytecode)
00119     accessor_send,      // send to interpreted accessor method (method containing a predicted instVar access)
00120     primitive_send,     // send to interpreted primitive method (method containing a predicted primitive call)
00121     no_send,            // for non-send instructions
00122 
00123     number_of_send_types
00124   };
00125 
00126   enum LoopType {       // Loop classification
00127     loop_start,         // instruction starting a loop
00128     loop_end,           // instruction ending a loop
00129     no_loop,            // for non-loop instructions
00130 
00131     number_of_loop_types
00132   };
00133 
00134   enum Code {
00135     // row 0
00136     push_temp_0                         = 0x00,
00137     push_temp_1                         = 0x01,
00138     push_temp_2                         = 0x02,
00139     push_temp_3                         = 0x03,
00140     push_temp_4                         = 0x04,
00141     push_temp_5                         = 0x05,
00142     unimplemented_06                    = 0x06,
00143     push_temp_n                         = 0x07,
00144     push_arg_1                          = 0x08, // n-1
00145     push_arg_2                          = 0x09, // n-2
00146     push_arg_3                          = 0x0a, // n-3
00147     push_arg_n                          = 0x0b, // n-1-b
00148     allocate_temp_1                     = 0x0c,
00149     allocate_temp_2                     = 0x0d,
00150     allocate_temp_3                     = 0x0e,
00151     allocate_temp_n                     = 0x0f, // 0 means 256
00152 
00153     // row 1
00154     store_temp_0_pop                    = 0x10,
00155     store_temp_1_pop                    = 0x11,
00156     store_temp_2_pop                    = 0x12,
00157     store_temp_3_pop                    = 0x13,
00158     store_temp_4_pop                    = 0x14,
00159     store_temp_5_pop                    = 0x15,
00160     store_temp_n                        = 0x16, // 255-b
00161     store_temp_n_pop                    = 0x17, // 255-b
00162     push_neg_n                          = 0x18, // -b
00163     push_succ_n                         = 0x19, // b+1
00164     push_literal                        = 0x1a,
00165     push_tos                            = 0x1b,
00166     push_self                           = 0x1c,
00167     push_nil                            = 0x1d,
00168     push_true                           = 0x1e,
00169     push_false                          = 0x1f,
00170 
00171     // row 2
00172     unimplemented_20                    = 0x20,
00173     unimplemented_21                    = 0x21,
00174     unimplemented_22                    = 0x22,
00175     unimplemented_23                    = 0x23,
00176     unimplemented_24                    = 0x24,
00177     unimplemented_25                    = 0x25,
00178     unimplemented_26                    = 0x26,
00179     unimplemented_27                    = 0x27,
00180     return_instVar_name                 = 0x28,
00181     push_classVar                       = 0x29,
00182     store_classVar_pop                  = 0x2a,
00183     store_classVar                      = 0x2b,
00184     return_instVar                      = 0x2c,
00185     push_instVar                        = 0x2d,
00186     store_instVar_pop                   = 0x2e,
00187     store_instVar                       = 0x2f,
00188 
00189     // row 3
00190     float_allocate                      = 0x30,
00191     float_floatify_pop                  = 0x31,
00192     float_move                          = 0x32,
00193     float_set                           = 0x33,
00194     float_nullary_op                    = 0x34,
00195     float_unary_op                      = 0x35,
00196     float_binary_op                     = 0x36,
00197     float_unary_op_to_oop               = 0x37,
00198     float_binary_op_to_oop              = 0x38,
00199     unimplemented_39                    = 0x39,
00200     unimplemented_3a                    = 0x3a,
00201     unimplemented_3b                    = 0x3b,
00202     unimplemented_3c                    = 0x3c,
00203     push_instVar_name                   = 0x3d,
00204     store_instVar_pop_name              = 0x3e,
00205     store_instVar_name                  = 0x3f,
00206 
00207     // row 4
00208     push_temp_0_context_0               = 0x40,
00209     push_temp_1_context_0               = 0x41,
00210     push_temp_2_context_0               = 0x42,
00211     push_temp_n_context_0               = 0x43,
00212     store_temp_0_context_0_pop          = 0x44,
00213     store_temp_1_context_0_pop          = 0x45,
00214     store_temp_2_context_0_pop          = 0x46,
00215     store_temp_n_context_0_pop          = 0x47,
00216     push_new_closure_context_0          = 0x48,
00217     push_new_closure_context_1          = 0x49,
00218     push_new_closure_context_2          = 0x4a,
00219     push_new_closure_context_n          = 0x4b,
00220     install_new_context_method_0        = 0x4c,
00221     install_new_context_method_1        = 0x4d,
00222     install_new_context_method_2        = 0x4e,
00223     install_new_context_method_n        = 0x4f,
00224 
00225     // row 5
00226     push_temp_0_context_1               = 0x50,
00227     push_temp_1_context_1               = 0x51,
00228     push_temp_2_context_1               = 0x52,
00229     push_temp_n_context_1               = 0x53,
00230     store_temp_0_context_1_pop          = 0x54,
00231     store_temp_1_context_1_pop          = 0x55,
00232     store_temp_2_context_1_pop          = 0x56,
00233     store_temp_n_context_1_pop          = 0x57,
00234     push_new_closure_tos_0              = 0x58,
00235     push_new_closure_tos_1              = 0x59,
00236     push_new_closure_tos_2              = 0x5a,
00237     push_new_closure_tos_n              = 0x5b,
00238     only_pop                            = 0x5c,
00239     install_new_context_block_1         = 0x5d,
00240     install_new_context_block_2         = 0x5e,
00241     install_new_context_block_n         = 0x5f,
00242 
00243     // row 6
00244     push_temp_0_context_n               = 0x60,
00245     push_temp_1_context_n               = 0x61,
00246     push_temp_2_context_n               = 0x62,
00247     push_temp_n_context_n               = 0x63,
00248     store_temp_0_context_n_pop          = 0x64,
00249     store_temp_1_context_n_pop          = 0x65,
00250     store_temp_2_context_n_pop          = 0x66,
00251     store_temp_n_context_n_pop          = 0x67,
00252     set_self_via_context                = 0x68,
00253     copy_1_into_context                 = 0x69,
00254     copy_2_into_context                 = 0x6a,
00255     copy_n_into_context                 = 0x6b,
00256     copy_self_into_context              = 0x6c,
00257     copy_self_1_into_context            = 0x6d,
00258     copy_self_2_into_context            = 0x6e,
00259     copy_self_n_into_context            = 0x6f,
00260 
00261     // row 7
00262     ifTrue_byte                         = 0x70,
00263     ifFalse_byte                        = 0x71,
00264     and_byte                            = 0x72,
00265     or_byte                             = 0x73,
00266     whileTrue_byte                      = 0x74,
00267     whileFalse_byte                     = 0x75,
00268     jump_else_byte                      = 0x76,
00269     jump_loop_byte                      = 0x77,
00270     ifTrue_word                         = 0x78,
00271     ifFalse_word                        = 0x79,
00272     and_word                            = 0x7a,
00273     or_word                             = 0x7b,
00274     whileTrue_word                      = 0x7c,
00275     whileFalse_word                     = 0x7d,
00276     jump_else_word                      = 0x7e,
00277     jump_loop_word                      = 0x7f,
00278 
00279     // row 8
00280     interpreted_send_0                  = 0x80,
00281     interpreted_send_1                  = 0x81,
00282     interpreted_send_2                  = 0x82,
00283     interpreted_send_n                  = 0x83,
00284     interpreted_send_0_pop              = 0x84,
00285     interpreted_send_1_pop              = 0x85,
00286     interpreted_send_2_pop              = 0x86,
00287     interpreted_send_n_pop              = 0x87,
00288     interpreted_send_self               = 0x88,
00289     interpreted_send_self_pop           = 0x89,
00290     interpreted_send_super              = 0x8a,
00291     interpreted_send_super_pop          = 0x8b,
00292     return_tos_pop_0                    = 0x8c,
00293     return_tos_pop_1                    = 0x8d,
00294     return_tos_pop_2                    = 0x8e,
00295     return_tos_pop_n                    = 0x8f,
00296 
00297     // row 9
00298     polymorphic_send_0                  = 0x90,
00299     polymorphic_send_1                  = 0x91,
00300     polymorphic_send_2                  = 0x92,
00301     polymorphic_send_n                  = 0x93,
00302     polymorphic_send_0_pop              = 0x94,
00303     polymorphic_send_1_pop              = 0x95,
00304     polymorphic_send_2_pop              = 0x96,
00305     polymorphic_send_n_pop              = 0x97,
00306     polymorphic_send_self               = 0x98,
00307     polymorphic_send_self_pop           = 0x99,
00308     polymorphic_send_super              = 0x9a,
00309     polymorphic_send_super_pop          = 0x9b,
00310     return_self_pop_0                   = 0x9c,
00311     return_self_pop_1                   = 0x9d,
00312     return_self_pop_2                   = 0x9e,
00313     return_self_pop_n                   = 0x9f,
00314 
00315     // row a
00316     compiled_send_0                     = 0xa0,
00317     compiled_send_1                     = 0xa1,
00318     compiled_send_2                     = 0xa2,
00319     compiled_send_n                     = 0xa3,
00320     compiled_send_0_pop                 = 0xa4,
00321     compiled_send_1_pop                 = 0xa5,
00322     compiled_send_2_pop                 = 0xa6,
00323     compiled_send_n_pop                 = 0xa7,
00324     compiled_send_self                  = 0xa8,
00325     compiled_send_self_pop              = 0xa9,
00326     compiled_send_super                 = 0xaa,
00327     compiled_send_super_pop             = 0xab,
00328     return_tos_zap_pop_n                = 0xac,
00329     return_self_zap_pop_n               = 0xad,
00330     non_local_return_tos_pop_n          = 0xae,
00331     non_local_return_self_pop_n         = 0xaf,
00332 
00333     // row b
00334     prim_call                           = 0xb0,
00335     predict_prim_call                   = 0xb1,
00336     prim_call_failure                   = 0xb2,
00337     predict_prim_call_failure           = 0xb3,
00338     dll_call_sync                       = 0xb4,
00339     prim_call_self                      = 0xb5,
00340     prim_call_self_failure              = 0xb6,
00341     unimplemented_b7                    = 0xb7,
00342     access_send_self                    = 0xb8,
00343     primitive_send_0                    = 0xb9,
00344     primitive_send_super                = 0xba,
00345     primitive_send_super_pop            = 0xbb,
00346     unimplemented_bc                    = 0xbc,
00347     primitive_send_1                    = 0xbd,
00348     primitive_send_2                    = 0xbe,
00349     primitive_send_n                    = 0xbf,
00350 
00351     // row c
00352     prim_call_lookup                    = 0xc0,
00353     predict_prim_call_lookup            = 0xc1,
00354     prim_call_failure_lookup            = 0xc2,
00355     predict_prim_call_failure_lookup    = 0xc3,
00356     dll_call_async                      = 0xc4,
00357     prim_call_self_lookup               = 0xc5,
00358     prim_call_self_failure_lookup       = 0xc6,
00359     unimplemented_c7                    = 0xc7,
00360     access_send_0                       = 0xc8,
00361     primitive_send_0_pop                = 0xc9,
00362     primitive_send_self                 = 0xca,
00363     primitive_send_self_pop             = 0xcb,
00364     unimplemented_cc                    = 0xcc,
00365     primitive_send_1_pop                = 0xcd,
00366     primitive_send_2_pop                = 0xce,
00367     primitive_send_n_pop                = 0xcf,
00368 
00369     // row d
00370     megamorphic_send_0                  = 0xd0,
00371     megamorphic_send_1                  = 0xd1,
00372     megamorphic_send_2                  = 0xd2,
00373     megamorphic_send_n                  = 0xd3,
00374     megamorphic_send_0_pop              = 0xd4,
00375     megamorphic_send_1_pop              = 0xd5,
00376     megamorphic_send_2_pop              = 0xd6,
00377     megamorphic_send_n_pop              = 0xd7,
00378     megamorphic_send_self               = 0xd8,
00379     megamorphic_send_self_pop           = 0xd9,
00380     megamorphic_send_super              = 0xda,
00381     megamorphic_send_super_pop          = 0xdb,
00382     unimplemented_dc                    = 0xdc,
00383     special_primitive_send_1_hint       = 0xdd,
00384     unimplemented_de                    = 0xde,
00385     unimplemented_df                    = 0xdf,
00386 
00387     // row e
00388     smi_add                             = 0xe0,
00389     smi_sub                             = 0xe1,
00390     smi_mult                            = 0xe2,
00391     smi_div                             = 0xe3,
00392     smi_mod                             = 0xe4,
00393     smi_create_point                    = 0xe5,
00394     smi_equal                           = 0xe6,
00395     smi_not_equal                       = 0xe7,
00396     smi_less                            = 0xe8,
00397     smi_less_equal                      = 0xe9,
00398     smi_greater                         = 0xea,
00399     smi_greater_equal                   = 0xeb,
00400     objArray_at                         = 0xec,
00401     objArray_at_put                     = 0xed,
00402     double_equal                        = 0xee,
00403     double_tilde                        = 0xef,
00404 
00405     // row f
00406     push_global                         = 0xf0,
00407     store_global_pop                    = 0xf1,
00408     store_global                        = 0xf2,
00409     push_classVar_name                  = 0xf3,
00410     store_classVar_pop_name             = 0xf4,
00411     store_classVar_name                 = 0xf5,
00412     smi_and                             = 0xf6,
00413     smi_or                              = 0xf7,
00414     smi_xor                             = 0xf8,
00415     smi_shift                           = 0xf9,
00416     unimplemented_fa                    = 0xfa,
00417     unimplemented_fb                    = 0xfb,
00418     unimplemented_fc                    = 0xfc,
00419     unimplemented_fd                    = 0xfd,
00420     unimplemented_fe                    = 0xfe,
00421     halt                                = 0xff,
00422 
00423     number_of_codes                     = 0x100
00424   };
00425 
00426  private:
00427   static char*          _entry_point[number_of_codes];
00428   static char*          _name[number_of_codes];
00429   static Format         _format[number_of_codes];
00430   static CodeType       _code_type[number_of_codes];
00431   static ArgumentSpec   _argument_spec[number_of_codes];
00432   static SendType       _send_type[number_of_codes];
00433   static bool           _single_step[number_of_codes];
00434   static bool           _pop_tos[number_of_codes];
00435   
00436   static void   def(Code code);
00437   static void   def(Code code, char* name, Format format, CodeType code_type, bool single_step, bool pop_tos = false);
00438   static void   def(Code code, char* name, Format format, ArgumentSpec argument_spec, SendType send_type, bool pop_tos = false);
00439   static void   def(Code code, char* name, Format format, CodeType code_type, bool single_step, ArgumentSpec argument_spec, SendType send_type, bool pop_tos);
00440 
00441  public:
00442   // Define entry points
00443   static void   set_entry_point(Code code, char* entry_point);
00444 
00445 
00446   // Testers
00447   static bool   is_defined(Code code)                   { return 0 <= code && code < number_of_codes && _format[code] != UNDEF; }
00448   static bool   is_self_send(Code code);
00449   static bool   is_super_send(Code code);
00450   static bool   has_access_send_code(Code code);
00451   static bool   has_predicted_send_code(Code code);
00452   static bool   is_send_code(Code code)                 { return send_type(code) != no_send; }
00453 
00454 
00455   // Bytecode specification
00456   static char*          entry_point     (Code code)     { return _entry_point[code]; }
00457   static char*          name            (Code code)     { return _name[code]; }
00458   static Format         format          (Code code)     { return _format[code]; }
00459   static CodeType       code_type       (Code code)     { return _code_type[code]; }
00460   static ArgumentSpec   argument_spec   (Code code)     { return _argument_spec[code]; }
00461   static SendType       send_type       (Code code)     { return _send_type[code]; }
00462   static bool           single_step     (Code code)     { return _single_step[code]; }
00463   static bool           pop_tos         (Code code)     { return _pop_tos[code]; }
00464   static LoopType       loop_type       (Code code);
00465 
00466 
00467   // Helpers for printing
00468   static char*  format_as_string        (Format format);
00469   static char*  code_type_as_string     (CodeType code_type);
00470   static char*  argument_spec_as_string (ArgumentSpec argument_spec);
00471   static char*  send_type_as_string     (SendType send_type);
00472   static char*  loop_type_as_string     (LoopType loop_type);
00473 
00474 
00475   // Send bytecode transitions
00476   //
00477   // The following functions return the corresponding interpreted, compiled,
00478   // polymorphic or megamorphic send bytecode for a given send bytecode. They
00479   // are used to implement the bytecode transitions during interpreter inline
00480   // cache misses.
00481 
00482   static Code original_send_code_for    (Code code);    // predicted sends keep original code (smi_add -> smi_add)
00483   static Code interpreted_send_code_for (Code code);    // predicted sends loose their original value (smi_add -> int'_send_1)
00484   static Code compiled_send_code_for    (Code code);
00485   static Code access_send_code_for      (Code code);
00486   static Code primitive_send_code_for   (Code code);
00487   static Code polymorphic_send_code_for (Code code);
00488   static Code megamorphic_send_code_for (Code code);
00489 
00490 
00491   // Primitive lookup bytecode transitions
00492   //
00493   // The following function returns the corresponding primitive call
00494   // bytecode for a given primitive call lookup bytecode. It is used
00495   // to implement the bytecode transition during a primitive lookup.
00496 
00497   static Code original_primitive_call_code_for  (Code code);
00498   static Code primitive_call_code_for           (Code code);
00499 
00500 
00501   // Initialization/debugging
00502   static void init();
00503   static void print();
00504 };

Generated on Mon Oct 9 13:37:05 2006 for Strongtalk VM by  doxygen 1.4.7