mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00

This commit introduces new attribute handles_flame and if that is _not_ the case, places ADD_PC right after INC_SP. This improves locality of PC manipulations to prevents unnecessary register spill- outs. As a result, it reduces the size of vm_exec_core from 32,688 bytes to 32,384 bytes on my machine. Speedup is very faint, but certain. ----------------------------------------------------------- benchmark results: minimum results in each 3 measurements. Execution time (sec) name before after so_ackermann 0.476 0.464 so_array 0.742 0.728 so_binary_trees 5.493 5.466 so_concatenate 3.619 3.395 so_count_words 0.190 0.184 so_exception 0.249 0.239 so_fannkuch 0.994 0.953 so_fasta 1.369 1.374 so_k_nucleotide 1.111 1.111 so_lists 0.470 0.481 so_mandelbrot 2.059 2.050 so_matrix 0.466 0.465 so_meteor_contest 2.712 2.781 so_nbody 1.154 1.204 so_nested_loop 0.852 0.846 so_nsieve 1.636 1.623 so_nsieve_bits 2.073 2.039 so_object 0.616 0.584 so_partial_sums 1.464 1.481 so_pidigits 1.075 1.082 so_random 0.321 0.317 so_reverse_complement 0.555 0.558 so_sieve 0.495 0.490 so_spectralnorm 1.634 1.627 Speedup ratio: compare with the result of `before' (greater is better) name after so_ackermann 1.025 so_array 1.019 so_binary_trees 1.005 so_concatenate 1.066 so_count_words 1.030 so_exception 1.040 so_fannkuch 1.043 so_fasta 0.996 so_k_nucleotide 1.000 so_lists 0.978 so_mandelbrot 1.004 so_matrix 1.001 so_meteor_contest 0.975 so_nbody 0.959 so_nested_loop 1.007 so_nsieve 1.008 so_nsieve_bits 1.017 so_object 1.056 so_partial_sums 0.989 so_pidigits 0.994 so_random 1.014 so_reverse_complement 0.996 so_sieve 1.010 so_spectralnorm 1.004 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62051 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
171 lines
4.3 KiB
Ruby
171 lines
4.3 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 'CALL_ATTRIBUTE(%s)', [
|
|
name, @name, @opes.map {|i| i[:name] }
|
|
].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
|
|
|
|
def has_attribute? k
|
|
@attrs_orig.has_key? k
|
|
end
|
|
|
|
def attributes
|
|
# need to generate predefined attribute defaults
|
|
sp_inc
|
|
# other_attribute
|
|
# ...
|
|
return @attrs.values
|
|
end
|
|
|
|
def width
|
|
return 1 + opes.size
|
|
end
|
|
|
|
def declarations
|
|
return @variables \
|
|
. values \
|
|
. group_by {|h| h[:type] } \
|
|
. map {|t, v| [t, v.map {|i| i[:name] }.sort ] } \
|
|
. map {|t, v| sprintf("%s %s", t, v.join(', ')) } \
|
|
. sort
|
|
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:%d>", @name, @loc[0], @loc[1]
|
|
end
|
|
|
|
private
|
|
|
|
def generate_attribute k, t, v
|
|
attr = RubyVM::Attribute.new \
|
|
insn: self, \
|
|
name: k, \
|
|
type: t, \
|
|
location: [], \
|
|
expr: v.to_s + ';'
|
|
return @attrs[k] ||= attr
|
|
end
|
|
|
|
def predefine_attributes
|
|
generate_attribute 'sp_inc', 'rb_snum_t', rets.size - pops.size
|
|
generate_attribute 'handles_frame', 'bool', \
|
|
opes.any? {|o| /CALL_INFO/ =~ o[:type] }
|
|
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
|