summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-10-29 03:21:22 +0000
committershyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-10-29 03:21:22 +0000
commitc80f3f709fc94dac52726b5d9a2f486e6c3be745 (patch)
treef0b76377a91af5378b117e72ffe1223151c2bda8
parent08e47ab98a7b205f64ec89d7dcc7c347b55f0dfe (diff)
less verbose code by sharing attribute definitions
The idea behind this commit is that handles_sp and leaf are two concepts that are not mutually independent. By making one explicitly depend another, we can reduces the number of lines of codes written, thus making things concise. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65426 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--insns.def11
-rwxr-xr-xtool/ruby_vm/models/bare_instructions.rb24
2 files changed, 23 insertions, 12 deletions
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