extensive use of instruction attributes

Instead of using magic numbers, let us define a series of attributes
and use them from the VM core.  Proper function declarations makes
these attributes inlined in most modern compilers.  On my machine
exact same binary is generated with or without this changeset.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62085 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
shyouhei 2018-01-29 06:47:05 +00:00
parent 582951e2c8
commit 9a8b38cacf
4 changed files with 30 additions and 30 deletions

View File

@ -2798,6 +2798,7 @@ vm.$(OBJEXT): {$(VPATH)}id.h
vm.$(OBJEXT): {$(VPATH)}id_table.h vm.$(OBJEXT): {$(VPATH)}id_table.h
vm.$(OBJEXT): {$(VPATH)}insns.def vm.$(OBJEXT): {$(VPATH)}insns.def
vm.$(OBJEXT): {$(VPATH)}insns.inc vm.$(OBJEXT): {$(VPATH)}insns.inc
vm.$(OBJEXT): {$(VPATH)}insns_info.inc
vm.$(OBJEXT): {$(VPATH)}intern.h vm.$(OBJEXT): {$(VPATH)}intern.h
vm.$(OBJEXT): {$(VPATH)}internal.h vm.$(OBJEXT): {$(VPATH)}internal.h
vm.$(OBJEXT): {$(VPATH)}io.h vm.$(OBJEXT): {$(VPATH)}io.h

View File

@ -49,15 +49,8 @@ class RubyVM::BareInstructions
end end
def call_attribute name def call_attribute name
return sprintf 'CALL_ATTRIBUTE(%s)', [ return sprintf 'attr_%s_%s(%s)', name, @name, \
name, @name, @opes.map {|i| i[:name] } @opes.map {|i| i[:name] }.compact.join(', ')
].flatten.compact.join(', ')
end
def sp_inc
return @attrs.fetch "sp_inc" do |k|
return generate_attribute k, 'rb_snum_t', rets.size - pops.size
end
end end
def has_attribute? k def has_attribute? k
@ -65,10 +58,6 @@ class RubyVM::BareInstructions
end end
def attributes def attributes
# need to generate predefined attribute defaults
sp_inc
# other_attribute
# ...
return @attrs.values return @attrs.values
end end
@ -120,19 +109,25 @@ class RubyVM::BareInstructions
private private
def generate_attribute k, t, v def generate_attribute t, k, v
attr = RubyVM::Attribute.new \ @attrs[k] ||= RubyVM::Attribute.new \
insn: self, \ insn: self, \
name: k, \ name: k, \
type: t, \ type: t, \
location: [], \ location: [], \
expr: v.to_s + ';' expr: v.to_s + ';'
return @attrs[k] ||= attr return @attrs[k] ||= attr
end end
def predefine_attributes def predefine_attributes
generate_attribute 'sp_inc', 'rb_snum_t', rets.size - pops.size generate_attribute 'const char*', 'name', "insn_name(#{bin})"
generate_attribute 'handles_frame', 'bool', \ generate_attribute 'enum ruby_vminsn_type', 'bin', bin
generate_attribute 'rb_num_t', 'open', opes.size
generate_attribute 'rb_num_t', 'popn', pops.size
generate_attribute 'rb_num_t', 'retn', rets.size
generate_attribute 'rb_num_t', 'width', width
generate_attribute 'rb_num_t', 'sp_inc', rets.size - pops.size
generate_attribute 'bool', 'handles_frame', \
opes.any? {|o| /CALL_INFO/ =~ o[:type] } opes.any? {|o| /CALL_INFO/ =~ o[:type] }
end end

View File

@ -8,9 +8,11 @@
%; %;
/* insn <%= insn.pretty_name %> */ /* insn <%= insn.pretty_name %> */
#define NAME_OF_CURRENT_INSN <%= insn.name %>
INSN_ENTRY(<%= insn.name %>) INSN_ENTRY(<%= insn.name %>)
{ {
%# NAME_OF_CURRENT_INSN is used in vm_exec.h
# define NAME_OF_CURRENT_INSN <%= insn.name %>
# define INSN_ATTR(x) <%= insn.call_attribute(' ## x ## ') %>
% unless insn.declarations.empty? % unless insn.declarations.empty?
<%= insn.declarations.join(";\n ") %>; <%= insn.declarations.join(";\n ") %>;
@ -27,28 +29,29 @@ INSN_ENTRY(<%= insn.name %>)
% insn.pops.reverse_each.with_index.reverse_each do |pop, i| % insn.pops.reverse_each.with_index.reverse_each do |pop, i|
<%= pop[:name] %> = <%= insn.cast_from_VALUE pop, "TOPN(#{i})"%>; <%= pop[:name] %> = <%= insn.cast_from_VALUE pop, "TOPN(#{i})"%>;
% end % end
DEBUG_ENTER_INSN(<%=cstr insn.name %>); DEBUG_ENTER_INSN(INSN_ATTR(name));
% if insn.handles_frame? % if insn.handles_frame?
ADD_PC(<%= insn.width %>); ADD_PC(INSN_ATTR(width));
% end % end
% unless insn.pops.empty? % unless insn.pops.empty?
POPN(<%= insn.pops.size %>); POPN(INSN_ATTR(popn));
% end % end
COLLECT_USAGE_INSN(<%= insn.bin %>); COLLECT_USAGE_INSN(INSN_ATTR(bin));
% insn.opes.each_with_index do |ope, i| % insn.opes.each_with_index do |ope, i|
COLLECT_USAGE_OPERAND(<%= insn.bin %>, <%= i %>, <%= ope[:name] %>); COLLECT_USAGE_OPERAND(INSN_ATTR(bin), <%= i %>, <%= ope[:name] %>);
% end % end
<%= render_c_expr insn.expr -%> <%= render_c_expr insn.expr -%>
% unless insn.rets.empty? % unless insn.rets.empty?
CHECK_VM_STACK_OVERFLOW_FOR_INSN(VM_REG_CFP, <%= insn.rets.size %>); CHECK_VM_STACK_OVERFLOW_FOR_INSN(VM_REG_CFP, INSN_ATTR(retn));
% insn.rets.each_with_index do |ret, i| % insn.rets.each_with_index do |ret, i|
PUSH(<%= insn.cast_to_VALUE ret %>); PUSH(<%= insn.cast_to_VALUE ret %>);
% end % end
% end % end
% unless insn.handles_frame? % unless insn.handles_frame?
ADD_PC(<%= insn.width %>); ADD_PC(INSN_ATTR(width));
PREFETCH(GET_PC()); PREFETCH(GET_PC());
% end % end
END_INSN(<%= insn.name %>); END_INSN(<%= insn.name %>);
# undef INSN_ATTR
# undef NAME_OF_CURRENT_INSN
} }
#undef NAME_OF_CURRENT_INSN

View File

@ -10,6 +10,7 @@
/* finish iseq array */ /* finish iseq array */
#include "insns.inc" #include "insns.inc"
#include "insns_info.inc"
#include <math.h> #include <math.h>
#include "constant.h" #include "constant.h"
#include "internal.h" #include "internal.h"