Permalink
Browse files

Move Lua->Ruby ip-mapping from Generator to InstructionSet.

Change Generator#vararg to only push the vararg range onto the stack, allowing the InstructionSet code to manipulate it like any other range.
Rename Generator#vararg to #push_vararg.
Fix Generator#new_closure to return the upvalue count.
Remove InstructionSet#binary_op and #unary_op, inlining their contents into the instruction loop.
Consolidate the :EQ, :LT, and :LE cases in InstructionSet into a single case.
  • Loading branch information...
1 parent a4179d3 commit b93116ad90373c033bb272f4f90415088162ff54 @Twisol committed Jul 20, 2011
Showing with 47 additions and 68 deletions.
  1. +15 −37 lib/lupin/generator.rb
  2. +32 −31 lib/lupin/instruction.rb
View
@@ -13,10 +13,6 @@ def initialize (state, function)
@constants = function.constants
@prototypes = function.prototypes
- # Goto labels to map jumps from Lua opcode counts to Rubinius counts
- @ips = []
- @current_ip = 0
-
@upvalue_locals = {} # Track which visible locals are held by closures.
# Shift the parameters into place.
@@ -45,28 +41,11 @@ def assemble (name, file)
end
- # Do stuff before each instruction
- def pre_instruction
- # Set a compile-time label for jumping to this instruction
- label = @ips[@current_ip]
- if !label
- label = @g.new_label
- @ips[@current_ip] = label
- end
- label.set!
- @current_ip += 1
-
- # TODO: Check debughooks here
+ def new_label
+ @g.new_label
end
- def jump (offset, condition=nil)
- index = @current_ip+offset
- label = @ips[index]
- if !label
- label = @g.new_label
- @ips[index] = label
- end
-
+ def jump (label, condition=nil)
if condition
@g.goto_if_true label
elsif condition == false
@@ -85,24 +64,24 @@ def jump_if_false (offset)
end
def if_else (proc_then=nil, proc_else=nil)
- else_label = @g.new_label
- done_label = @g.new_label
+ else_label = new_label
+ done_label = new_label
if proc_then
if proc_else
- @g.goto_if_false else_label
+ jump_if_false else_label
proc_then.call
- @g.goto done_label
+ jump done_label
else_label.set!
proc_else.call
done_label.set!
else
- @g.goto_if_false done_label
+ jump_if_false done_label
proc_then.call
done_label.set!
end
elsif proc_else
- @g.goto_if_true done_label
+ jump_if_true done_label
proc_else.call
done_label.set!
end
@@ -145,6 +124,11 @@ def push_rk (register)
end
end
+ def push_vararg
+ push_parameters
+ @g.send :dup, 0
+ end
+
def local_get (register)
@g.push_local register+1
@g.send :value, 0 if @upvalue_locals[register]
@@ -271,13 +255,6 @@ def return
@g.ret
end
- def vararg (base, count)
- push_parameters
- @g.send :dup, 0
- range_set(base, count)
- pop
- end
-
def new_table (array_size, hash_size)
@g.push_literal Hash
@g.send :new, 0
@@ -288,6 +265,7 @@ def new_closure (index)
@g.push_literal Lupin::Function
@g.push_literal proto
@g.send :new, 1
+ proto.upvalue_count
end
def share_upvalue (index)
View
@@ -14,19 +14,25 @@ def initialize (instructions)
end
def compile (g)
- pc, length = 0, @instructions.length
+ # Create an array of labels, one per instruction.
+ labels = Array.new(@instructions.length) {g.new_label}
+ pc, length = 0, @instructions.length
while pc < length
i = @instructions[pc]
+ labels[pc].set!
- g.pre_instruction
case opcode(i)
when :MOVE
g.local_get B(i)
g.local_set A(i)
g.pop
when :LOADNIL
- g.push_nil
+ A(i).upto(B(i)) do |index|
+ g.push_nil
+ g.local_set index
+ g.pop
+ end
when :LOADK
g.push_constant Bx(i)
g.local_set A(i)
@@ -36,7 +42,7 @@ def compile (g)
g.local_set A(i)
g.pop
- g.jump 1 if C(i) > 0
+ g.jump labels[pc+2] if C(i) > 0
when :GETGLOBAL
g.push_constant Bx(i)
g.global_get
@@ -68,9 +74,19 @@ def compile (g)
g.table_set
g.pop
when :ADD, :SUB, :MUL, :DIV, :MOD, :POW
- binary_op g, i, opcode(i).to_s.downcase
+ g.push_rk B(i)
+ g.push_rk C(i)
+ g.__send__ opcode(i).to_s.downcase
+ g.local_set A(i)
+ when :EQ, :LT, :LE
+ g.push_rk B(i)
+ g.push_rk C(i)
+ g.__send__ opcode(i).to_s.downcase
+ g.jump labels[pc+2], (A(i) == 0)
when :UNM, :LEN
- unary_op g, i, opcode(i).to_s.downcase
+ g.local_get B(i)
+ g.__send__ opcode(i).to_s.downcase
+ g.local_set A(i)
when :NOT
if_else proc {
push_bool false
@@ -83,7 +99,7 @@ def compile (g)
g.local_set A(i)
g.pop
when :JMP
- g.jump sBx(i)
+ g.jump labels[pc+sBx(i)+1]
when :CALL
g.local_get A(i)
g.range_get A(i)+1, B(i)-1
@@ -101,35 +117,22 @@ def compile (g)
g.call
g.return
when :VARARG
- g.vararg A(i), B(i)-1
+ g.push_vararg
+ g.range_set A(i), B(i)-1
+ g.pop
when :SELF
g.local_get B(i)
g.local_set A(i)+1
g.push_rk C(i)
g.table_get
g.local_set A(i)
g.pop
- when :EQ
- g.push_rk B(i)
- g.push_rk C(i)
- g.eq
- g.jump 1, (A(i) == 0)
- when :LT
- g.push_rk B(i)
- g.push_rk C(i)
- g.lt
- g.jump 1, (A(i) == 0)
- when :LE
- g.push_rk B(i)
- g.push_rk C(i)
- g.le
- g.jump 1, (A(i) == 0)
when :TEST
g.local_get A(i)
- g.jump 1, (C(i) != 0)
+ g.jump labels[pc+2], (C(i) != 0)
when :TESTSET
g.local_get B(i)
- g.jump 1, C(i) != 0
+ g.jump labels[pc+2], (C(i) != 0)
g.local_get B(i)
g.local_set A(i)
@@ -143,7 +146,7 @@ def compile (g)
g.pop
# Jump to the associated FORLOOP instruction
- g.jump sBx(i)
+ g.jump labels[pc+sBx(i)+1]
when :FORLOOP
# Do the conditional check
g.local_get A(i)
@@ -158,7 +161,7 @@ def compile (g)
}
g.lt
- g.jump_if_false 0 # Break out of the loop
+ g.jump_if_false labels[pc+1] # Break out of the loop
# Increment the count
g.local_get A(i)
@@ -169,7 +172,7 @@ def compile (g)
g.pop
# Go to the top of the loop
- g.jump sBx(i)
+ g.jump labels[pc+sBx(i)+1]
when :TFORLOOP
# Call the iterator function
g.local_get A(i)
@@ -182,7 +185,7 @@ def compile (g)
g.local_get A(i)+3
g.push_nil
g.eq
- g.jump_if_true 1
+ g.jump_if_true labels[pc+2]
# Otherwise, set it as the current loop index.
g.local_get A(i)+3
@@ -197,7 +200,6 @@ def compile (g)
block_number = if C(i) == 0
pc += 1
- g.pre_instruction
@instructions[pc]
else
C(i)
@@ -221,7 +223,6 @@ def compile (g)
upvalues = g.new_closure Bx(i)
upvalues.times do
pc += 1
- g.pre_instruction
upvalue = @instructions[pc]
case opcode(upvalue)

0 comments on commit b93116a

Please sign in to comment.