1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/tool/ruby_vm/models/bare_instructions.rb
shyouhei 31ecd18f1a s/CALL_SIMPLE_METHOD/DISPATCH_ORIGINAL_INSN/
Now that DISPATCH_ORIGINAL_INSN is introduced, we can replace
CALL_SIMPLE_METHOD with DISPATCH_ORIGINAL_INSN. These two macros
differ in size very much and results in this big difference in
compiled binary size. This changeset reduces the size of
vm_exec_core from 32,352 bytes to 27,008 bytes on my machine.  As
a result it yields slightly better performance.
Closes [GH-1779].

-----------------------------------------------------------
benchmark results:
minimum results in each 3 measurements.
Execution time (sec)
name    before  after
so_ackermann     0.484  0.454
so_array         0.837  0.779
so_binary_trees  5.928  5.801
so_concatenate   3.473  3.543
so_count_words   0.201  0.222
so_exception     0.255  0.252
so_fannkuch      1.080  1.019
so_fasta         1.459  1.463
so_k_nucleotide  1.218  1.180
so_lists         0.499  0.484
so_mandelbrot    2.189  2.324
so_matrix        0.510  0.496
so_meteor_contest        3.025  2.925
so_nbody         1.319  1.273
so_nested_loop   0.941  0.932
so_nsieve        1.806  1.647
so_nsieve_bits   2.151  2.078
so_object        0.632  0.621
so_partial_sums  1.560  1.632
so_pidigits      1.190  1.183
so_random        0.333  0.353
so_reverse_complement    0.604  0.586
so_sieve         0.521  0.481
so_spectralnorm  1.774  1.722

Speedup ratio: compare with the result of `before' (greater is better)
name    after
so_ackermann    1.065
so_array        1.075
so_binary_trees 1.022
so_concatenate  0.980
so_count_words  0.903
so_exception    1.009
so_fannkuch     1.059
so_fasta        0.997
so_k_nucleotide 1.032
so_lists        1.032
so_mandelbrot   0.942
so_matrix       1.028
so_meteor_contest       1.034
so_nbody        1.036
so_nested_loop  1.009
so_nsieve       1.097
so_nsieve_bits  1.035
so_object       1.018
so_partial_sums 0.956
so_pidigits     1.006
so_random       0.943
so_reverse_complement   1.032
so_sieve        1.083
so_spectralnorm 1.030

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62088 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-01-29 07:04:50 +00:00

167 lines
4.5 KiB
Ruby

#! /your/favourite/path/to/ruby
# -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
#
# 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.
require_relative '../loaders/insns_def'
require_relative 'c_expr'
require_relative 'typemap'
require_relative 'attribute'
class RubyVM::BareInstructions
attr_reader :template, :name, :opes, :pops, :rets, :decls, :expr
def initialize opts = {}
@template = opts[:template]
@name = opts[:name]
@loc = opts[:location]
@sig = opts[:signature]
@expr = RubyVM::CExpr.new opts[:expr]
@opes = typesplit @sig[:ope]
@pops = typesplit @sig[:pop].reject {|i| i == '...' }
@rets = typesplit @sig[:ret].reject {|i| i == '...' }
@attrs = opts[:attributes].map {|i|
RubyVM::Attribute.new i.merge(:insn => self)
}.each_with_object({}) {|a, h|
h[a.key] = a
}
@attrs_orig = @attrs.dup
predefine_attributes
end
def pretty_name
n = @sig[:name]
o = @sig[:ope].map{|i| i[/\S+$/] }.join ', '
p = @sig[:pop].map{|i| i[/\S+$/] }.join ', '
r = @sig[:ret].map{|i| i[/\S+$/] }.join ', '
return sprintf "%s(%s)(%s)(%s)", n, o, p, r
end
def bin
return "BIN(#{name})"
end
def call_attribute name
return sprintf 'attr_%s_%s(%s)', name, @name, \
@opes.map {|i| i[:name] }.compact.join(', ')
end
def has_attribute? k
@attrs_orig.has_key? k
end
def attributes
return @attrs.values
end
def width
return 1 + opes.size
end
def declarations
return @variables \
. values \
. group_by {|h| h[:type] } \
. sort_by {|t, v| t } \
. map {|t, v| [t, v.map {|i| i[:name] }.sort ] } \
. map {|t, v|
sprintf("MAYBE_UNUSED(%s) %s", t, v.join(', '))
}
end
def preamble
# preamble makes sense for operand unifications
return []
end
def sc?
# sc stands for stack caching.
return false
end
def cast_to_VALUE var, expr = var[:name]
RubyVM::Typemap.typecast_to_VALUE var[:type], expr
end
def cast_from_VALUE var, expr = var[:name]
RubyVM::Typemap.typecast_from_VALUE var[:type], expr
end
def operands_info
opes.map {|o|
c, _ = RubyVM::Typemap.fetch o[:type]
next c
}.join
end
def handles_frame?
/\b(false|0)\b/ !~ @attrs['handles_frame'].expr.expr
end
def inspect
sprintf "#<%s %s@%s:%d>", self.class.name, @name, @loc[0], @loc[1]
end
private
def generate_attribute t, k, v
@attrs[k] ||= RubyVM::Attribute.new \
insn: self, \
name: k, \
type: t, \
location: [], \
expr: v.to_s + ';'
return @attrs[k] ||= attr
end
def predefine_attributes
generate_attribute 'const char*', 'name', "insn_name(#{bin})"
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', false
end
def typesplit a
@variables ||= {}
a.map do |decl|
md = %r'
(?<comment> /[*] [^*]* [*]+ (?: [^*/] [^*]* [*]+ )* / ){0}
(?<ws> \g<comment> | \s ){0}
(?<ident> [_a-zA-Z] [0-9_a-zA-Z]* ){0}
(?<type> (?: \g<ident> \g<ws>+ )* \g<ident> ){0}
(?<var> \g<ident> ){0}
\G \g<ws>* \g<type> \g<ws>+ \g<var>
'x.match(decl)
@variables[md['var']] ||= {
decl: decl,
type: md['type'],
name: md['var'],
}
end
end
@instances = RubyVM::InsnsDef.map {|h|
new h.merge(:template => h)
}
def self.fetch name
@instances.find do |insn|
insn.name == name
end or raise IndexError, "instruction not found: #{name}"
end
def self.to_a
@instances
end
end