From 9c93b38b8f8d46dc63250ef586b25c5fc579b6e1 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Fri, 15 Jun 2018 21:54:21 +0300 Subject: [PATCH] crete positions while collecting objects clear two phase lifecycle for positions always created invalid and set later new does not auto add to cache but create and get_or_create do --- lib/risc/collector.rb | 9 +++++---- lib/risc/machine.rb | 19 ++++++++++--------- lib/risc/text_writer.rb | 21 ++++++++++++++++----- test/risc/test_collector.rb | 12 +++++++++--- test/risc/test_machine.rb | 6 +++--- 5 files changed, 43 insertions(+), 24 deletions(-) diff --git a/lib/risc/collector.rb b/lib/risc/collector.rb index fc6b6470..2c0d9cfc 100644 --- a/lib/risc/collector.rb +++ b/lib/risc/collector.rb @@ -1,12 +1,13 @@ module Risc # collect anything that is in the space but and reachable from init + # + # The place we collect in is the position map in Position class module Collector def self.collect_space - @objects = {} keep Parfait.object_space , 0 Risc.machine.constants.each {|obj| keep(obj,0)} - @objects + Position.positions end def self.keep( object , depth ) @@ -30,7 +31,7 @@ module Risc # Objects are data and get assembled after functions def self.add_object( objekt , depth) - return false if @objects[objekt] + return false if Position.set?(objekt) return true if objekt.is_a? Fixnum return true if objekt.is_a?( Risc::Label) #puts message(objekt , depth) @@ -39,7 +40,7 @@ module Risc raise "adding non parfait #{objekt.class}:#{objekt}" end #raise "Method #{objekt.name}" if objekt.is_a? Parfait::TypedMethod - @objects[objekt] = objekt + Position.get_or_create(objekt) true end diff --git a/lib/risc/machine.rb b/lib/risc/machine.rb index e879dd7b..e0733e03 100644 --- a/lib/risc/machine.rb +++ b/lib/risc/machine.rb @@ -50,7 +50,8 @@ module Risc # machine keeps a list of all objects and their positions. # this is lazily created with a collector def object_positions - @objects ||= Collector.collect_space + Collector.collect_space if Position.positions.empty? + Position.positions end # lazy init risc_init @@ -86,7 +87,7 @@ module Risc def position_all raise "Not translated " unless @translated #need the initial jump at 0 and then functions - Position.new(cpu_init , 0) + Position.new(cpu_init).set(0) code_start = position_objects( @platform.padding ) # and then everything code position_code(code_start) @@ -97,14 +98,17 @@ module Risc # return final position that is stored in code_start def position_objects(at) # want to have the objects first in the executable - sorted = object_positions.values.sort do |left,right| + sorted = object_positions.keys.sort do |left,right| left.class.name <=> right.class.name end previous = nil - sorted.each do | objekt| + sorted.each do |objekt| next if objekt.is_a?( Parfait::BinaryCode) or objekt.is_a?( Risc::Label ) before = at - position = Position.new(objekt , at) + unless( Position.set?(objekt)) + raise objekt.class + end + position = Position.get(objekt).set(at) previous.position_listener(objekt) if previous previous = position at += objekt.padded_length @@ -132,9 +136,6 @@ module Risc code_start = Position.get(method.binary.last_code).next_slot end end - #Position.set( first_method.cpu_instructions, code_start + Parfait::BinaryCode.byte_offset , first_method.binary) - #log.debug "Method #{first_method.name}:#{before.to_s(16)} len: #{(code_start - before).to_s(16)}" - #log.debug "Instructions #{first_method.cpu_instructions.object_id.to_s(16)}:#{(before+Parfait::BinaryCode.byte_offset).to_s(16)}" end # Create Binary code for all methods and the initial jump @@ -144,7 +145,7 @@ module Risc # constant loads into one instruction. # def create_binary - object_positions.each do |id , method| + object_positions.each do |method,position| next unless method.is_a? Parfait::TypedMethod writer = BinaryWriter.new(method.binary) writer.assemble(method.cpu_instructions) diff --git a/lib/risc/text_writer.rb b/lib/risc/text_writer.rb index 78aec1ba..7645a7ba 100644 --- a/lib/risc/text_writer.rb +++ b/lib/risc/text_writer.rb @@ -35,7 +35,7 @@ module Risc end def sorted_objects - @machine.object_positions.values.sort do |left , right| + @machine.object_positions.keys.sort do |left , right| Position.get(left).at <=> Position.get(right).at end end @@ -50,11 +50,22 @@ module Risc # Write all the objects in the order that they have been positioed def write_objects sorted_objects.each do |objekt| - next if objekt.is_a? Risc::Label # ignore - next if objekt.is_a? Parfait::BinaryCode # ignore + next unless is_object(objekt) write_any( objekt ) end end + def is_object(object) + case object + when Risc::Label , Parfait::BinaryCode + return false + when Parfait::Object , Symbol + return true + when Arm::Instruction + return false + else + raise "Class #{object.class}" + end + end # Write the BinaryCode objects of all methods to stream. # Really like any other object, it's just about the ordering @@ -118,8 +129,8 @@ module Risc def write_object_check(object) log.debug "Write object #{object.class} #{object.inspect[0..100]}" #Only initially created codes are collected. Binary_init and method "tails" not - if !@machine.object_positions.has_key?(object) and !object.is_a?(Parfait::BinaryCode) - log.debug "Object at 0x#{Position.get(object).to_s(16)}:#{object.get_type()}" + unless object.is_a?(Parfait::BinaryCode) + log.debug "Object at 0x#{Position.get(object)}:#{object.get_type()}" raise "Object(0x#{object.object_id.to_s(16)}) not linked #{object.inspect}" end end diff --git a/test/risc/test_collector.rb b/test/risc/test_collector.rb index a2d0d8a5..5ec39ec5 100644 --- a/test/risc/test_collector.rb +++ b/test/risc/test_collector.rb @@ -13,17 +13,23 @@ module Risc end def test_collect_all_types - Risc::Collector.collect_space.each do |id, objekt| + Risc::Collector.collect_space.each do |objekt , position| next unless objekt.is_a?( Parfait::Type ) assert Parfait.object_space.get_type_for( objekt.hash ) , objekt.hash end end def test_allowed_types - Risc::Collector.collect_space.each do |id, objekt| + Risc::Collector.collect_space.each do |objekt , position| next if objekt.is_a?( Parfait::Object ) next if objekt.is_a?( Symbol ) - assert_equal 1 , objekt.class + assert false + end + end + def test_positions + Risc::Collector.collect_space.each do |objekt , position| + assert_equal Position , position.class + assert !position.valid? end end end diff --git a/test/risc/test_machine.rb b/test/risc/test_machine.rb index c4f0da62..d18ecf36 100644 --- a/test/risc/test_machine.rb +++ b/test/risc/test_machine.rb @@ -41,7 +41,7 @@ module Risc @machine.position_all end def test_positions_set - @machine.object_positions.each do |id,obj| + @machine.object_positions.each do |obj , position| assert Position.get(obj).valid? , "#{Position.get(obj)} , #{obj.object_id.to_s(16)}" end end @@ -71,8 +71,8 @@ module Risc assert 0 != bin.get_word(0) , "index 0 is 0 #{bin.inspect}" end def test_positions_set - @machine.object_positions.each do |id,obj| - assert Position.get(obj).valid? , "#{Position.get(obj)} , #{obj.object_id.to_s(16)}" + @machine.object_positions.each do |obj,position| + assert position.valid? , "#{position} , #{obj.object_id.to_s(16)}" end end