* vm_dump.c (debug_print_pre): fix to show control frame count.

* insns.def (opt_call_c_function): fix operand type.
* lib/vm/instruction.rb: ditto.
* insnhelper.ci (vm_push_frame, vm_pop_frame): fix to show
  control stack status on if VMDEBUG == 2.
* vm.h: add a comment about VMDEBUG.
* iseq.c (find_prev_line_no): fix to skip bug report if
  line is not found.
* lib/vm/instruction.rb: fix to use build_string() on
  source code generators.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12922 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ko1 2007-08-12 19:09:15 +00:00
Родитель 99b51f6020
Коммит b1c5d848f8
6 изменённых файлов: 198 добавлений и 145 удалений

Просмотреть файл

@ -1,3 +1,22 @@
Mon Aug 13 04:02:29 2007 Koichi Sasada <ko1@atdot.net>
* vm_dump.c (debug_print_pre): fix to show control frame count.
* insns.def (opt_call_c_function): fix operand type.
* lib/vm/instruction.rb: ditto.
* insnhelper.ci (vm_push_frame, vm_pop_frame): fix to show
control stack status on if VMDEBUG == 2.
* vm.h: add a comment about VMDEBUG.
* iseq.c (find_prev_line_no): fix to skip bug report if
line is not found.
* lib/vm/instruction.rb: fix to use build_string() on
source code generators.
Mon Aug 13 03:57:32 2007 Koichi Sasada <ko1@atdot.net> Mon Aug 13 03:57:32 2007 Koichi Sasada <ko1@atdot.net>
* template/yasmdata.rb.tmpl: fix type and name. * template/yasmdata.rb.tmpl: fix type and name.

Просмотреть файл

@ -1059,9 +1059,9 @@ defineclass
default: default:
rb_bug("unknown defineclass type: %d", (int)define_type); rb_bug("unknown defineclass type: %d", (int)define_type);
} }
COPY_CREF(klass_iseq->cref_stack, vm_cref_push(th, klass, NOEX_PUBLIC)); COPY_CREF(klass_iseq->cref_stack, vm_cref_push(th, klass, NOEX_PUBLIC));
/* enter scope */ /* enter scope */
vm_push_frame(th, klass_iseq, vm_push_frame(th, klass_iseq,
FRAME_MAGIC_CLASS, klass, (VALUE) GET_DFP() | 0x02, FRAME_MAGIC_CLASS, klass, (VALUE) GET_DFP() | 0x02,
@ -2096,12 +2096,10 @@ opt_regexpmatch2
*/ */
DEFINE_INSN DEFINE_INSN
opt_call_c_function opt_call_c_function
(VALUE func) (rb_insn_func_t funcptr)
() ()
() ()
{ {
rb_insn_func_t funcptr = (rb_insn_func_t) func;
reg_cfp = (funcptr)(th, reg_cfp); reg_cfp = (funcptr)(th, reg_cfp);
if (reg_cfp == 0) { if (reg_cfp == 0) {

8
iseq.c
Просмотреть файл

@ -568,7 +568,9 @@ find_prev_line_no(rb_iseq_t *iseqdat, unsigned long pos)
} }
} }
} }
rb_bug("find_prev_line_no: can't find - %lu", pos);
/* rb_bug("find_prev_line_no: can't find - %lu", pos); */
return 0; return 0;
} }
@ -665,6 +667,10 @@ insn_operand_intern(rb_iseq_t *iseq,
ret = rb_str_new2("<cdhash>"); ret = rb_str_new2("<cdhash>");
break; break;
case TS_FUNCPTR:
ret = rb_str_new2("<funcptr>");
break;
default: default:
rb_bug("ruby_iseq_disasm: unknown operand type: %c", type); rb_bug("ruby_iseq_disasm: unknown operand type: %c", type);
} }

Просмотреть файл

