From 30d9aaf61b293cbdbc6ce959e5f2d3add602e3b8 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Thu, 4 Jun 2015 08:22:38 +0300 Subject: [PATCH] extract padding functions to module and finally TEST them its especially the brain bending stuff that needs tests --- lib/register/assembler.rb | 31 +++++++++-------------- lib/virtual.rb | 1 + lib/virtual/compiled_method_info.rb | 6 ----- lib/virtual/padding.rb | 22 +++++++++++++++++ lib/virtual/parfait_adapter.rb | 15 ++---------- lib/virtual/positioned.rb | 11 --------- test/virtual/test_padding.rb | 38 +++++++++++++++++++++++++++++ 7 files changed, 75 insertions(+), 49 deletions(-) create mode 100644 lib/virtual/padding.rb create mode 100644 test/virtual/test_padding.rb diff --git a/lib/register/assembler.rb b/lib/register/assembler.rb index 5d14740b..539cd82a 100644 --- a/lib/register/assembler.rb +++ b/lib/register/assembler.rb @@ -9,6 +9,7 @@ module Register # functions on the objects, but now it has gone to a visitor pattern. class Assembler + include Padding TYPE_REF = 0 TYPE_INT = 1 TYPE_BITS = 4 @@ -49,9 +50,12 @@ module Register def assemble # must be same order as link + begin link - @machine.objects.each do |objekt| + all= @machine.objects.sort{|a,b| a.position <=> b.position} + all.each do |objekt| + puts "Linked #{objekt.class}(#{objekt.object_id.to_s(16)}) at #{objekt.position.to_s(16)} / #{objekt.mem_length.to_s(16)}" objekt.position end # first we need to create the binary code for the methods @@ -76,6 +80,7 @@ module Register assemble_any( objekt ) end rescue LinkException + puts "RELINK" # knowing that we fix the problem, we hope to get away with retry. retry end @@ -111,9 +116,9 @@ module Register end def assemble_any obj - puts "Assemble #{obj.class} at stream #{(@stream.length).to_s(16)} pos:#{obj.position.to_s(16)} , len:#{obj.mem_length}" + puts "Assemble #{obj.class}(#{obj.object_id.to_s(16)}) at stream #{(@stream.length).to_s(16)} pos:#{obj.position.to_s(16)} , len:#{obj.mem_length}" if @stream.length != obj.position - raise "Assemble #{obj.class} at #{@stream.length.to_s(16)} not #{obj.position.to_s(16)}" + raise "Assemble #{obj.class} #{obj.object_id.to_s(16)} at #{@stream.length.to_s(16)} not #{obj.position.to_s(16)}" end clazz = obj.class.name.split("::").last send("assemble_#{clazz}".to_sym , obj) @@ -149,7 +154,8 @@ module Register puts "Nil for #{object.class}.#{var}" unless inst write_ref_for(inst) end - pad_after( layout.get_length * 4 ) + puts "layout leng=#{layout.get_length.to_s(16)} mem_len=#{layout.mem_length.to_s(16)}" + pad_after( layout.mem_length ) object.position end @@ -185,6 +191,7 @@ module Register end def assemble_Method(method) + raise "no" count = method.info.blocks.inject(0) { |c , block| c += block.mem_length } word = (count+7) / 32 # all object are multiple of 8 words (7 for header) raise "Method too long, splitting not implemented #{method.name}/#{count}" if word > 15 @@ -236,26 +243,12 @@ module Register @stream.write_sint32 object.position end - # objects only come in lengths of multiple of 8 words - # but there is a constant overhead of 2 words, one for type, one for layout - # and as we would have to subtract 1 to make it work without overhead, we now have to add 7 - def padded len - a = 32 * (1 + (len + 7)/32 ) - #puts "#{a} for #{len}" - a - end - - def padded_words words - padded(words*4) # 4 == word length, a constant waiting for a home - end - # pad_after is always in bytes and pads (writes 0's) up to the next 8 word boundary def pad_after length - pad = padded(length) - length - 8 # for header, type and layout + pad = padding_for(lenght) pad.times do @stream.write_uint8(0) end - #puts "padded #{length} with #{pad} stream pos #{@stream.length.to_s(16)}" end end diff --git a/lib/virtual.rb b/lib/virtual.rb index 27673f04..84442edb 100644 --- a/lib/virtual.rb +++ b/lib/virtual.rb @@ -2,6 +2,7 @@ require "parfait" require "virtual/machine" #if we are in the ruby run-time / generating an executable require "virtual/positioned" +require "virtual/padding" require "virtual/parfait_adapter" require "virtual/compiler" diff --git a/lib/virtual/compiled_method_info.rb b/lib/virtual/compiled_method_info.rb index bde31be3..dd7ea147 100644 --- a/lib/virtual/compiled_method_info.rb +++ b/lib/virtual/compiled_method_info.rb @@ -140,12 +140,6 @@ module Virtual padded(l) end - def padded len - a = 32 * (1 + (len + 7)/32 ) - #puts "#{a} for #{len}" - a - end - # position of the function is the position of the entry block, is where we call def set_position at at += 8 #for the 2 header words diff --git a/lib/virtual/padding.rb b/lib/virtual/padding.rb new file mode 100644 index 00000000..8beb7d89 --- /dev/null +++ b/lib/virtual/padding.rb @@ -0,0 +1,22 @@ + +module Padding + + # objects only come in lengths of multiple of 8 words + # but there is a constant overhead of 2 words, one for type, one for layout + # and as we would have to subtract 1 to make it work without overhead, we now have to add 7 + def padded len + a = 32 * (1 + (len + 7)/32 ) + #puts "#{a} for #{len}" + a + end + + def padded_words words + padded(words*4) # 4 == word length, a constant waiting for a home + end + + def padding_for length + pad = padded(length) - length - 8 # for header, type and layout + puts "padded #{length.to_s(16)} with #{pad.to_s(16)} stream pos #{@stream.length.to_s(16)}" + pad + end +end diff --git a/lib/virtual/parfait_adapter.rb b/lib/virtual/parfait_adapter.rb index 1ba9ea55..85a181e0 100644 --- a/lib/virtual/parfait_adapter.rb +++ b/lib/virtual/parfait_adapter.rb @@ -39,18 +39,6 @@ module FakeMem end @position = pos end - # objects only come in lengths of multiple of 8 words - # but there is a constant overhead of 2 words, one for type, one for layout - # and as we would have to subtract 1 to make it work without overhead, we now have to add 7 - def padded len - a = 32 * (1 + (len + 7)/32 ) - #puts "#{a} for #{len}" - a - end - - def padded_words words - padded(words*4) # 4 == word length, a constant waiting for a home - end end module Virtual def self.new_list array @@ -110,7 +98,8 @@ module Parfait # These are the same functions that Builtin implements at run-time class Object include FakeMem - + include Padding + # these internal functions are _really_ internal # they respresent the smallest code needed to build larger functionality # but should _never_ be used outside parfait. in fact that should be impossible diff --git a/lib/virtual/positioned.rb b/lib/virtual/positioned.rb index 3660bb7a..aac7b9e8 100644 --- a/lib/virtual/positioned.rb +++ b/lib/virtual/positioned.rb @@ -15,16 +15,5 @@ module Positioned end @position = pos end - # objects only come in lengths of multiple of 8 words - # but there is a constant overhead of 2 words, one for type, one for layout - # and as we would have to subtract 1 to make it work without overhead, we now have to add 7 - def padded len - a = 32 * (1 + (len + 7)/32 ) - #puts "#{a} for #{len}" - a - end - def padded_words words - padded(words*4) # 4 == word length, a constant waiting for a home - end end diff --git a/test/virtual/test_padding.rb b/test/virtual/test_padding.rb new file mode 100644 index 00000000..6e7bb309 --- /dev/null +++ b/test/virtual/test_padding.rb @@ -0,0 +1,38 @@ +require_relative "../helper" + +class Padded + include Padding +end + +class TestPadding < MiniTest::Test + + def setup + @pad = Padded.new + end + def test_small + [6,20,23,24].each do |p| + assert_equal 32 , @pad.padded(p) , "Expecting 32 for #{p}" + end + end + def test_large + [26,40,53,56].each do |p| + assert_equal 64 , @pad.padded(p) , "Expecting 64 for #{p}" + end + end +end + +class TestPositioning < MiniTest::Test + def test_list1 + list = Virtual.new_list([1]) + assert_equal 32 , list.mem_length + end + def test_list5 + list = Virtual.new_list([1,2,3,4,5]) + assert_equal 32 , list.mem_length + end + def test_layout + layout = Parfait::Layout.new Object + layout.push 5 + assert_equal 32 , layout.mem_length + end +end