1 require "#{File.dirname(__FILE__)}/../../kernel/core/iseq"
3 class ShotgunInstructions
5 def generate_switch(fd, op="op")
6 fd.puts "switch(#{op}) {"
7 InstructionSet::OpCodes.each do |ins|
8 code = send(ins.opcode) rescue nil
10 fd.puts " case #{ins.bytecode}: { /* #{ins.opcode} */"
12 if ins.check_interrupts?
13 fd.puts " goto check_interrupts;"
15 fd.puts " goto insn_start;"
17 fd.puts " goto next_op;"
21 STDERR.puts "Problem with opcode: #{ins.opcode}"
24 fd.puts "default: printf(\"Invalid bytecode: %d\\n\", (int)op); sassert(0);\n"
29 def generate_threaded(fd, op="op")
30 InstructionSet::OpCodes.each do |ins|
31 code = send(ins.opcode) rescue nil
33 fd.puts " insn_#{ins.bytecode}: {"
35 if ins.check_interrupts?
36 fd.puts " goto check_interrupts;"
38 fd.puts " goto insn_start;"
45 STDERR.puts "Problem with opcode: #{ins.opcode}"
52 code = "static int _ip_size(uint32_t bc) {\nswitch(bc) {\n"
53 InstructionSet::OpCodes.each do |ins|
55 code << " case #{ins.bytecode}:\n"
58 code << " return 3;\n"
60 InstructionSet::OpCodes.each do |ins|
62 code << " case #{ins.bytecode}:\n"
65 code << " return 2;\n"
67 code << "}\nreturn 1;\n}\n\n"
69 code << "#define DT_ADDRESSES static void* _dt_addresses[#{InstructionSet::OpCodes.size + 1}]; static int _dt_size = #{InstructionSet::OpCodes.size};\n"
70 code << "#define SETUP_DT_ADDRESSES "
72 InstructionSet::OpCodes.each do |ins|
73 code << "_dt_addresses[#{ins.bytecode}] = &&insn_#{ins.bytecode}; "
79 static inline uint32_t read_int_from_be(uint8_t *str) {
80 return (uint32_t)((str[0] << 24)
86 static void calculate_into_gotos(STATE, OBJECT iseq, OBJECT output, void* addrs[], int size) {
93 f = bytearray_bytes(state, iseq);
94 insn = (uint8_t*)bytearray_byte_address(state, iseq);
95 compiled = (uintptr_t*)bytearray_byte_address(state, output);
98 for(offset = 0; offset < f; offset += 4) {
100 op = *((uint32_t*)(insn + offset));
102 op = read_int_from_be(insn + offset);
104 /* Protect against errant data */
105 if(op > size) op = 0;
106 *compiled++ = (uintptr_t)addrs[op];
107 /* copy the instruction args */
108 sz = _ip_size(op) - 1;
109 for(i = 0; i < sz; i++) {
111 #if CONFIG_BIG_ENDIAN
112 op = *((uint32_t*)(insn + offset));
114 op = read_int_from_be(insn + offset);
116 *compiled++ = (uintptr_t)op;
126 def generate_declarations(fd)
128 fd.puts "native_int j, k, m;"
129 fd.puts "OBJECT _lit, t1, t2, t3, t4;"
130 fd.puts "struct message msg;"
134 str = "static const char instruction_names[] = {\n"
135 InstructionSet::OpCodes.each do |ins|
136 str << " \"#{ins.opcode.to_s}\\0\"\n"
140 str << "static const unsigned short instruction_name_offsets[] = {\n"
141 InstructionSet::OpCodes.each_with_index do |ins, index|
142 str << ",\n" if index > 0
144 offset += ins.opcode.to_s.length + 1
148 const char *get_instruction_name(int op) {
149 return instruction_names + instruction_name_offsets[op];
154 def generate_names_header
155 str = "const char *get_instruction_name(int op);\n"
157 InstructionSet::OpCodes.each do |ins|
158 str << "#define CPU_INSTRUCTION_#{ins.opcode.to_s.upcase} #{ins.bytecode}\n" unless ins.opcode == :unused
165 # Performs a no-op, i.e. does nothing.
173 # The classic no-op operator; performs no actions, and does not modify the
176 # To consume an item from the stack, but otherwise do nothing, use
186 # Pushes an integer literal value onto the stack
195 # Pushes the value of the integer literal onto the stack.
202 # Certain common cases (i.e. -1, 0, 1, and 2) are optimised to avoid the
203 # lookup of the literal value in the literals tuple.
208 stack_push(I2N(_int));
213 # Pushes -1 onto the stack
222 # Fast push of -1 (negative 1) onto the stack. This is an optimisation
223 # applied whenever a literal -1 is encountered by the compiler. It is
224 # equivalent to 'push -1', but faster because there is no need to lookup
225 # the literal value in the literals tuple.
234 # Pushes 0 onto the stack
243 # Fast push of 0 (zero) onto the stack. This is an optimisation applied
244 # whenever a literal 0 is encountered by the compiler. It is equivalent to
245 # 'push 0', but faster because there is no need to lookup the literal
246 # value in the literals tuple.
255 # Pushes 1 onto the stack
264 # Fast push of 1 (one) onto the stack. This is an optimisation applied
265 # whenever a literal 1 is encountered by the compiler. It is equivalent to
266 # 'push 1', but faster because there is no need to lookup the literal
267 # value in the literals tuple.
276 # Pushes 2 onto the stack
285 # Fast push of 2 (two) onto the stack. This is an optimisation applied
286 # whenever a literal 2 is encountered by the compiler. It is equivalent to
287 # 'push 2', but faster because there is no need to lookup the literal
288 # value in the literals tuple.
297 # Puts nil on the stack
306 # The special object nil is pushed onto the stack.
313 # Pushes true onto the stack
322 # The special value true is pushed onto the stack.
329 # Pushes false onto the stack
338 # The special object false is pushed onto the stack.
341 "stack_push(Qfalse);"
345 # Pushes the current method context onto the stack
354 # Creates a reference to the current method execution context, and pushes
359 methctx_reference(state, c->active_context);
360 stack_push(c->active_context);
365 # Pushes a literal from the current state onto the stack.
367 # \push_literal index
374 # The literal identified by the opcode argument (+index+) in the current
375 # state literals tuple is retrieved and placed onto the stack.
377 # The literals tuple is part of the machine state, and holds all literal
378 # objects defined or used within a particular scope.
383 t1 = cpu_current_literals(state, c);
384 t2 = fast_fetch(t1, _int);
390 # Sets a literal to the specified value
400 # Used to set the value of a literal that is a regular expression. The
401 # Regexp object to which the literal is to be set is copied from the top
402 # of the stack, but is not consumed.
404 # Unlike other literals such as strings and numbers, creating a Regexp
405 # literal (i.e. via the /regex/ syntax) is a two step process to create
406 # the literal slot for the Regexp, create a literal for the string between
407 # the '/' delimiters and create a new Regexp object passing it the string.
408 # Only then can the literal value be set, using the set_literal opcode.
413 tuple_put(state, cpu_current_literals(state, c), _int, stack_top());
418 # Pushes a reference to the current self object onto the stack.
427 # The current self object is pushed onto the stack.
430 "stack_push(c->self);"
434 # Pushes the value of a local variable onto the stack
443 # Retrieves the current value (+local_value+) of the referenced local
444 # variable (+local+), and pushes it onto the stack.
449 stack_push(fast_fetch(c->locals, _int));
452 # "next_int; stack_push(fast_fetch(cpu_current_locals(state, c), _int));"
456 # Pushes the value of a local from an enclosing scope onto the stack
458 # \push_local_depth depth local
465 # Retrieves the value of a local variable from a context enclosing the
466 # current context, and pushes it onto the stack.
471 # i = i + j # i is a local variable from enclosing scope at depth 1
479 k = (native_int)_int;
481 t1 = c->active_context;
482 for(j = 0; j < k; j++) {
483 t2 = blokctx_env(state, t1);
484 t1 = blokenv_get_home_block(t2);
486 stack_push(tuple_at(state, blokctx_locals(state, t1), _int));
491 # Pushes the current exception onto the stack
500 # Pushes the current exception onto the stack, so that it can be used for
501 # some purpose, such as checking the exception type, setting an exception
502 # variable in a rescue clause, etc.
508 # foo = BAR # BAR is not defined
509 # rescue NameError # push_exception used to check type of exception (via ===)
515 "stack_push(c->exception);"
519 # Clears any exceptions from the current execution context
527 # Clears any exceptions from the current execution context. The stack is
528 # untouched by this opcode.
537 # Pushes a block onto the stack
546 # Pushes the current block onto the stack. Used when a block passed to a
551 # yield # yields to the block passed to the method, which causes
552 # # push_block to be called
557 "stack_push(cpu_current_block(state, c));"
561 # Pushes an instance variable onto the stack
570 # Pushes the instance variable identified by +lit+ onto the stack.
575 stack_push(object_get_ivar(state, c->self, _lit));
580 # Allocate space for a new object
590 # Pop a field +count+ and \allocate space for an object with the
591 # appropriate header and field space. The object created will be
592 # uninitialized; it will have its parent \class and all fields initialized
598 stack_push(NEW_OBJECT(Qnil, N2I(_lit)));
603 # Sets a literal to reference the specified \class
614 # Pops a literal reference and a \class off the top of the stack, sets the
615 # \class of the literal to the new \class, and then pushes it back onto
628 # Store a value into the specified object field
640 # Overwrite the value of a particular field slot with the specified
641 # object. The object reference is left on the stack.
648 SET_FIELD(t3, N2I(t1), t2);
654 # Retrieve the value within the field of the specified object
665 # Retrieve the object of the specified object field number.
671 stack_push(NTH_FIELD(t2, N2I(t1)));
676 # Pushes a value from an object field onto the stack
685 # Pushes the value of the specified field in the current object onto the
688 # Fields are similar to instance variables, but have dedicated storage
689 # allocated. They are primarily used on core or bootstap classes.
690 # Accessing a field is slightly faster than accessing an ivar.
695 stack_push(NTH_FIELD(c->self, _int));
700 # Store a value into a field of self
702 # \store_my_field fld
710 # Stores the value at the top of the stack into the field specified by
713 # The stack is left unmodified.
718 SET_FIELD(c->self, _int, stack_top());
723 # Calls a primitive method
725 # \send_primitive primitive_index argc
737 # Execute a primitive method on the receiver (+receiver+). The index of the
738 # primitive to execute (+primitive_index+), and the number of arguments
739 # being passed (+argc+) are specified as paramters.
741 # When the primitive returns, the return value will be on top of the
744 # The implementation of the primitive is responsible for consuming the
745 # receiver and any arguments that are on the stack, and for placing a
746 # return value onto the stack.
751 j = (native_int)_int; // primitive index
753 k = (native_int)_int; // num_args
755 // Should the OBJECT parameter be removed since a primitive is not necesarily
756 // performed on an object? Or should we state that the semantics of a primitive
757 // will always have an object or else it needs to be an opcode... ?
758 // If the primitive fails raise an exception
764 if(!cpu_perform_system_primitive(state, c, j, &msg))
766 cpu_raise_primitive_failure(state, c, j);
772 # Unconditionally jump execution to the position specified by the label
780 # Moves the instruction pointer to the instruction following the specified
781 # label without disturbing the stack.
796 # Jump execution to the position specified by the label if the top of the
797 # stack evaluates to false.
799 # \goto_if_false label
806 # Remove the top item on the stack, and if +nil+ or +false+, jump to the
807 # instruction following the specified label; otherwise, continue.
825 # Jump execution to the position specified by the label if the top of the
826 # stack evaluates to true.
828 # \goto_if_true label
835 # Remove the top item on the stack, and if not +nil+ or +false+, jump to
836 # the instruction following the specified label; otherwise, continue.
854 # Jump execution to the position specified by the label if the top of the
855 # stack is not undefined.
857 # \goto_if_defined label
864 # Remove the top item on the stack, and if it is not the special value
865 # +undefined+, jump to the instruction following the specified label;
866 # otherwise, continue.
884 # Swap the top two stack values
896 # Swaps the top two items on the stack, so that the second item becomes
897 # the first, and the first item becomes the second.
909 # Duplicate the top item on the stack
920 # Duplicate the top value on the operand stack and push the duplicated
921 # value onto the operand stack.
931 # Pop an item off the stack and discard
940 # Removes the top item from the stack, discarding it.
942 # Pop is typically used when the return value of another opcode is not
946 " (void)stack_pop();"
950 # Sets the value of a local variable
960 # Pops +value+ off the stack, and uses it to set the value of the local
961 # variable identified by the literal +local+. The value is then pushed back
962 # onto the stack, to represent the return value from the expression.
968 // printf("Set local %d to %s\\n", _int, _inspect(t1));
970 if(t2->gc_zone == 0) {
971 sassert(_int < NUM_FIELDS(t2) && "locals tuple sized wrong");
972 fast_unsafe_set(t2, _int, t1);
974 tuple_put(state, t2, _int, t1);
981 # Sets a method argument local from the caller's stack
983 # \set_local_from_fp local arg
989 # Copies the value of method argument +arg+ into the local variable
990 # +local+. Method arguments are accessed from the caller's stack via
991 # negative offsets from the frame pointer, where 0 is the first argument,
992 # 1 is the second, etc.
994 # This opcode is now deprecated, and is not currently used under
999 # Under compiler1, this opcode was used to copy method args into stack
1000 # locals if the method arg was modified, but not captured. The use of
1001 # stack and frame locals has been deprecated under compiler2, and all
1002 # locals are now allocated in the execution context locals tuple. This
1003 # opcode has thus been modified to store a frame referenced method arg in
1006 def set_local_from_fp
1009 k = (native_int)_int;
1012 t1 = c->stack_top[c->fp - _int];
1014 t2 = cpu_current_locals(state, c);
1015 if(t2->gc_zone == 0) {
1016 sassert(k < NUM_FIELDS(t2) && "locals tuple sized wrong");
1017 fast_unsafe_set(t2, k, t1);
1019 tuple_put(state, t2, k, t1);
1025 # Updates the value of a local variable contained in an enclosing scope
1027 # \set_local_depth depth local
1035 # Uses the +value+ on the top of the stack to update the value of the
1036 # local variable +local+ in an enclosing scope. The value is then pushed
1037 # back onto the stack, to represent the return value from the expression.
1042 # i = i + j # i is a local variable from enclosing scope at depth 1
1050 k = (native_int)_int;
1053 t1 = c->active_context;
1055 for(j = 0; j < k; j++) {
1056 t2 = blokctx_env(state, t1);
1057 t1 = blokenv_get_home_block(t2);
1060 t2 = blokctx_locals(state, t1);
1061 if(t2->gc_zone == 0) {
1062 sassert(_int < NUM_FIELDS(t2) && "locals tuple sized wrong");
1063 fast_unsafe_set(t2, _int, t3);
1065 tuple_put(state, t2, _int, t3);
1073 # Create an array and populate with items on the stack
1083 # * [value1, value2, ..., valueN]
1086 # Creates a new array, populating its contents with the number of items
1087 # (+argc+) specified in the opcode. The contents of the new array are
1088 # taken from the stack, with the top item on the stack becoming the last
1089 # item in the array. The resulting array is added back to the stack.
1094 t1 = array_new(state, _int);
1096 for(; j >= 0; j--) {
1098 array_set(state, t1, j, t2);
1101 cpu_perform_hook(state, c, BASIC_CLASS(array),
1102 global->sym_from_literal, t1);
1108 # Unpack the array on the top of the stack into individual items on the
1113 # * [value1, value2, ..., valueN]
1122 # Removes the array currently on top of the stack, and replaces it with
1123 # the contents of the array, such that the first item in the array ends up
1124 # on top of the stack.
1128 # Push array places the contents of the array onto the stack in reverse
1129 # order to the order in which items on the stack are added to an array by
1135 j = N2I(array_get_total(t1));
1136 for(j--; j >= 0; j--) {
1137 stack_push(array_get(state, t1, j));
1143 # Convert a tuple to an array, or wrap an object within an array
1153 # Removes the object on the top of the stack, and:
1155 # If the input is a tuple, a new array object is created based on the
1158 # If the input is an array, it is unmodified.
1160 # If the input is any other type, that type is wrapped within a new array
1163 # The resulting array is then pushed back onto the stack.
1168 if(REFERENCE_P(t1) && object_kind_of_p(state, t1, global->tuple)) {
1169 t1 = array_from_tuple(state, t1);
1170 } else if(!REFERENCE_P(t1) || !object_kind_of_p(state, t1, global->array)) {
1171 t2 = array_new(state, 1);
1172 array_set(state, t2, 0, t1);
1180 # Casts the value on the top of the stack into an array to be used as
1183 # \cast_array_for_args size
1191 # Removes the object on the top of the stack, and:
1193 # If the object is a tuple, it is cast to an array.
1195 # If the object is already an array, it is left unmodified.
1197 # If the object is any other type, it is wrapped in a 1-element array with
1198 # the object as the value of the single element.
1200 # The resulting array is then pushed back onto the stack, and the size of
1201 # the array is added to the argument +size+ that was specified with the
1202 # opcode, and saved as the current method argument count.
1204 # This opcode will always be followed by a push_array instruction that
1205 # unpacks the array elements into discrete stack entries prior to calling
1206 # either send_with_arg_register or send_super_with_arg_register.
1211 # This opcode exists to handle argscat and argspush, where a splat arg is
1212 # specified in addition to one or more discrete arguments.
1214 def cast_array_for_args
1219 if(REFERENCE_P(t1) && object_kind_of_p(state, t1, global->tuple)) {
1220 t1 = array_from_tuple(state, t1);
1221 } else if(!REFERENCE_P(t1) || !object_kind_of_p(state, t1, global->array)) {
1222 t2 = array_new(state, 1);
1223 array_set(state, t2, 0, t1);
1227 c->args += N2I(array_get_total(t1));
1232 # Convert stack object to a tuple
1242 # If stack object is an array, create a new tuple from the array data
1244 # If the stack value is a tuple, leave the stack unmodified
1246 # Otherwise, create a unary tuple from the value on the stack
1251 if(REFERENCE_P(t1) && object_kind_of_p(state, t1, global->array)) {
1252 j = N2I(array_get_total(t1));
1253 t2 = tuple_new(state, j);
1255 for(k = 0; k < j; k++) {
1256 tuple_put(state, t2, k, array_get(state, t1, k));
1259 } else if(!REFERENCE_P(t1) || !object_kind_of_p(state, t1, global->tuple)) {
1260 t2 = tuple_new(state, 1);
1261 tuple_put(state, t2, 0, t1);
1269 # Converts the item on the top of the stack into an argument for a block
1272 # \cast_for_single_block_arg
1280 # The item on the top of the stack is popped, and:
1282 # If it has no fields, the result is nil
1284 # If the item contains a single field, the result is the value in the
1287 # If the item is a tuple, the result is an array created from the tuple.
1289 # The result is then pushed onto the stack.
1291 def cast_for_single_block_arg
1298 stack_push(tuple_at(state, t1, 0));
1300 stack_push(array_from_tuple(state, t1));
1306 # Converts a block argument single-valued tuple into multiple arguments if
1307 # the arg is an array
1309 # \cast_for_multi_block_arg
1311 # * tuple[array[el1,el2,...,eln]]
1314 # * tuple[el1,el2,...,eln]
1317 # If the tuple on the top of the stack has only a single element, and that
1318 # element is an array, a new tuple is created containing the contents of
1319 # the array, and this new tuple is used to update the top of the stack.
1322 # [[1,2,3]].each do |i,j,k|
1327 def cast_for_multi_block_arg
1331 /* If there is only one thing in the tuple... */
1333 t1 = tuple_at(state, t1, 0);
1334 /* and that thing is an array... */
1335 if(RISA(t1, array)) {
1336 /* make a tuple out of the array contents... */
1337 j = N2I(array_get_total(t1));
1338 t2 = tuple_new(state, j);
1340 for(k = 0; k < j; k++) {
1341 tuple_put(state, t2, k, array_get(state, t1, k));
1344 /* and put it on the top o the stack. */
1352 # Create a hash and populate with items on the stack
1365 # * { key1 => value1, key2 => value2, ..., keyN => valueN }
1368 # Creates a new hash, populating its contents with the number of items
1369 # (+argc+) specified in the opcode. The contents of the new hash are taken
1370 # from the stack, with the top item on the stack becoming the last key in
1371 # the hash, the second top item becoming the last value, and so on. The
1372 # resulting hash is added back to the stack.
1377 t1 = hash_new(state);
1382 hash_set(state, t1, t2, t3);
1386 cpu_perform_hook(state, c, BASIC_CLASS(hash),
1387 global->sym_from_literal, t1);
1394 # Sets an instance variable on self
1404 # Pops a value off the stack, and uses it to set the value of the instance
1405 # variable identifies by the literal +ivar+ on the current +self+ object.
1406 # The value popped off the stack is then pushed back on again.
1412 object_set_ivar(state, c->self, _lit, t2);
1418 # Pushes a constant onto the stack
1420 # \push_const constant
1427 # Locates the constant indicated by the literal +constant+ from the
1428 # current context, and pushes it onto the stack. If the constant cannot be
1429 # found in the current context, nothing is pushed onto the stack, and a
1430 # NameError exception is raised.
1433 # engine = RUBY_ENGINE # RUBY_ENGINE is a constant defined by Rubinius
1439 t1 = cpu_const_get_in_context(state, c, _lit);
1440 if(AUTOLOAD_P(t1)) {
1441 cpu_send(state, c, t1, state->global->sym_call, 0, Qnil);
1442 } else if(t1 != Qundef) {
1451 # \find_const constant
1459 # Pops the module or \class +ns+ off the stack, and searches within it's
1460 # namespace for the constant identified by the literal +constant+. If
1461 # found, it is pushed onto the stack; otherwise, nothing is pushed onto
1462 # the stack, and a NameError exception is raised.
1466 # enum = Enumerable::Enumerator(str, :each_byte)
1473 t2 = cpu_const_get_from(state, c, _lit, t1);
1474 if(AUTOLOAD_P(t2)) {
1475 cpu_send(state, c, t2, state->global->sym_call, 0, Qnil);
1476 } else if(t2 != Qundef) {
1483 # Sets a literal to refer to a constant
1493 # Pops an object off the stack, and sets the literal referenced in the
1494 # opcode to refer to the object as a constant. The constant is pushed back
1501 t2 = staticscope_get_module(cpu_current_scope(state, c));
1502 stack_push(cpu_const_set(state, c, _lit, t1, t2));
1507 # Sets the value of a constant under a module
1517 # Pops the new +value+ for a constant identified by the +lit+ index in the
1518 # literals tuple, in the scope of +module+, which is also popped from the
1526 stack_push(cpu_const_set(state, c, _lit, t2, t3));
1531 # Pushes the top level global object onto the stack
1540 # Pushes the top-level global object that represents the top-level
1541 # namespace for constants. Used when a global variable is referenced.
1544 # puts $: # Global variables are looked up on the top-level Globals object
1548 "stack_push(global->object);"
1552 # Sets the enclosing class/module when opening a class/module
1561 # Pops +\class+ off the stack, and uses it as the enclosing scope for
1562 # subsequent \class or module definitions.
1567 # module A # encloser is set to A after this line
1568 # module B # encloser is set to B after this line
1569 # end # encloser is reset to A after this line
1576 cpu_set_encloser_path(state, c, t1);
1581 # Resets the current class/module to the parent class/module
1589 # Resets the current enclosing \class or module to the parent \class or
1590 # module in the enclosing scope path. Used when a \class or module
1591 # definition ends, to \pop up a level in the enclosure stack.
1596 # module A # encloser is set to A after this line
1597 # module B # encloser is set to B after this line
1598 # end # encloser is reset to A after this line
1604 cpu_push_encloser(state, c);
1609 # Creates or re-opens a \class.
1611 # \open_class_under \class
1620 # Creates or re-opens a \class, popping the superclass (or nil) and the
1621 # enclosing \class from the stack. Upon return, the new \class is pushed
1624 # The +\class+ argument to the opcode is the \class literal identifying
1625 # the \class to be opened.
1635 # # Stack transition:
1636 # # [...,A,C] => [...,B]
1639 def open_class_under
1645 t3 = cpu_open_class(state, c, t2, t1, _lit, &created);
1647 if(AUTOLOAD_P(t3)) {
1648 cpu_send(state, c, t3, state->global->sym_call, 0, Qnil);
1649 } else if(t3 != Qundef) {
1651 if(created) cpu_perform_hook(state, c, t3, global->sym_opened_class, t1);
1657 # Creates or re-opens a \class.
1659 # \open_class class_name
1667 # Creates or re-opens a \class, taking the superclass (or nil) from the
1668 # stack. Upon return, the new \class is pushed onto the stack.
1670 # The +class_name+ argument to the opcode is the \class literal
1671 # identifying the \class to be opened.
1674 # * open_class_under
1676 # The enclosing \class (if any) will be the current enclosing \class in
1677 # the current execution context. Typically, this will have been set by
1678 # executing the opcode push_encloser.
1685 # # Stack transition:
1686 # # [...,A] => [...,B]
1693 t2 = staticscope_get_module(cpu_current_scope(state, c));
1695 t3 = cpu_open_class(state, c, t2, t1, _lit, &created);
1697 if(AUTOLOAD_P(t3)) {
1698 cpu_send(state, c, t3, state->global->sym_call, 0, Qnil);
1699 } else if(t3 != Qundef) {
1701 if(created) cpu_perform_hook(state, c, t3, global->sym_opened_class, t1);
1707 # Creates or opens a module nested under another module
1709 # \open_module_under name
1717 # Pops an enclosing \class or module from the stack, and creates or
1718 # re-opens the module identified by the literal +name+. The module is then
1719 # pushed onto the stack.
1722 # module X::Y # Opens module Y under the module X
1726 def open_module_under
1730 t2 = cpu_open_module(state, c, t1, _lit);
1732 if(AUTOLOAD_P(t2)) {
1733 cpu_send(state, c, t2, state->global->sym_call, 0, Qnil);
1741 # Creates or reopens a module
1743 # \open_module module
1750 # Creates or re-opens the module referenced by the literal +module+, and
1751 # pushes it onto the stack.
1756 # module A # Creates module A (or re-opens it if it already exists)
1763 t2 = staticscope_get_module(cpu_current_scope(state, c));
1764 t1 = cpu_open_module(state, c, t2, _lit);
1765 if(AUTOLOAD_P(t1)) {
1766 cpu_send(state, c, t1, state->global->sym_call, 0, Qnil);
1774 # Returns the metaclass for an object
1784 # Pops an object off the stack, obtains it's metaclass (creating it if
1785 # necessary), and pushes it onto the stack.
1787 # An object metaclass is it's singleton class, i.e. the class that is used
1788 # to hold object specific methods. In Rubinius, any object can call the
1789 # +metaclass+ method to obtain its metaclass.
1792 # o.metclass # returns o's metaclass
1798 stack_push(object_metaclass(state, t1));
1803 # Attaches a method definition to an object's singleton \class
1805 # \attach_method name
1814 # Hooks up a compiled method to an object instance via it's singleton
1817 # The object the method is to be added to (+receiver+) and the compiled
1818 # method object (+method+) are popped from the stack, while the name of
1819 # the method is an argument to the opcode (+name+). On return, the
1820 # compiled method is pushed back onto the stack.
1824 # Class/module methods are handled by add_method.
1831 cpu_attach_method(state, c, t1, _lit, t2);
1833 cpu_perform_hook(state, c, t1, global->sym_s_method_added, _lit);
1838 # Adds a method to a \class or module
1849 # Hooks up a compiled method to a \class or module.
1851 # The \class or module the method is to be added to (+receiver+) and the
1852 # compiled method object (+method+) are popped from the stack, while the
1853 # name of the method is an argument to the opcode (+name+). On return, the
1854 # compiled method is pushed back onto the stack.
1858 # Singleton methods are handled by attach_method.
1865 cpu_add_method(state, c, t1, _lit, t2);
1867 cpu_perform_hook(state, c, t1, global->sym_method_added, _lit);
1872 # Activates a cached method on an object in preparation for execution.
1874 # \activate_method argc
1890 # Pops the top five items off the stack, using these to identify the
1891 # object on which to invoke the method (+receiver+), the CompiledMethod
1892 # instance to execute (+method+, i.e. +self+), the number of argments the
1893 # method defines (+size+), the +locals+ currently in scope, and any
1894 # +block+ passed to the method.
1896 # Additionally, the actual arguments to be passed to the method must also
1897 # be on the stack as an array, with the number of actual arguments passed
1898 # (+argc+) specified alongside the opcode; these arguments will be
1899 # consumed from the stack and pushed into locals when the method starts
1902 # When the method returns, the return value will be on top of the stack.
1904 # Used by CompiledMethod#activate.
1909 msg.recv = stack_pop();
1910 msg.method = stack_pop();
1911 msg.module = stack_pop();
1912 msg.args = N2I(stack_pop());
1913 msg.name = cmethod_get_name(msg.method);
1914 t3 = stack_pop(); /* locals */
1915 msg.block = stack_pop();
1917 cpu_activate_method(state, c, &msg);
1919 if(NIL_P(cpu_current_locals(state, c)) || NUM_FIELDS(t3) >= NUM_FIELDS(cpu_current_locals(state, c))) {
1920 cpu_set_locals(state, c, t3);
1928 # Sends a message with no args to a receiver
1930 # \send_method method_name
1938 # Pops an object off the top of the stack (+receiver+), and sends it the no
1939 # arg message +method_name+.
1941 # When the method returns, the return value will be on top of the stack.
1943 # * send_with_arg_register
1945 # This form of send is for methods that take no arguments.
1947 # Make primitives safer by having the opcode be aware of the number of
1948 # args sent. This way we can remove the dependency of primitives being
1949 # embedded in methods.
1953 next_literal_into(msg.send_site);
1954 msg.recv = stack_pop();
1962 # Placeholder for a removed opcode
1970 # Raises an assert failure if used.
1972 # This opcode is used wherever a previously used opcode has been removed.
1973 # It ensures that removing an opcode does not change the numbering of
1974 # succeeding opcodes.
1976 # The same opcode symbol (:unused) and instruction body can be used anywhere
1977 # an opcode has been removed.
1981 sassert(0 && "deprecated opcode was encountered!");
1986 # Sends a message with arguments on the stack
1988 # \send_stack method argc
2000 # Pops the receiver and the block to be passed off the stack, and sends
2001 # the message +method+ with +argc+ arguments. The arguments to the method
2002 # remain on the stack, ready to be converted to locals when the method is
2005 # When the method returns, the return value will be on top of the stack.
2007 # * send_stack_with_block
2009 # This opcode does not pass a block to the receiver; see
2010 # send_stack_with_block for the equivalent op code used when a block is to
2015 next_literal_into(msg.send_site);
2016 msg.recv = stack_pop();
2018 next_int_into(msg.args);
2025 # Sends a message with arguments and a block on the stack
2027 # \send_stack_with_block method argc
2040 # Pops the receiver +receiver+ and a block off the stack, and sends the
2041 # message +method+ with +argc+ arguments. The arguments to the method
2042 # remain on the stack, ready to be converted to locals as part of method
2045 # When the method returns, the return value will be on top of the stack.
2049 # This opcode passes a block to the receiver; see send_stack for the
2050 # equivalent op code used when no block is to be passed.
2052 def send_stack_with_block
2054 next_literal_into(msg.send_site);
2055 msg.recv = stack_pop();
2056 msg.block = stack_pop();
2057 next_int_into(msg.args);
2064 # Sends a message with args to a receiver
2066 # \send_with_arg_register method
2079 # Pops the receiver +receiver+ and a block +block+ off the top of the stack,
2080 # and sends the message +method+. The number of arguments taken by the
2081 # method must have previously been set in the args register, and the arg
2082 # values themselves remain on the top of the stack, to be converted to
2083 # locals as part of method activation.
2085 # When the method returns, the return value will be on top of the stack.
2089 # * cast_array_for_args
2091 # The number of arguments to be passed to the method in +args+ must have
2092 # been set previously via a call to either set_args or
2093 # cast_array_for_args.
2095 def send_with_arg_register
2097 next_literal_into(msg.send_site);
2098 msg.recv = stack_pop();
2099 msg.block = stack_pop();
2104 msg.priv = c->call_flags;
2105 msg.klass = _real_class(state, msg.recv);
2109 cpu_send_message(state, c, &msg);
2114 # Call a method on the superclass with a block
2116 # \send_super_stack_with_block method argc
2128 # Pops a block off the stack, and sends the message +method+ with +argc+
2129 # arguments. The arguments to the method remain on the stack, ready to be
2130 # converted into locals when the method is activated.
2132 # When the method returns, the return value will be on top of the stack.
2134 # The receiver is not specified for a call to super; it is the superclass
2135 # of the current object that will receive the message.
2137 def send_super_stack_with_block
2143 goto perform_super_send;
2148 # Call a method on the superclass, passing args plus a block
2150 # \send_super_with_arg_register method
2162 # Pops a block off the stack, and sends the message +method+ to the current
2163 # objects superclass. The arguments to the method areleft on the top of
2164 # the stack, ready to be converted into locals when the method is
2167 # When the method returns, the return value will be on top of the stack.
2170 # * cast_array_for_args
2172 # The args register must have previously been set to the count of the
2173 # number of arguments in +args+ via either set_args or
2174 # cast_array_for_args.
2176 def send_super_with_arg_register
2183 msg.send_site = _lit;
2185 msg.block = stack_pop();
2189 msg.klass = class_get_superclass(cpu_current_module(state, c));
2191 cpu_send_message(state, c, &msg);
2196 # Calls the method specified on the top of the stack on an object
2212 # Pops the name of the method +method+ to call off the stack, and if
2213 # necessary, converts it to a symbol. Then pops +block+ and the receiver
2214 # +receiver+ off the stack. Any arguments required by the method must have
2215 # been placed on the stack previously, and the number of arguments set in
2216 # the args register. The arguments will be popped from the stack and
2217 # converted to locals when the method is activated.
2219 # When the method returns, the return value will be on top of the stack.
2222 # * cast_array_for_args
2224 # The number of arguments to be passed to the method in +args+ must have
2225 # been set previously via a call to either set_args or
2226 # cast_array_for_args.
2232 if(RISA(t3, string)) {
2233 t3 = string_to_sym(state, t3);
2238 _lit = global->sym_send;
2252 # Locates a method by searching the \class hierarchy from a specified
2265 # Pops a flag indicating whether or not to search in private methods, the
2266 # method name, and the object to search from off the stack. If a matching
2267 # method is located, it is pushed onto the stack; otherwise, nil is pushed
2272 t1 = stack_pop(); // include_private
2273 t2 = stack_pop(); // meth
2274 t3 = stack_pop(); // self
2275 stack_push(cpu_locate_method_on(state, c, t3, t2, t1));
2280 # Implementation of + optimised for fixnums
2282 # \meta_send_op_plus
2291 # Pops +value1+ and +value2+ off the stack, and pushes the logical result
2292 # of (+value1+ + +value2+). If +value1+ and +value2+ are both fixnums, the
2293 # addition is done directly via the fixnum_add primitive; otherwise, the +
2294 # method is called on +value1+, passing +value2+ as the argument.
2296 def meta_send_op_plus
2300 if(FIXNUM_P(t1) && FIXNUM_P(t2)) {
2301 stack_set_top(fixnum_add(state, t1, t2));
2303 _lit = global->sym_plus;
2306 goto perform_no_ss_send;
2312 # Implementation of - optimised for fixnums
2314 # \meta_send_op_minus
2323 # Pops +value1+ and +value2+ off the stack, and pushes the logical result
2324 # of (+value1+ - +value2+). If +value1+ and +value2+ are both fixnums, the
2325 # subtraction is done directly via the fixnum_sub primitive; otherwise,
2326 # the - method is called on +value1+, passing +value2+ as the argument.
2328 def meta_send_op_minus
2332 if(FIXNUM_P(t1) && FIXNUM_P(t2)) {
2333 stack_set_top(fixnum_sub(state, t1, t2));
2335 _lit = global->sym_minus;
2338 goto perform_no_ss_send;
2344 # Implementation of == optimised for fixnums and symbols
2346 # \meta_send_op_equal
2355 # Pops +value1+ and +value2+ off the stack, and pushes the logical result
2356 # of (+value1+ == +value2+). If +value1+ and +value2+ are both fixnums or
2357 # both symbols, the comparison is done directly; otherwise, the == method
2358 # is called on +value1+, passing +value2+ as the argument.
2360 def meta_send_op_equal
2364 /* If both are not references, compare them directly. */
2365 if(!REFERENCE_P(t1) && !REFERENCE_P(t2)) {
2366 stack_set_top((t1 == t2) ? Qtrue : Qfalse);
2368 _lit = global->sym_equal;
2371 goto perform_no_ss_send;
2377 # Implementation of != optimised for fixnums and symbols
2379 # \meta_send_op_nequal
2388 # Pops +value1+ and +value2+ off the stack, and pushes the logical result
2389 # of !(+value1+ == +value2+). If +value1+ and +value2+ are both fixnums or
2390 # both symbols, the comparison is done directly; otherwise, the != method
2391 # is called on +value1+, passing +value2+ as the argument.
2393 # Is this correct? Shouldn't the non-optimised case call ==, and negate
2396 def meta_send_op_nequal
2400 /* If both are not references, compare them directly. */
2401 if(!REFERENCE_P(t1) && !REFERENCE_P(t2)) {
2402 stack_set_top((t1 == t2) ? Qfalse : Qtrue);
2404 _lit = global->sym_nequal;
2407 goto perform_no_ss_send;
2413 # Implementation of === (triple \equal) optimised for fixnums and symbols
2415 # \meta_send_op_tequal
2424 # Pops +value1+ and +value2+ off the stack, and pushes the logical result
2425 # of (+value1+ === +value2+). If +value1+ and +value2+ are both fixnums or
2426 # both symbols, the comparison is done directly; otherwise, the === method
2427 # is called on +value1+, passing +value2+ as the argument.
2429 # Exactly like equal, except calls === if it can't handle it directly.
2431 def meta_send_op_tequal
2435 /* If both are fixnums, or both are symbols, compare the ops directly. */
2436 if((FIXNUM_P(t1) && FIXNUM_P(t2)) || (SYMBOL_P(t1) && SYMBOL_P(t2))) {
2437 stack_set_top((t1 == t2) ? Qtrue : Qfalse);
2439 _lit = global->sym_tequal;
2442 goto perform_no_ss_send;
2448 # Implementation of < optimised for fixnums
2459 # Pops +value1+ and +value2+ off the stack, and pushes the logical result
2460 # of (+value1+ < +value2+). If +value1+ and +value2+ are both fixnums, the
2461 # comparison is done directly; otherwise, the < method is called on
2462 # +value1+, passing +value2+ as the argument.
2468 if(FIXNUM_P(t1) && FIXNUM_P(t2)) {
2471 stack_set_top((j < k) ? Qtrue : Qfalse);
2473 _lit = global->sym_lt;
2476 goto perform_no_ss_send;
2482 # Implementation of > optimised for fixnums
2493 # Pops +value1+ and +value2+ off the stack, and pushes the logical result
2494 # of (+value1+ > +value2+). If +value1+ and +value2+ are both fixnums, the
2495 # comparison is done directly; otherwise, the > method is called on
2496 # +value1+, passing +value2+ as the argument.
2502 if(FIXNUM_P(t1) && FIXNUM_P(t2)) {
2505 stack_set_top((j > k) ? Qtrue : Qfalse);
2507 _lit = global->sym_gt;
2510 goto perform_no_ss_send;
2520 if(REFERENCE_P(t1) && t1->obj_type == BlockEnvType) {
2521 blokenv_call(state, c, t1, _int);
2523 _lit = global->sym_call;
2528 cpu_send(state, c, t1, _lit, j, t2);
2534 # Soft return from a block
2543 # Pops the return value from the stack, and returns to the calling method
2544 # or block. The return value is pushed onto the stack of the caller during
2551 # Unlike ret, this return opcode does not consider non-local returns. It
2552 # simply returns to the calling block or method context. Thus, it is used
2553 # when, for example, breaking from a loop, or upon the normal completion
2559 cpu_simple_return(state, c, t1);
2564 # Raises an exception
2573 # Pops an exception instance +exception+ off the stack, and uses it to
2574 # raise an exception in the machine.
2579 cpu_raise_exception(state, c, t1);
2584 # Simple return from a method (only)
2593 # Pops the top value from the stack, and uses it as the return value from
2601 # \sret is an optimised version of the more general ret. It works only
2602 # with method (MethodContext) returns, but as a result, can skip the
2603 # extra work to figure out how to long return from a block.
2608 cpu_simple_return(state, c, t1);
2613 # Shifts the first item in a tuple onto the stack
2617 # * [value1, value2, ..., valueN]
2621 # * [value2, ..., valueN]
2624 # Pops a tuple off the top of the stack. If the tuple is empty, the tuple
2625 # is pushed back onto the stack, followed by nil. Otherwise, the tuple is
2626 # shifted, with the tuple then pushed back onto the stack, followed by the
2627 # item that was previously at the head of the tuple.
2629 # This opcode is poorly named; it actually performs a shift, rather than
2635 sassert(REFERENCE_P(t1));
2636 if(NUM_FIELDS(t1) == 0) {
2640 j = NUM_FIELDS(t1) - 1;
2641 t3 = tuple_at(state, t1, 0);
2642 t2 = tuple_new(state, j);
2643 object_copy_fields_from(state, t1, t2, 1, j);
2651 # Converts multiple individual caller arguments into an array for a rest
2662 # * [rest1, rest2, ..., restN]
2665 # Pops 0 or more rest arguments from the top of the stack into an array to
2666 # be used as a rest argument to a method whose last (non-block) parameter
2669 # The number of arguments to place into the rest array is determined by
2670 # how many actual args have been passed to the method, less the number of
2671 # arguments +argc+ required by the method. If this is less than or \equal to
2672 # 0, an empty array is pushed onto the stack. If the number is greater
2673 # than 0, arguments are popped from the stack so that the first rest arg
2674 # is at the start of the array, and the last rest arg is at the end.
2676 # This opcode is performed after the non-splat arguments have been dealt
2677 # with, so that the top of the stack contains the first rest argument
2678 # (remembering that arguments are pushed onto the stack in right to left
2688 # # In foo, c = [3,4,5]
2689 # # On the top of the stack after this opcode is [3,4,5]
2695 j = cpu_current_argcount(c) - _int;
2697 t1 = array_new(state, j);
2698 for(k = 0; k < j; k++) {
2699 array_set(state, t1, k, stack_pop());
2706 # Converts multiple individual caller arguments into an array for a rest
2709 # \make_rest_fp argc
2713 # * [rest1, rest2, ..., restN]
2716 # Copies multiple individual arguments to a method from the caller's stack
2717 # into an array to be used as a rest argument. Used when the method to be
2718 # called has a rest argument (i.e. the last defined method parameter is a
2721 # The number of arguments to place into the rest array is determined by
2722 # how many actual args have been passed to the method, less the number of
2723 # arguments +argc+ required by the method. If this is less than or \equal to
2724 # 0, an empty array is pushed onto the stack. If the number is greater
2725 # than 0, arguments are copied from before the frame pointer into the
2726 # array, so that the first rest arg is at the start of the array, and the
2727 # last rest arg is at the end.
2736 # # In foo, c = [3,4,5]
2737 # # On the top of the stack after this opcode is [3,4,5]
2743 j = cpu_current_argcount(c) - _int;
2745 t1 = array_new(state, j);
2746 for(k = _int, m = 0; k < cpu_current_argcount(c); k++, m++) {
2747 array_set(state, t1, m, c->stack_top[c->fp - k]);
2754 # Verify the number of arguments is between the acceptable range
2756 # \check_argcount min max
2762 # If the number of arguments is less than +min+, or greater than +max+, an
2763 # ArgumentError is raised.
2771 if(cpu_current_argcount(c) < (unsigned long int)j) {
2772 cpu_raise_arg_error(state, c, cpu_current_argcount(c), j);
2773 } else if(_int >= 0 && cpu_current_argcount(c) > (unsigned long int)_int) {
2774 cpu_raise_arg_error(state, c, cpu_current_argcount(c), _int);
2780 # Test to determine whether an argument was passed
2789 # Checks if the number of arguments passed to a method is greater than the
2790 # specified argument index +index+ (0-based), and pushes the result of the
2791 # test onto the stack.
2796 if((unsigned long int)_int < cpu_current_argcount(c)) {
2805 # Test to determine whether a block argument was passed
2807 # \passed_blockarg index
2814 # Checks if a block was passed to a method, and pushes the result of the
2815 # test onto the stack.
2820 if((unsigned long int)_int == c->blockargs) {
2829 # Appends two stings together to form a single string
2840 # Pops two strings off the stack, appends the second to the first, and
2841 # then pushes the combined string back onto the stack.
2843 # The original string is modified by the append.
2849 string_append(state, t1, t2);
2855 # Create a new string with the same contents as the string currently on
2866 # Consume the string on the stack, replacing it with a duplicate. Mutating
2867 # operations on the original string will not affect the duplicate, and
2873 stack_push(string_dup(state, t1));
2878 # Sets the number of args from the stack
2887 # Pops a fixnum off the top of the stack, and uses its value to set the
2888 # argument count for a method prior to executing it.
2890 # * send_with_arg_register
2891 # * send_super_with_arg_register
2893 # Used prior to send_with_arg_register and send_super_with_arg_register to
2894 # set the number of arguments being passed to a method.
2904 # Pushes the number of arguments passed to a method onto the stack
2913 # Pushes the number of arguments +argc+ actually passed to a method onto
2920 stack_push(I2N(c->args));
2925 # Sets call flags prior to a send operation
2927 # \set_call_flags flags
2933 # The call flags on the current execution context are set to the opcode
2936 # Currently, the only call flag is 1, which instructs the machine to
2937 # include private methods when looking for a method that responds to a
2943 c->call_flags = _int;
2948 # Creates a compiler2 style block
2958 # Pops +compiled_method+ off of the stack, and converts it into a
2959 # block environment +block_env+, which is then pushed back onto the stack.
2963 # This opcode replaces create_block, which is used under compiler1, but
2964 # deprecated under compiler2. Unlike create_block which uses the same
2965 # instruction sequence as the enclosing method context, \create_block2
2966 # takes its own instruction sequence in the form of a compiled method.
2970 t1 = stack_pop(); /* the method */
2971 t4 = c->active_context;
2974 if(block_context_p(state, t4)) {
2975 t3 = blokctx_home(state, t4);
2980 methctx_reference(state, t4);
2981 methctx_reference(state, t3);
2983 cmethod_set_staticscope(t1,
2984 cmethod_get_staticscope(cpu_current_method(state, c)));
2986 t2 = blokenv_s_under_context2(state, t1, t3, t4);
2992 # Evaluate if +object+ is an instance of +\class+ or of an ancestor of
3004 # Evaluate if the object is created by +\class+, its parent, or a further
3005 # ancestor. This differs from +instance_of+ in that the \class heirarchy
3006 # will be evaluated rather than just the \class object given.
3023 # Evaluate if +object+ is an instance of +class+
3034 # If the object is an instance of +\class+ return the special value +true+,
3035 # otherwise return +false+. This check is different than +kind_of+ in that
3036 # it does not evaluate superclass relationships. Instance-specific
3037 # subtyping via metaclasses are ignored in computing the parent \class.
3045 if(object_class(state, t1) == t2) {
3054 # Pauses execution and yields to the debugger
3062 # Pauses virtual machine execution at the \yield_debugger instruction, and
3063 # yields control to the debugger on the debug channel. If no debugger is
3064 # registered, an error is raised.
3066 # The \yield_debugger instruction is VM plumbing that exists to support
3067 # "full-speed" debugging. As such, it is not output by the compiler, but
3068 # rather is used by the debugger to replace an existing instruction at a
3069 # breakpoint. Prior to encountering a \yield_debugger instruction, the VM
3070 # will execute normally, i.e. at full speed, and not be slowed
3071 # significantly by the fact that a debugger is attached.
3073 # When the debugger is yielded to by this instruction, it can examine the
3074 # execution context, stack, etc, or replace the \yield_debugger instruction
3075 # with the original instruction at that point, and then step through the
3080 cpu_yield_debugger(state, c);
3085 # Return true if value is a Fixnum, otherwise false
3095 # Consume the value on the stack, and put the special values true or false
3096 # depending on whether the consumed value was of Fixnum type
3101 stack_push(FIXNUM_P(t1) ? Qtrue : Qfalse);
3106 # Return true if value is a Symbol, otherwise false
3116 # Consume the value on the stack, and put the special values true or false
3117 # depending on whether the consumed value was of Symbol type
3122 stack_push(SYMBOL_P(t1) ? Qtrue : Qfalse);
3127 # Return true if value is nil, otherwise false
3137 # Consume the value on the stack, and put the special values true or false
3138 # depending on whether the consumed value was the special value nil
3143 stack_push(t1 == Qnil ? Qtrue : Qfalse);
3148 # Get the \class for the specified object
3158 # Consume the object reference on the stack, and push a reference to the
3159 # parent \class in its place.
3164 stack_push(object_class(state, t1));
3169 # Perform a raw comparison of two object references
3180 # Performs a comparison of two objects, resulting in either +true+ or
3181 # +false+ being pushed onto the stack as a result. The comparison is done
3182 # without any method calls.
3184 # For two Fixnums, two Symbols, or two literals (+true+, +false+, +nil+),
3185 # return +true+ if the values are identical.
3187 # For two object references (including Bignum), return +true+ if value1
3188 # and value2 point to the same instance.
3194 stack_push(t1 == t2 ? Qtrue : Qfalse);
3199 # Checks if the specified method serial number matches an expected value
3201 # \check_serial method serial
3209 # Pops an object off the stack, and determines whether the serial number
3210 # of the method identified by the literal +method+ is the same as the
3211 # expected value +serial+. The result is pushed back on the stack as the
3212 # value +true+ or +false+.
3214 # This opcode is typically used to determine at runtime whether an
3215 # optimisation can be performed. At compile time, two code paths are
3216 # generated: a slow, but guaranteed correct path, and a fast path that
3217 # uses certain optimisations. The serial number check is then performed at
3218 # runtime to determine which code path is executed.
3220 # For example, a method such as Fixnum#times can be optimised at compile
3221 # time, but we can't know until runtime whether or not the Fixnum#times
3222 # method has been overridden. The serial number check is used to determine
3223 # each time the code is executed, whether or not the standard Fixnum#times
3224 # has been overridden. It leverages the serial number field on a
3225 # CompiledMethod, is initialised to either 0 (for kernel land methods) or
3226 # 1 (for user land methods).
3233 stack_push(cpu_check_serial(state, c, t1, _lit, _int));
3239 si = ShotgunInstructions.new
3240 si.generate_declarations(STDOUT)
3241 si.generate_switch(STDOUT)
3243 File.open("instruction_names.c","w") do |f|
3244 f.puts si.generate_names
3247 File.open("instruction_names.h","w") do |f|
3248 f.puts si.generate_names_header
3251 File.open("instruction_funcs.gen", "w") do |f|
3252 f.puts si.generate_dter
3255 File.open("instruction_dt.gen", "w") do |f|
3256 si.generate_declarations(f)
3257 si.generate_threaded(f)