mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	To perform a regular method call, the VM needs two structs, `rb_call_info` and `rb_call_cache`. At the moment, we allocate these two structures in separate buffers. In the worst case, the CPU needs to read 4 cache lines to complete a method call. Putting the two structures together reduces the maximum number of cache line reads to 2. Combining the structures also saves 8 bytes per call site as the current layout uses separate two pointers for the call info and the call cache. This saves about 2 MiB on Discourse. This change improves the Optcarrot benchmark at least 3%. For more details, see attached bugs.ruby-lang.org ticket. Complications: - A new instruction attribute `comptime_sp_inc` is introduced to calculate SP increase at compile time without using call caches. At compile time, a `TS_CALLDATA` operand points to a call info struct, but at runtime, the same operand points to a call data struct. Instruction that explicitly define `sp_inc` also need to define `comptime_sp_inc`. - MJIT code for copying call cache becomes slightly more complicated. - This changes the bytecode format, which might break existing tools. [Misc #16258]
		
			
				
	
	
		
			62 lines
		
	
	
	
		
			1.9 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			62 lines
		
	
	
	
		
			1.9 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
%# -*- C -*-
 | 
						|
%# Copyright (c) 2017 Urabe, Shyouhei.  All rights reserved.
 | 
						|
%#
 | 
						|
%# This file is a part of  the programming language Ruby.  Permission is hereby
 | 
						|
%# granted, to either  redistribute and/or modify this file,  provided that the
 | 
						|
%# conditions mentioned  in the  file COPYING  are met.   Consult the  file for
 | 
						|
%# details.
 | 
						|
%#
 | 
						|
PUREFUNC(MAYBE_UNUSED(static int comptime_insn_stack_increase(int depth, int insn, const VALUE *opes)));
 | 
						|
PUREFUNC(static rb_snum_t comptime_insn_stack_increase_dispatch(enum ruby_vminsn_type insn, const VALUE *opes));
 | 
						|
 | 
						|
rb_snum_t
 | 
						|
comptime_insn_stack_increase_dispatch(enum ruby_vminsn_type insn, const VALUE *opes)
 | 
						|
{
 | 
						|
    static const signed char t[] = {
 | 
						|
% RubyVM::Instructions.each_slice 8 do |a|
 | 
						|
        <%= a.map { |i|
 | 
						|
          if i.has_attribute?('sp_inc')
 | 
						|
            '-127'
 | 
						|
          else
 | 
						|
            sprintf("%4d", i.rets.size - i.pops.size)
 | 
						|
          end
 | 
						|
        }.join(', ') -%>,
 | 
						|
% end
 | 
						|
    };
 | 
						|
    signed char c = t[insn];
 | 
						|
 | 
						|
    ASSERT_VM_INSTRUCTION_SIZE(t);
 | 
						|
    if (c != -127) {
 | 
						|
        return c;
 | 
						|
    }
 | 
						|
    else switch(insn) {
 | 
						|
    default:
 | 
						|
        UNREACHABLE;
 | 
						|
% RubyVM::Instructions.each do |i|
 | 
						|
%   next unless i.has_attribute?('sp_inc')
 | 
						|
%   attr_function =
 | 
						|
%     if i.has_attribute?('comptime_sp_inc')
 | 
						|
%       "attr_comptime_sp_inc_#{i.name}"
 | 
						|
%     else
 | 
						|
%       "attr_sp_inc_#{i.name}"
 | 
						|
%     end
 | 
						|
    case <%= i.bin %>:
 | 
						|
        return <%= attr_function %>(<%=
 | 
						|
          i.opes.map.with_index do |v, j|
 | 
						|
            if v[:type] == 'CALL_DATA' && i.has_attribute?('comptime_sp_inc')
 | 
						|
              v = v.dup
 | 
						|
              v[:type] = 'CALL_INFO'
 | 
						|
            end
 | 
						|
            i.cast_from_VALUE v, "opes[#{j}]"
 | 
						|
          end.join(", ")
 | 
						|
        %>);
 | 
						|
% end
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
comptime_insn_stack_increase(int depth, int insn, const VALUE *opes)
 | 
						|
{
 | 
						|
    enum ruby_vminsn_type itype = (enum ruby_vminsn_type)insn;
 | 
						|
    return depth + (int)comptime_insn_stack_increase_dispatch(itype, opes);
 | 
						|
}
 |