work on jump insertion continues

Now registering CodeListener instead of PositionListener
Also instead of on the previous, in itself, which is simpler
and allows to react to insertion at end
This commit is contained in:
Torsten Ruger 2018-06-07 19:26:02 +03:00
parent 7fa8397b56
commit 2d218bbc48
5 changed files with 61 additions and 29 deletions

View File

@ -39,11 +39,7 @@ module Parfait
def extend_one() def extend_one()
@next = BinaryCode.new(1) @next = BinaryCode.new(1)
if Risc::Position.set?(self) Risc::Position.get(self).trigger_inserted if Risc::Position.set?(self)
Risc::Position.log.debug "extending one in #{self}"
my_pos = Risc::Position.get(self)
Risc::CodeListener.init( @next , my_pos + self.padded_length)
end
end end
def ensure_next def ensure_next

View File

@ -121,7 +121,8 @@ module Risc
Parfait.object_space.types.values.each do |type| Parfait.object_space.types.values.each do |type|
next unless type.methods next unless type.methods
type.methods.each_method do |method| type.methods.each_method do |method|
last_code = CodeListener.init(method.binary , code_start) last_code = CodeListener.init(method.binary)
last_code.set(code_start)
first_position = InstructionListener.init(method.cpu_instructions, method.binary) first_position = InstructionListener.init(method.cpu_instructions, method.binary)
first_position.set( code_start + Parfait::BinaryCode.byte_offset) first_position.set( code_start + Parfait::BinaryCode.byte_offset)
last_code.position_listener( prev_code.object) if prev_code last_code.position_listener( prev_code.object) if prev_code

View File

@ -9,15 +9,8 @@ module Risc
# #
class CodeListener class CodeListener
attr_reader :code , :method def set(at)
raise "Called"
def initialize(code , method)
super(code,pos)
@code = code
@method = method
raise "Method nil" unless method
end
def set(at )
next_pos = at + code.padded_length next_pos = at + code.padded_length
if code.next if code.next
Position.set(code.next , next_pos, method) Position.set(code.next , next_pos, method)
@ -33,7 +26,9 @@ module Risc
# insert a jump to the next instruction, at the last instruction # insert a jump to the next instruction, at the last instruction
# thus hopping over the object header # thus hopping over the object header
def set_jump(at) def set_jump_for(position)
at = position.at
code = position.object
jump = Branch.new("BinaryCode #{at.to_s(16)}" , code.next) jump = Branch.new("BinaryCode #{at.to_s(16)}" , code.next)
translator = Risc.machine.platform.translator translator = Risc.machine.platform.translator
cpu_jump = translator.translate(jump) cpu_jump = translator.translate(jump)
@ -42,20 +37,31 @@ module Risc
cpu_jump.assemble(JumpWriter.new(code)) cpu_jump.assemble(JumpWriter.new(code))
end end
def position_inserted(position)
Position.log.debug "extending one in #{self}"
pos = CodeListener.init( position.object.next )
pos.set( position + position.object.padded_length)
return unless position.valid?
set_jump_for(position)
end
def position_changed(position)
return unless position.object.next
raise "Called"
end
# Create Position for the given BinaryCode object # Create Position for the given BinaryCode object
# return the last position that was created, for chaining # return the first position that was created, to set it
def self.init( code , at = -1) def self.init( code )
first = nil
while code while code
raise "Not Binary Code #{code.class}" unless code.is_a?(Parfait::BinaryCode) raise "Not Binary Code #{code.class}" unless code.is_a?(Parfait::BinaryCode)
position = Position.new(code , at) position = Position.new(code , -1)
if code.next first = position unless first
listener = PositionListener.new(code.next) position.position_listener(CodeListener.new)
position.position_listener( listener)
end
at += code.padded_length unless at < 0
code = code.next code = code.next
end end
position first
end end
end end
end end

View File

@ -20,16 +20,19 @@ module Risc
def test_init_returns_position def test_init_returns_position
assert_equal Position , CodeListener.init(@binary).class assert_equal Position , CodeListener.init(@binary).class
end end
def test_not_init_listner
pos = CodeListener.init(@binary)
assert CodeListener == pos.event_table[:position_changed].last.class
end
def test_init_listner def test_init_listner
@binary.extend_one @binary.extend_one
CodeListener.init(@binary) CodeListener.init(@binary)
pos = Position.get(@binary) pos = Position.get(@binary)
assert !pos.event_table[:position_changed].empty? assert_equal CodeListener , pos.event_table[:position_changed].first.class
end end
def test_not_init_listner def test_extends_creates_jump
@binary.extend_one
CodeListener.init(@binary) CodeListener.init(@binary)
pos = Position.get(@binary)
assert pos.event_table[:position_changed].empty?
end end
end end
end end

View File

@ -0,0 +1,26 @@
require_relative "helper"
module Risc
# tests that require a boot and test propagation
class TestCodeListenerFull < MiniTest::Test
def setup
Risc.machine.boot
@binary = Parfait::BinaryCode.new(1)
@method = Parfait.object_space.types.values.first.methods
@label = Risc.label("hi","ho")
@machine.translate(:arm)
@machine.position_all
end
def test_listener_after_extend
CodeListener.init(@binary).set(0)
@binary.extend_one
pos = Position.get(@binary.next)
assert_equal CodeListener , pos.event_table[:position_changed].first.class
end
def test_extend_sets_next_pos
CodeListener.init(@binary).set(0)
@binary.extend_one
assert Position.get(@binary.next)
end
end
end