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()
@next = BinaryCode.new(1)
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
Risc::Position.get(self).trigger_inserted if Risc::Position.set?(self)
end
def ensure_next

View File

@ -121,7 +121,8 @@ module Risc
Parfait.object_space.types.values.each do |type|
next unless type.methods
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.set( code_start + Parfait::BinaryCode.byte_offset)
last_code.position_listener( prev_code.object) if prev_code

View File

@ -9,15 +9,8 @@ module Risc
#
class CodeListener
attr_reader :code , :method
def initialize(code , method)
super(code,pos)
@code = code
@method = method
raise "Method nil" unless method
end
def set(at)
raise "Called"
next_pos = at + code.padded_length
if code.next
Position.set(code.next , next_pos, method)
@ -33,7 +26,9 @@ module Risc
# insert a jump to the next instruction, at the last instruction
# 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)
translator = Risc.machine.platform.translator
cpu_jump = translator.translate(jump)
@ -42,20 +37,31 @@ module Risc
cpu_jump.assemble(JumpWriter.new(code))
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
# return the last position that was created, for chaining
def self.init( code , at = -1)
# return the first position that was created, to set it
def self.init( code )
first = nil
while code
raise "Not Binary Code #{code.class}" unless code.is_a?(Parfait::BinaryCode)
position = Position.new(code , at)
if code.next
listener = PositionListener.new(code.next)
position.position_listener( listener)
end
at += code.padded_length unless at < 0
position = Position.new(code , -1)
first = position unless first
position.position_listener(CodeListener.new)
code = code.next
end
position
first
end
end
end

View File

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