summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog19
-rw-r--r--insns.def8
-rw-r--r--iseq.c8
-rw-r--r--lib/vm/instruction.rb307
-rw-r--r--vm.h2
-rw-r--r--vm_dump.c1
6 files changed, 199 insertions, 146 deletions
diff --git a/ChangeLog b/ChangeLog
index 790c2f4cb5..cb9bbc9edc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
* template/yasmdata.rb.tmpl: fix type and name.
diff --git a/insns.def b/insns.def
index c235426748..8a4ba182d8 100644
--- a/insns.def
+++ b/insns.def
@@ -1059,9 +1059,9 @@ defineclass
default:
rb_bug("unknown defineclass type: %d", (int)define_type);
}
-
+
COPY_CREF(klass_iseq->cref_stack, vm_cref_push(th, klass, NOEX_PUBLIC));
-
+
/* enter scope */
vm_push_frame(th, klass_iseq,
FRAME_MAGIC_CLASS, klass, (VALUE) GET_DFP() | 0x02,
@@ -2096,12 +2096,10 @@ opt_regexpmatch2
*/
DEFINE_INSN
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);
if (reg_cfp == 0) {
diff --git a/iseq.c b/iseq.c
index 94e8eeff22..091faef58f 100644
--- a/iseq.c
+++ b/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;
}
@@ -665,6 +667,10 @@ insn_operand_intern(rb_iseq_t *iseq,
ret = rb_str_new2("<cdhash>");
break;
+ case TS_FUNCPTR:
+ ret = rb_str_new2("<funcptr>");
+ break;
+
default:
rb_bug("ruby_iseq_disasm: unknown operand type: %c", type);
}
diff --git a/lib/vm/instruction.rb b/lib/vm/instruction.rb
index 183d6b4b17..5308f5b4a7 100644
--- a/lib/vm/instruction.rb
+++ b/lib/vm/instruction.rb
@@ -638,6 +638,22 @@ module RubyVM
@insns.use_const?
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)
d = @insns.destdir
fn = File.join(d, fn) if d
@@ -667,19 +683,21 @@ module RubyVM
private
def make_header_prepare_stack insn
- ret = []
+ comment " /* prepare stack status */"
+
push_ba = insn.pushsc
raise "unsupport" if push_ba[0].size > 0 && push_ba[1].size > 0
push_ba.each{|pushs|
pushs.each{|r|
- ret << " PUSH(SCREG(#{r}));"
+ commit " PUSH(SCREG(#{r}));"
}
}
- ret.join("\n") + "\n"
end
def make_header_operands insn
+ comment " /* declare and get from iseq */"
+
vars = insn.opes
n = 0
ops = []
@@ -696,40 +714,39 @@ module RubyVM
# reverse or not?
# ops.join
- ops.reverse.join("\n") + "\n"
+ commit ops.reverse
end
def make_header_default_operands insn
- ret = []
vars = insn.defopes
vars.each{|e|
next if e[1] == '*'
if use_const?
- ret << " const #{e[0][0]} #{e[0][1]} = #{e[1]};"
+ commit " const #{e[0][0]} #{e[0][1]} = #{e[1]};"
else
- ret << " #define #{e[0][1]} #{e[1]}"
+ commit " #define #{e[0][1]} #{e[1]}"
end
}
- ret.join("\n") + "\n"
end
def make_footer_default_operands insn
+ comment " /* declare and initialize default opes */"
if use_const?
- "\n"
+ commit
else
- ret = []
vars = insn.defopes
vars.each{|e|
next if e[1] == '*'
- ret << "#undef #{e[0][1]}\n"
+ commit "#undef #{e[0][1]}"
}
- ret.join("\n") + "\n"
end
end
def make_header_stack_pops insn
+ comment " /* declare and pop from stack */"
+
n = 0
pops = []
vars = insn.pops
@@ -748,119 +765,118 @@ module RubyVM
@popn = n
# reverse or not?
- pops.reverse.join("\n") + "\n"
+ commit pops.reverse
end
def make_header_temporary_vars insn
- ret = []
+ comment " /* declare temporary vars */"
+
insn.tvars.each{|var|
- ret << " #{var[0]} #{var[1]};"
+ commit " #{var[0]} #{var[1]};"
}
- ret.join("\n") + "\n"
end
def make_header_stack_val insn
- ret = []
+ comment "/* declare stack push val */"
+
vars = insn.opes + insn.pops + insn.defopes.map{|e| e[0]}
insn.rets.each{|var|
if vars.all?{|e| e[1] != var[1]} && var[1] != '...'
- ret << " #{var[0]} #{var[1]};"
+ commit " #{var[0]} #{var[1]};"
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
def make_footer_stack_val insn
- ret = []
+ comment " /* push stack val */"
+
insn.rets.reverse_each{|v|
if v[1] == '...'
break
end
if v[2]
- ret << " SCREG(#{v[2]}) = #{v[1]};"
+ commit " SCREG(#{v[2]}) = #{v[1]};"
else
- ret << " PUSH(#{v[1]});"
+ commit " PUSH(#{v[1]});"
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
- 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
+ def make_footer_undefs insn
+ commit "#undef CURRENT_INSN_#{insn.name}"
+ commit "#undef INSN_IS_SC"
+ commit "#undef INSN_LABEL"
+ commit "#undef LABEL_IS_SC"
end
def make_header insn
- ret = "\nINSN_ENTRY(#{insn.name}){\n"
- ret += " /* prepare stack status */\n" if verbose?
- ret += make_header_prepare_stack insn
- ret += "{\n"
- ret += " /* declare stack push val */\n" if verbose?
- ret += make_header_stack_val insn
- ret += " /* declare and initialize default opes */\n" if verbose?
- ret += make_header_default_operands insn
- ret += " /* declare and get from iseq */\n" if verbose?
- ret += make_header_operands insn
- ret += " /* declare and pop from stack */\n" if verbose?
- ret += make_header_stack_pops insn
- ret += " /* declare temporary vars */\n" if verbose?
- ret += make_header_temporary_vars insn
-
- 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"
+ commit "INSN_ENTRY(#{insn.name}){"
+ make_header_prepare_stack insn
+ commit "{"
+ make_header_stack_val insn
+ make_header_default_operands insn
+ make_header_operands insn
+ make_header_stack_pops insn
+ make_header_temporary_vars insn
+ #
+ make_hader_debug insn
+ make_header_pc insn
+ make_header_popn insn
+ make_header_defines insn
+ make_header_analysys insn
+ commit "{"
end
def make_footer insn
- ret = ''
- ret = " /* push stack val */\n" if verbose?
- ret += make_footer_stack_val insn
- # debug info
-
- # 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"
+ make_footer_stack_val insn
+ make_footer_default_operands insn
+ make_footer_undefs insn
+ commit " END_INSN(#{insn.name});}}}"
end
def make_insn_def insn
- ret = make_header insn
- if line = insn.body.instance_variable_get(:@line_no)
- file = insn.body.instance_variable_get(:@file)
- ret << "#line #{line+1} \"#{file}\"" << "\n"
- ret << insn.body
- ret << '#line __CURRENT_LINE__ "__CURRENT_FILE__"' << "\n"
- else
- ret << insn.body
+ build_string do
+ make_header insn
+ if line = insn.body.instance_variable_get(:@line_no)
+ file = insn.body.instance_variable_get(:@file)
+ commit "#line #{line+1} \"#{file}\""
+ commit insn.body
+ commit '#line __CURRENT_LINE__ "__CURRENT_FILE__"'
+ else
+ insn.body
+ end
+ make_footer(insn)
end
- ret << make_footer(insn)
end
end
@@ -868,15 +884,19 @@ module RubyVM
# vmtc.inc
class VmTCIncGenerator < SourceCodeGenerator
def generate
- insns_table = ''
- insns_end_table = ''
- @insns.each{|insn|
- insns_table << " LABEL_PTR(#{insn.name}),\n"
- }
- @insns.each{|insn|
- insns_end_table << " ELABEL_PTR(#{insn.name}),\n"
- }
+ insns_table = build_string do
+ @insns.each{|insn|
+ commit " LABEL_PTR(#{insn.name}),"
+ }
+ 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)
end
end
@@ -915,6 +935,8 @@ module RubyVM
"TS_CDHASH"
when /^ISEQ/
"TS_ISEQ"
+ when /rb_insn_func_t/
+ "TS_FUNCPTR"
else
raise "unknown op type: #{op}"
end
@@ -931,7 +953,8 @@ module RubyVM
'TS_IC' => 'C',
'TS_CDHASH' => 'H',
'TS_ISEQ' => 'S',
- 'TS_VARIABLE' => '.',
+ 'TS_VARIABLE' => '.',
+ 'TS_FUNCPTR' => 'F',
}
# insns_info.inc
@@ -986,12 +1009,14 @@ module RubyVM
# insns.inc
class InsnsIncGenerator < SourceCodeGenerator
def generate
- insns = ''
i=0
- @insns.each{|insn|
- insns << " %-30s = %d,\n" % ["BIN(#{insn.name})", i]
- i+=1
- }
+ insns = build_string do
+ @insns.each{|insn|
+ commit " %-30s = %d,\n" % ["BIN(#{insn.name})", i]
+ i+=1
+ }
+ end
+
ERB.new(vpath.read('template/insns.inc.tmpl')).result(binding)
end
end
@@ -1000,13 +1025,14 @@ module RubyVM
# minsns.inc
class MInsnsIncGenerator < SourceCodeGenerator
def generate
- defs = ''
i=0
- @insns.each{|insn|
- defs << " rb_define_const(mYarvInsns, %-30s, INT2FIX(%d));\n" %
- ["\"I#{insn.name}\"", i]
- i+=1
- }
+ defs = build_string do
+ @insns.each{|insn|
+ commit " rb_define_const(mYarvInsns, %-30s, INT2FIX(%d));\n" %
+ ["\"I#{insn.name}\"", i]
+ i+=1
+ }
+ end
ERB.new(vpath.read('template/minsns.inc.tmpl')).result(binding)
end
end
@@ -1032,7 +1058,7 @@ module RubyVM
val
when /^ID/
"INT2FIX(#{val})"
- when /^ISEQ/
+ when /^ISEQ/, /^rb_insn_func_t/
val
when /GENTRY/
raise
@@ -1057,39 +1083,42 @@ module RubyVM
opt_insns_map[originsn] << insn
}
- opt_insns_map.each{|originsn, optinsns|
- rule += "case BIN(#{originsn.name}):\n"
-
- optinsns.sort_by{|opti|
- opti.defopes.find_all{|e| e[1] == '*'}.size
- }.each{|opti|
- rule += " if(\n"
- i = 0
- rule += ' ' + opti.defopes.map{|opinfo|
- i += 1
- next if opinfo[1] == '*'
- "insnobj->operands[#{i-1}] == #{val_as_type(opinfo)}\n"
- }.compact.join('&& ')
- rule += " ){\n"
- idx = 0
- n = 0
- opti.defopes.each{|opinfo|
- if opinfo[1] == '*'
- if idx != n
- rule += " insnobj->operands[#{idx}] = insnobj->operands[#{n}];\n"
+ rule = build_string do
+ opt_insns_map.each{|originsn, optinsns|
+ commit "case BIN(#{originsn.name}):"
+
+ optinsns.sort_by{|opti|
+ opti.defopes.find_all{|e| e[1] == '*'}.size
+ }.each{|opti|
+ commit " if("
+ i = 0
+ commit " " + opti.defopes.map{|opinfo|
+ i += 1
+ next if opinfo[1] == '*'
+ "insnobj->operands[#{i-1}] == #{val_as_type(opinfo)}"
+ }.compact.join('&& ')
+ commit " ){"
+ idx = 0
+ n = 0
+ opti.defopes.each{|opinfo|
+ if opinfo[1] == '*'
+ if idx != n
+ commit " insnobj->operands[#{idx}] = insnobj->operands[#{n}];"
+ end
+ idx += 1
+ else
+ # skip
end
- idx += 1
- else
- # skip
- end
- n += 1
+ n += 1
+ }
+ commit " insnobj->insn_id = BIN(#{opti.name});"
+ commit " insnobj->operand_size = #{idx};"
+ commit " break;\n }\n"
}
- rule += " insnobj->insn_id = BIN(#{opti.name});\n"
- rule += " insnobj->operand_size = #{idx};\n"
- rule += " break;\n }\n"
+ commit " break;";
}
- rule += " break;\n";
- }
+ end
+
ERB.new(vpath.read('template/optinsn.inc.tmpl')).result(binding)
end
end
diff --git a/vm.h b/vm.h
index 0104203892..08bcef03cf 100644
--- a/vm.h
+++ b/vm.h
@@ -31,7 +31,7 @@ extern VALUE ruby_vm_redefined_flag;
* debug level:
* 0: no debug output
* 1: show instruction name
- * 2:
+ * 2: show stack frame when control stack frame is changed
* 3: show stack status
* 4: show register
* 5:
diff --git a/vm_dump.c b/vm_dump.c
index 0f782e68c1..1c54413f39 100644
--- a/vm_dump.c
+++ b/vm_dump.c
@@ -358,6 +358,7 @@ debug_print_pre(rb_thread_t *th, rb_control_frame_t *cfp)
VALUE *seq = iseq->iseq;
int pc = cfp->pc - iseq->iseq_encoded;
+ printf("%3d ", VM_CFP_CNT(th, cfp));
ruby_iseq_disasm_insn(0, seq, pc, iseq, 0);
}