diff --git a/insns.def b/insns.def index 629a2f1bc9..132ce2f179 100644 --- a/insns.def +++ b/insns.def @@ -44,9 +44,11 @@ `insn_stack_increase`. * handles_sp: If it is true, VM deals with sp in the insn. + Default is if the instruction takes ISEQ operand or not. * leaf: indicates that the instruction is "leaf" i.e. it does - not introduce new stack frame on top of it. Default true. + not introduce new stack frame on top of it. + If an instruction handles sp, that can never be a leaf. - Attributes can access operands, but not stack (push/pop) variables. @@ -357,7 +359,7 @@ putiseq (ISEQ iseq) () (VALUE ret) -// attr bool leaf = true; /* yes it is */ +// attr bool handles_sp = false; /* of course it doesn't */ { ret = (VALUE)iseq; } @@ -713,7 +715,6 @@ defineclass (ID id, ISEQ class_iseq, rb_num_t flags) (VALUE cbase, VALUE super) (VALUE val) -// attr bool handles_sp = true; { VALUE klass = vm_find_or_create_class_by_id(id, flags, cbase, super); @@ -740,7 +741,6 @@ send (CALL_INFO ci, CALL_CACHE cc, ISEQ blockiseq) (...) (VALUE val) -// attr bool handles_sp = true; // attr rb_snum_t sp_inc = - (int)(ci->orig_argc + ((ci->flag & VM_CALL_ARGS_BLOCKARG) ? 1 : 0)); { struct rb_calling_info calling; @@ -757,7 +757,6 @@ opt_send_without_block (CALL_INFO ci, CALL_CACHE cc) (...) (VALUE val) -// attr bool leaf = false; /* Of course it isn't. */ // attr bool handles_sp = true; // attr rb_snum_t sp_inc = -ci->orig_argc; { @@ -828,7 +827,6 @@ invokesuper (CALL_INFO ci, CALL_CACHE cc, ISEQ blockiseq) (...) (VALUE val) -// attr bool handles_sp = true; // attr rb_snum_t sp_inc = - (int)(ci->orig_argc + ((ci->flag & VM_CALL_ARGS_BLOCKARG) ? 1 : 0)); { struct rb_calling_info calling; @@ -845,7 +843,6 @@ invokeblock (CALL_INFO ci) (...) (VALUE val) -// attr bool leaf = false; /* Of course it isn't. */ // attr bool handles_sp = true; // attr rb_snum_t sp_inc = 1 - ci->orig_argc; { diff --git a/tool/ruby_vm/models/bare_instructions.rb b/tool/ruby_vm/models/bare_instructions.rb index 7d9ed6da5a..2767f383e6 100755 --- a/tool/ruby_vm/models/bare_instructions.rb +++ b/tool/ruby_vm/models/bare_instructions.rb @@ -144,6 +144,7 @@ class RubyVM::BareInstructions end def predefine_attributes + # Beware: order matters here because some attribute depends another. generate_attribute 'const char*', 'name', "insn_name(#{bin})" generate_attribute 'enum ruby_vminsn_type', 'bin', bin generate_attribute 'rb_num_t', 'open', opes.size @@ -151,11 +152,24 @@ class RubyVM::BareInstructions generate_attribute 'rb_num_t', 'retn', rets.size generate_attribute 'rb_num_t', 'width', width generate_attribute 'rb_snum_t', 'sp_inc', rets.size - pops.size - generate_attribute 'bool', 'handles_sp', false - generate_attribute 'bool', 'leaf', opes.all? {|o| - # Insn with ISEQ should yield it; can never be a leaf. - o[:type] != 'ISEQ' - } + generate_attribute 'bool', 'handles_sp', default_definition_of_handles_sp + generate_attribute 'bool', 'leaf', default_definition_of_leaf + end + + def default_definition_of_handles_sp + # Insn with ISEQ should yield it; can handle sp. + return opes.any? {|o| o[:type] == 'ISEQ' } + end + + def default_definition_of_leaf + # Insn that handles SP can never be a leaf. + if not has_attribute? 'handles_sp' then + return ! default_definition_of_handles_sp + elsif handles_sp? then + return "! #{call_attribute 'handles_sp'}" + else + return true + end end def typesplit a