@ -638,6 +638,22 @@ module RubyVM
@insns.use_const? @insns.use_const?
end end
def build_string
@lines = []
yield
@lines.join("\n")
end
EMPTY_STRING = ''.freeze
def commit str = EMPTY_STRING
@lines << str
end
def comment str
@lines << str if verbose?
end
def output_path(fn) def output_path(fn)
d = @insns.destdir d = @insns.destdir
fn = File.join(d, fn) if d fn = File.join(d, fn) if d
@ -667,19 +683,21 @@ module RubyVM
private private
def make_header_prepare_stack insn def make_header_prepare_stack insn
ret = [] comment " /* prepare stack status */"
push_ba = insn.pushsc push_ba = insn.pushsc
raise "unsupport" if push_ba[0].size > 0 && push_ba[1].size > 0 raise "unsupport" if push_ba[0].size > 0 && push_ba[1].size > 0
push_ba.each{|pushs| push_ba.each{|pushs|
pushs.each{|r| pushs.each{|r|
ret << " PUSH(SCREG(#{r}));" commit " PUSH(SCREG(#{r}));"
} }
} }
ret.join("\n") + "\n"
end end
def make_header_operands insn def make_header_operands insn
comment " /* declare and get from iseq */"
vars = insn.opes vars = insn.opes
n = 0 n = 0
ops = [] ops = []
@ -696,40 +714,39 @@ module RubyVM
# reverse or not? # reverse or not?
# ops.join # ops.join
ops.reverse.join("\n") + "\n" commit ops.reverse
end end
def make_header_default_operands insn def make_header_default_operands insn
ret = []
vars = insn.defopes vars = insn.defopes
vars.each{|e| vars.each{|e|
next if e[1] == '*' next if e[1] == '*'
if use_const? if use_const?
ret << " const #{e[0][0]} #{e[0][1]} = #{e[1]};" commit " const #{e[0][0]} #{e[0][1]} = #{e[1]};"
else else
ret << " #define #{e[0][1]} #{e[1]}" commit " #define #{e[0][1]} #{e[1]}"
end end
} }
ret.join("\n") + "\n"
end end
def make_footer_default_operands insn def make_footer_default_operands insn
comment " /* declare and initialize default opes */"
if use_const? if use_const?
"\n" commit
else else
ret = []
vars = insn.defopes vars = insn.defopes
vars.each{|e| vars.each{|e|
next if e[1] == '*' next if e[1] == '*'
ret << "#undef #{e[0][1]}\n" commit "#undef #{e[0][1]}"
} }
ret.join("\n") + "\n"
end end
end end
def make_header_stack_pops insn def make_header_stack_pops insn
comment " /* declare and pop from stack */"
n = 0 n = 0
pops = [] pops = []
vars = insn.pops vars = insn.pops
@ -748,119 +765,118 @@ module RubyVM
@popn = n @popn = n
# reverse or not? # reverse or not?
pops.reverse.join("\n") + "\n" commit pops.reverse
end end
def make_header_temporary_vars insn def make_header_temporary_vars insn
ret = [] comment " /* declare temporary vars */"
insn.tvars.each{|var| insn.tvars.each{|var|
ret << " #{var[0]} #{var[1]};" commit " #{var[0]} #{var[1]};"
} }
ret.join("\n") + "\n"
end end
def make_header_stack_val insn def make_header_stack_val insn
ret = [] comment "/* declare stack push val */"
vars = insn.opes + insn.pops + insn.defopes.map{|e| e[0]} vars = insn.opes + insn.pops + insn.defopes.map{|e| e[0]}
insn.rets.each{|var| insn.rets.each{|var|
if vars.all?{|e| e[1] != var[1]} && var[1] != '...' if vars.all?{|e| e[1] != var[1]} && var[1] != '...'
ret << " #{var[0]} #{var[1]};" commit " #{var[0]} #{var[1]};"
end end
} }
ret.join("\n") + "\n" end
def make_header_analysys insn
commit " USAGE_ANALYSIS_INSN(BIN(#{insn.name}));"
insn.opes.each_with_index{|op, i|
commit " USAGE_ANALYSIS_OPERAND(BIN(#{insn.name}), #{i}, #{op[1]});"
}
end
def make_header_pc insn
commit " ADD_PC(1+#{@opn});"
commit " PREFETCH(GET_PC());"
end
def make_header_popn insn
comment " /* management */"
commit " POPN(#{@popn});" if @popn > 0
end
def make_hader_debug insn
comment " /* for debug */"
commit " DEBUG_ENTER_INSN(\"#{insn.name}\");"
end
def make_header_defines insn
commit " #define CURRENT_INSN_#{insn.name} 1"
commit " #define INSN_IS_SC() #{insn.sc ? 0 : 1}"
commit " #define INSN_LABEL(lab) LABEL_#{insn.name}_##lab"
commit " #define LABEL_IS_SC(lab) LABEL_##lab##_###{insn.sc.size == 0 ? 't' : 'f'}"
end end
def make_footer_stack_val insn def make_footer_stack_val insn
ret = [] comment " /* push stack val */"
insn.rets.reverse_each{|v| insn.rets.reverse_each{|v|
if v[1] == '...' if v[1] == '...'
break break
end end
if v[2] if v[2]
ret << " SCREG(#{v[2]}) = #{v[1]};" commit " SCREG(#{v[2]}) = #{v[1]};"
else else
ret << " PUSH(#{v[1]});" commit " PUSH(#{v[1]});"
end end
} }
ret.join("\n") + "\n"
end
def make_header_analysys insn
ret = " USAGE_ANALYSIS_INSN(BIN(#{insn.name}));\n"
insn.opes.each_with_index{|op, i|
ret += " USAGE_ANALYSIS_OPERAND(BIN(#{insn.name}), #{i}, #{op[1]});\n"
}
ret
end end
def make_header_analysys insn def make_footer_undefs insn
ret = " USAGE_ANALYSIS_INSN(BIN(#{insn.name}));\n" commit "#undef CURRENT_INSN_#{insn.name}"
insn.opes.each_with_index{|op, i| commit "#undef INSN_IS_SC"
ret += " USAGE_ANALYSIS_OPERAND(BIN(#{insn.name}), #{i}, #{op[1]});\n" commit "#undef INSN_LABEL"
} commit "#undef LABEL_IS_SC"
ret
end end
def make_header insn def make_header insn
ret = "\nINSN_ENTRY(#{insn.name}){\n" commit "INSN_ENTRY(#{insn.name}){"
ret += " /* prepare stack status */\n" if verbose? make_header_prepare_stack insn
ret += make_header_prepare_stack insn commit "{"
ret += "{\n" make_header_stack_val insn
ret += " /* declare stack push val */\n" if verbose? make_header_default_operands insn
ret += make_header_stack_val insn make_header_operands insn
ret += " /* declare and initialize default opes */\n" if verbose? make_header_stack_pops insn
ret += make_header_default_operands insn make_header_temporary_vars insn
ret += " /* declare and get from iseq */\n" if verbose? #
ret += make_header_operands insn make_hader_debug insn
ret += " /* declare and pop from stack */\n" if verbose? make_header_pc insn
ret += make_header_stack_pops insn make_header_popn insn
ret += " /* declare temporary vars */\n" if verbose? make_header_defines insn
ret += make_header_temporary_vars insn make_header_analysys insn
commit "{"
ret += " /* for debug */\n" if verbose?
ret += " DEBUG_ENTER_INSN(\"#{insn.name}\");\n"
ret += " /* management */\n" if verbose?
ret += " ADD_PC(1+#{@opn});\n"
ret += " PREFETCH(GET_PC());\n"
ret += " POPN(#{@popn});\n" if @popn > 0
ret += " #define CURRENT_INSN_#{insn.name} 1\n"
ret += " #define INSN_IS_SC() #{insn.sc ? 0 : 1}\n"
ret += " #define INSN_LABEL(lab) LABEL_#{insn.name}_##lab\n"
ret += " #define LABEL_IS_SC(lab) LABEL_##lab##_###{insn.sc.size == 0 ? 't' : 'f'}\n"
ret += make_header_analysys insn
ret += "{\n"
end end
def make_footer insn def make_footer insn
ret = '' make_footer_stack_val insn
ret = " /* push stack val */\n" if verbose? make_footer_default_operands insn
ret += make_footer_stack_val insn make_footer_undefs insn
# debug info commit " END_INSN(#{insn.name});}}}"
# epilogue
ret += make_footer_default_operands insn
ret += "#undef CURRENT_INSN_#{insn.name}\n"
ret += "#undef INSN_IS_SC\n"
ret += "#undef INSN_LABEL\n"
ret += "#undef LABEL_IS_SC\n"
ret += " END_INSN(#{insn.name});\n}}\n"
ret += "}\n"
end end
def make_insn_def insn def make_insn_def insn
ret = make_header insn build_string do
if line = insn.body.instance_variable_get(:@line_no) make_header insn
file = insn.body.instance_variable_get(:@file) if line = insn.body.instance_variable_get(:@line_no)
ret << "#line #{line+1} \"#{file}\"" << "\n" file = insn.body.instance_variable_get(:@file)
ret << insn.body commit "#line #{line+1} \"#{file}\""
ret << '#line __CURRENT_LINE__ "__CURRENT_FILE__"' << "\n" commit insn.body
else commit '#line __CURRENT_LINE__ "__CURRENT_FILE__"'
ret << insn.body else
insn.body
end
make_footer(insn)
end end
ret << make_footer(insn)
end end
end end
@ -868,15 +884,19 @@ module RubyVM
# vmtc.inc # vmtc.inc
class VmTCIncGenerator < SourceCodeGenerator class VmTCIncGenerator < SourceCodeGenerator
def generate def generate
insns_table = ''
insns_end_table = ''
@insns.each{|insn| insns_table = build_string do
insns_table << " LABEL_PTR(#{insn.name}),\n" @insns.each{|insn|
} commit " LABEL_PTR(#{insn.name}),"
@insns.each{|insn| }
insns_end_table << " ELABEL_PTR(#{insn.name}),\n" end
}
insn_end_table = build_string do
@insns.each{|insn|
commit " ELABEL_PTR(#{insn.name}),\n"
}
end
ERB.new(vpath.read('template/vmtc.inc.tmpl')).result(binding) ERB.new(vpath.read('template/vmtc.inc.tmpl')).result(binding)
end end
end end
@ -915,6 +935,8 @@ module RubyVM
"TS_CDHASH" "TS_CDHASH"
when /^ISEQ/ when /^ISEQ/
"TS_ISEQ" "TS_ISEQ"
when /rb_insn_func_t/
"TS_FUNCPTR"
else else
raise "unknown op type: #{op}" raise "unknown op type: #{op}"
end end
@ -931,7 +953,8 @@ module RubyVM
'TS_IC' => 'C', 'TS_IC' => 'C',
'TS_CDHASH' => 'H', 'TS_CDHASH' => 'H',
'TS_ISEQ' => 'S', 'TS_ISEQ' => 'S',
'TS_VARIABLE' => '.', 'TS_VARIABLE' => '.',
'TS_FUNCPTR' => 'F',
} }
# insns_info.inc # insns_info.inc
@ -986,12 +1009,14 @@ module RubyVM
# insns.inc # insns.inc
class InsnsIncGenerator < SourceCodeGenerator class InsnsIncGenerator < SourceCodeGenerator
def generate def generate
insns = ''
i=0 i=0
@insns.each{|insn| insns = build_string do
insns << " %-30s = %d,\n" % ["BIN(#{insn.name})", i] @insns.each{|insn|
i+=1 commit " %-30s = %d,\n" % ["BIN(#{insn.name})", i]
} i+=1
}
end
ERB.new(vpath.read('template/insns.inc.tmpl')).result(binding) ERB.new(vpath.read('template/insns.inc.tmpl')).result(binding)
end end
end end
@ -1000,13 +1025,14 @@ module RubyVM
# minsns.inc # minsns.inc
class MInsnsIncGenerator < SourceCodeGenerator class MInsnsIncGenerator < SourceCodeGenerator
def generate def generate
defs = ''
i=0 i=0
@insns.each{|insn| defs = build_string do
defs << " rb_define_const(mYarvInsns, %-30s, INT2FIX(%d));\n" % @insns.each{|insn|
["\"I#{insn.name}\"", i] commit " rb_define_const(mYarvInsns, %-30s, INT2FIX(%d));\n" %
i+=1 ["\"I#{insn.name}\"", i]
} i+=1
}
end
ERB.new(vpath.read('template/minsns.inc.tmpl')).result(binding) ERB.new(vpath.read('template/minsns.inc.tmpl')).result(binding)
end end
end end
@ -1032,7 +1058,7 @@ module RubyVM
val val
when /^ID/ when /^ID/
"INT2FIX(#{val})" "INT2FIX(#{val})"
when /^ISEQ/ when /^ISEQ/, /^rb_insn_func_t/
val val
when /GENTRY/ when /GENTRY/
raise raise
@ -1057,39 +1083,42 @@ module RubyVM
opt_insns_map[originsn] << insn opt_insns_map[originsn] << insn
} }
opt_insns_map.each{|originsn, optinsns| rule = build_string do
rule += "case BIN(#{originsn.name}):\n" opt_insns_map.each{|originsn, optinsns|
commit "case BIN(#{originsn.name}):"
optinsns.sort_by{|opti| optinsns.sort_by{|opti|
opti.defopes.find_all{|e| e[1] == '*'}.size opti.defopes.find_all{|e| e[1] == '*'}.size
}.each{|opti| }.each{|opti|
rule += " if(\n" commit " if("
i = 0 i = 0
rule += ' ' + opti.defopes.map{|opinfo| commit " " + opti.defopes.map{|opinfo|
i += 1 i += 1
next if opinfo[1] == '*' next if opinfo[1] == '*'
"insnobj->operands[#{i-1}] == #{val_as_type(opinfo)}\n" "insnobj->operands[#{i-1}] == #{val_as_type(opinfo)}"
}.compact.join('&& ') }.compact.join('&& ')
rule += " ){\n" commit " ){"
idx = 0 idx = 0
n = 0 n = 0
opti.defopes.each{|opinfo| opti.defopes.each{|opinfo|
if opinfo[1] == '*' if opinfo[1] == '*'
if idx != n if idx != n
rule += " insnobj->operands[#{idx}] = insnobj->operands[#{n}];\n" commit " insnobj->operands[#{idx}] = insnobj->operands[#{n}];"
end
idx += 1
else
# skip
end end
idx += 1 n += 1
else }
# skip commit " insnobj->insn_id = BIN(#{opti.name});"
end commit " insnobj->operand_size = #{idx};"
n += 1 commit " break;\n }\n"
} }
rule += " insnobj->insn_id = BIN(#{opti.name});\n" commit " break;";
rule += " insnobj->operand_size = #{idx};\n"
rule += " break;\n }\n"
} }
rule += " break;\n"; end
}
ERB.new(vpath.read('template/optinsn.inc.tmpl')).result(binding) ERB.new(vpath.read('template/optinsn.inc.tmpl')).result(binding)
end end
end end

2
vm.h
Просмотреть файл

@ -31,7 +31,7 @@ extern VALUE ruby_vm_redefined_flag;
* debug level: * debug level:
* 0: no debug output * 0: no debug output
* 1: show instruction name * 1: show instruction name
* 2: * 2: show stack frame when control stack frame is changed
* 3: show stack status * 3: show stack status
* 4: show register * 4: show register
* 5: * 5:

Просмотреть файл

@ -358,6 +358,7 @@ debug_print_pre(rb_thread_t *th, rb_control_frame_t *cfp)
VALUE *seq = iseq->iseq; VALUE *seq = iseq->iseq;
int pc = cfp->pc - iseq->iseq_encoded; int pc = cfp->pc - iseq->iseq_encoded;
printf("%3d ", VM_CFP_CNT(th, cfp));
ruby_iseq_disasm_insn(0, seq, pc, iseq, 0); ruby_iseq_disasm_insn(0, seq, pc, iseq, 0);
} }