Permalink
Browse files

Rework VM instruction parsing and generation.

  • Loading branch information...
1 parent d9ea900 commit 9b60cfd857847d5355e387ef9b0d81a109cf425c Brian Ford committed Oct 27, 2009
View
@@ -60,12 +60,13 @@ tmtags
!/bin/rbx
/vm/log
-/vm/instructions.cpp
/vm/.deps
/kernel/bootstrap/rubinius_config.rb
/kernel/bootstrap/ruby_config.rb
+/kernel/compiler/opcodes.rb
+
/lib/etc.rb
/lib/kernel.rb
/lib/rbconfig.rb
@@ -6,7 +6,6 @@ next section.
1. Install [ruby 1.8](http://www.ruby-lang.org/en/downloads/)
1. Install [RubyGems](http://rubyforge.org/projects/rubygems)
-1. Install rake and ParseTree: <tt>gem install rake ParseTree</tt>
1. Install Git
1. Clone rubinius: <tt>git clone git://github.com/evanphx/rubinius.git</tt>
1. cd to your rubinius checkout
@@ -54,7 +53,6 @@ for rubinius development.
### Requirements through RubyGems
* rake
-* ParseTree
Rake may be obtained with the <tt>gem install</tt> command. See <tt>gem
help</tt> and http://www.rubygems.org for more information.
@@ -470,13 +470,6 @@ def initialize(inst, cm, ip, args_reg)
end
@ip = ip
@line = cm.line_from_ip(ip)
-
- if sc = @op.stack_consumed
- @stack_consumed = calculate_stack_usage(sc, args_reg)
- else
- @stack_produced = 0
- end
- @stack_produced = calculate_stack_usage(@op.stack_produced)
end
# Instruction pointer
@@ -520,30 +513,6 @@ def size
attr_reader :stack_produced
##
- # Calculate the stack usage (pushes or pops) of this instruction.
- #
- # @return [Integer]
- def calculate_stack_usage(code, args_reg=0)
- usage = code
- if code < 0
- usage = 0
- # Stack usage depends on opcode args
- code *= -1
- arg, code = code.divmod(10)
- if arg >= 1 and arg <= 2
- # Opcode consumes/produces a multiple of the value in the specified
- # opcode arg
- usage += args[arg-1]
- elsif arg == 3
- # Opcode consumes number of args specified in args register
- usage += args_reg
- end
- usage += code
- end
- return usage
- end
-
- ##
# A nice human readable interpretation of this set of instructions
def to_s
str = "%04d: %-27s" % [@ip, opcode]
@@ -5,9 +5,6 @@ class Compiler
class Generator
- CALL_FLAG_PRIVATE = 1
- CALL_FLAG_CONCAT = 2
-
##
# Jump label for the goto instructions.
@@ -632,7 +629,7 @@ def send_with_block(meth, count, priv=false)
def send_with_splat(meth, args, priv=false, concat=false)
val = 0
- val |= CALL_FLAG_CONCAT if concat
+ val |= Rubinius::InstructionSet::CALL_FLAG_CONCAT if concat
add :set_call_flags, val unless val == 0
add :allow_private if priv
@@ -9,13 +9,6 @@ class OpCode
:stack, :stack_consumed, :stack_produced, :variable_stack,
:position, :stack_difference
- ##
- # Returns a symbol specifying the effect of the symbol on the flow of
- # execution, or nil if the instruction does not effect flow. The symbol
- # may be one of :sequential, :send, :return, :goto, or :raise.
-
- attr_reader :flow
-
alias_method :name, :opcode
alias_method :width, :size
@@ -25,16 +18,14 @@ def initialize(opcode, bytecode, params)
@args = params[:args]
@arg_count = @args.size
@size = @arg_count + 1
- @flow = params[:flow] || :sequential
- @flags = params[:vm_flags] || []
@stack_consumed, @stack_produced = params[:stack]
- if @stack_consumed
+ if @stack_consumed.kind_of? Fixnum
@variable_stack = false
@stack_difference = @stack_produced - @stack_consumed
else
@variable_stack = true
- extra, @position = params[:variable_stack]
+ extra, @position = @stack_consumed
@stack_difference = @stack_produced - extra
end
end
@@ -43,14 +34,6 @@ def variable_stack?
@variable_stack
end
- def check_interrupts?
- @flags.include? :check_interrupts
- end
-
- def terminator?
- @flags.include? :terminator
- end
-
def to_s
@opcode.to_s
end
@@ -59,12 +42,6 @@ def to_s
# InstructionSet methods
- # Allocates a new ID every call.
- def self.opcode_id
- @opcode_ids ||= -1
- @opcode_ids += 1
- end
-
# Returns the opcode map.
def self.opcodes_map
@opcodes_map ||= Rubinius::LookupTable.new
@@ -76,8 +53,7 @@ def self.opcodes
end
# Utility method for defining the opcodes.
- def self.opcode(name, params={})
- id = opcode_id
+ def self.opcode(id, name, params={})
opcodes[id] = OpCode.new name, id, params
opcodes_map[name] = opcodes_map[id] = id
end
@@ -91,206 +67,6 @@ def self.[](name_or_id)
raise InvalidOpCode, "Invalid opcode #{op.inspect}" unless opcode
opcode
end
-
- ##
- # List of Rubinius machine opcodes
- #
- # Each opcode consists of a hash identifying:
- # - The opcode symbol
- # - An array of the arguments required by the opcode, which may be of types
- # :int, :literal, :local, :block_local, :field, :primitive, :ip,
- # :depth, or :cache
- # - A 2 element array of codes indicating what changes the opcode makes to
- # the stack. The first code identifies the number of operands popped from
- # the stack, and the second the number of operands pushed back onto the
- # stack.
- #
- # If the code is zero or a positive value, it is the exact number of
- # operands pushed or popped. If the code is a negative value, it means the
- # number of operands consumed/produced is calculated based on another
- # value, and cannot be determined just from the opcode.
- #
- # Negative codes consist of 2-digits, where:
- # - the first digit is where the arg to be multiplied comes from;
- # 1 = first opcode arg, 2 = second opcode arg, 3 = arg register;
- # - the final digit is a constant number to be added to the result.
- #
- # - If the opcode can change the flow of execution, it will have a :flow key,
- # followed by a value indicating whether the opcode performs a :send, a
- # :goto, or a :return.
- # - An optional :vm_flags key whose value is an array of the vm_flags set
- # by the opcode. These flags are used when generating the opcode logic in
- # instructions.rb into C include files.
- #--
- # IMPORTANT: Do not change the order of opcodes! The position in this array
- # is the opcode's instuction bytecode.
-
- opcode :noop, :stack => [0, 0], :args => []
-
- # pushs
- opcode :push_nil, :stack => [0, 1], :args => []
- opcode :push_true, :stack => [0, 1], :args => []
- opcode :push_false, :stack => [0, 1], :args => []
- opcode :push_int, :stack => [0, 1], :args => [:int]
- opcode :push_self, :stack => [0, 1], :args => []
-
- # literals
- opcode :set_literal, :stack => [0, 0], :args => [:literal]
- opcode :push_literal, :stack => [0, 1], :args => [:literal]
-
- # flow control
-
- opcode :goto, :stack => [0, 0], :args => [:ip],
- :flow => :goto
- opcode :goto_if_false, :stack => [1, 0], :args => [:ip],
- :flow => :goto
- opcode :goto_if_true, :stack => [1, 0], :args => [:ip],
- :flow => :goto
- opcode :goto_if_defined, :stack => [1, 0], :args => [:ip],
- :flow => :goto
- opcode :ret, :stack => [0, 0], :args => [],
- :flow => :return,
- :vm_flags => [:terminator]
-
- # stack maintainence
- opcode :swap_stack, :stack => [1, 1], :args => []
- opcode :dup_top, :stack => [0, 1], :args => []
- opcode :pop, :stack => [1, 0], :args => []
- opcode :rotate, :stack => [0, 0], :args => [:int]
- opcode :move_down, :stack => [0, 0], :args => [:int]
-
- # locals
- opcode :set_local, :stack => [1, 1], :args => [:local]
- opcode :push_local, :stack => [0, 1], :args => [:local]
- opcode :push_local_depth, :stack => [0, 1], :args => [:depth, :block_local]
- opcode :set_local_depth, :stack => [1, 1], :args => [:depth, :block_local]
- opcode :passed_arg, :stack => [0, 1], :args => [:int]
-
- # exceptions
- opcode :push_exception, :stack => [0, 1], :args => []
- opcode :clear_exception, :stack => [0, 0], :args => []
- opcode :pop_exception, :stack => [1, 0], :args => []
- opcode :raise_exc, :stack => [0, 0], :args => [],
- :flow => :raise,
- :vm_flags => [:terminator]
- opcode :setup_unwind, :stack => [0, 0], :args => [:ip, :type]
- opcode :pop_unwind, :stack => [0, 0], :args => []
- opcode :raise_return, :stack => [0, 0], :args => []
- opcode :ensure_return, :stack => [0, 0], :args => []
- opcode :raise_break, :stack => [0, 0], :args => []
- opcode :reraise, :stack => [0, 0], :args => []
-
- # array
- opcode :make_array, :stack => [nil, 1], :args => [:int],
- :variable_stack => [0,1]
- opcode :cast_array, :stack => [1, 1], :args => []
- opcode :shift_array, :stack => [1, 2], :args => []
-
- # ivars
- opcode :set_ivar, :stack => [1, 1], :args => [:literal]
- opcode :push_ivar, :stack => [0, 1], :args => [:literal]
-
- # constants
- opcode :push_const, :stack => [0, 1], :args => [:literal]
- opcode :set_const, :stack => [1, 1], :args => [:literal]
- opcode :set_const_at, :stack => [2, 0], :args => [:literal]
- opcode :find_const, :stack => [1, 1], :args => [:literal]
- opcode :push_cpath_top, :stack => [0, 1], :args => []
- opcode :push_const_fast, :stack => [0, 1], :args => [:literal, :literal]
-
- # send
- opcode :set_call_flags, :stack => [0, 0], :args => [:int]
- opcode :allow_private, :stack => [0, 0], :args => []
- opcode :send_method, :stack => [1, 1], :args => [:literal],
- :flow => :send,
- :vm_flags => [:check_interrupts]
- opcode :send_stack, :stack => [nil, 1], :args => [:literal, :int],
- :flow => :send,
- :vm_flags => [:check_interrupts],
- :variable_stack => [1,2]
- opcode :send_stack_with_block, :stack => [nil, 1], :args => [:literal, :int],
- :flow => :send,
- :vm_flags => [:check_interrupts],
- :variable_stack => [2,2]
- opcode :send_stack_with_splat, :stack => [nil, 1], :args => [:literal, :int],
- :flow => :send,
- :vm_flags => [:check_interrupts],
- :variable_stack => [3,2]
- opcode :send_super_stack_with_block, :stack => [nil, 1], :args => [:literal, :int],
- :flow => :send,
- :vm_flags => [:check_interrupts],
- :variable_stack => [1,2]
- opcode :send_super_stack_with_splat, :stack => [nil, 1], :args => [:literal, :int],
- :flow => :send,
- :variable_stack => [2,2]
-
- # blocks
- opcode :push_block, :stack => [0, 1], :args => []
- opcode :passed_blockarg, :stack => [0, 1], :args => [:int]
- opcode :create_block, :stack => [0, 1], :args => [:literal]
- opcode :cast_for_single_block_arg, :stack => [0, 1], :args => []
- opcode :cast_for_multi_block_arg, :stack => [0, 1], :args => []
- opcode :cast_for_splat_block_arg, :stack => [0, 1], :args => []
- opcode :yield_stack, :stack => [nil, 1], :args => [:int],
- :flow => :send,
- :variable_stack => [0,1]
- opcode :yield_splat, :stack => [nil, 1], :args => [:int],
- :flow => :send,
- :variable_stack => [1,1]
-
- # strings
- opcode :string_append, :stack => [2, 1], :args => []
- opcode :string_dup, :stack => [1, 1], :args => []
-
- # scope
- opcode :push_scope, :stack => [0, 1], :args => []
- opcode :add_scope, :stack => [1, 0], :args => []
-
- # misc
- opcode :push_variables, :stack => [0, 1], :args => []
- opcode :check_interrupts, :stack => [0, 0], :args => []
- opcode :yield_debugger, :stack => [0, 0], :args => [],
- :vm_flags => [:check_interrupts]
- opcode :is_nil, :stack => [1, 1], :args => []
- opcode :check_serial, :stack => [1, 1], :args => [:literal, :int]
- opcode :check_serial_private, :stack => [1, 1], :args => [:literal, :int]
-
- # field access ,
- opcode :push_my_field, :stack => [0, 1], :args => [:field]
- opcode :store_my_field, :stack => [1, 1], :args => [:field]
-
- # type checks ,
- opcode :kind_of, :stack => [2, 1], :args => []
- opcode :instance_of, :stack => [2, 1], :args => []
-
- # meta opcodes, used for optimization only.
- opcode :meta_push_neg_1, :stack => [0, 1], :args => []
- opcode :meta_push_0, :stack => [0, 1], :args => []
- opcode :meta_push_1, :stack => [0, 1], :args => []
- opcode :meta_push_2, :stack => [0, 1], :args => []
- opcode :meta_send_op_plus, :stack => [2, 1], :args => [:literal],
- :flow => :send,
- :vm_flags => [:check_interrupts]
- opcode :meta_send_op_minus, :stack => [2, 1], :args => [:literal],
- :flow => :send,
- :vm_flags => [:check_interrupts]
- opcode :meta_send_op_equal, :stack => [2, 1], :args => [:literal],
- :flow => :send,
- :vm_flags => [:check_interrupts]
- opcode :meta_send_op_lt, :stack => [2, 1], :args => [:literal],
- :flow => :send,
- :vm_flags => [:check_interrupts]
- opcode :meta_send_op_gt, :stack => [2, 1], :args => [:literal],
- :flow => :send,
- :vm_flags => [:check_interrupts]
- opcode :meta_send_op_tequal, :stack => [2, 1], :args => [:literal],
- :flow => :send,
- :vm_flags => [:check_interrupts]
- opcode :meta_send_call, :stack => [nil, 1], :args => [:literal, :int],
- :flow => :send,
- :variable_stack => [1,2]
- opcode :push_my_offset, :stack => [0, 1], :args => [:field]
-
end
##
@@ -4,6 +4,7 @@ compiler.rbc
node.rbc
nodes.rbc
iseq.rbc
+opcodes.rbc
generator.rbc
bytecode.rbc
compile.rbc
@@ -39,6 +39,7 @@ class Tuple < Array
require 'compiler/node'
require 'compiler/nodes'
require 'compiler/iseq'
+require 'compiler/opcodes'
require 'compiler/generator'
require 'compiler/bytecode'
require 'compiler/compiled_file'
Oops, something went wrong.

0 comments on commit 9b60cfd

Please sign in to comment.