fixes #26
only recurse to 1k then come up for air an go again. Should allow for 1M objects on a 2k stack (previously exceptions at 3.6k)
This commit is contained in:
parent
74f3420d45
commit
ab87806d08
@ -1,43 +1,76 @@
|
|||||||
module Risc
|
module Risc
|
||||||
|
|
||||||
# collect anything that is in the space but and reachable from init
|
# collect anything that is in the space and reachable (linker constants)
|
||||||
#
|
#
|
||||||
# The place we collect in is the position map in Position class
|
# The place we collect in is the position map in Position class
|
||||||
module Collector
|
module Collector
|
||||||
|
# Collect all object that need to be added to the binary
|
||||||
|
# This means the object_space and aby constants the linker has
|
||||||
|
# we call keep on each object, see there for details
|
||||||
|
# return all positions
|
||||||
def self.collect_space(linker)
|
def self.collect_space(linker)
|
||||||
keep Parfait.object_space , 0
|
keep Parfait.object_space
|
||||||
linker.constants.each do |obj|
|
linker.constants.each do |obj|
|
||||||
keep(obj,0)
|
keep(obj)
|
||||||
end
|
end
|
||||||
Position.positions
|
Position.positions
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.keep( object , depth )
|
# keep "collects" the object for "keeping". Such objects get written to binary
|
||||||
|
# keeping used to be done by adding to a hash, but now the object is
|
||||||
|
# given a position, and the Position class has a hash of all positions
|
||||||
|
# (the same hash has all objects, off course)
|
||||||
|
def self.keep( object)
|
||||||
|
collection = []
|
||||||
|
mark_1k( object , 0 , collection)
|
||||||
|
collection.each do |obj|
|
||||||
|
#puts "obj #{obj.object_id}"
|
||||||
|
keep(obj)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# marking object that make up the binary.
|
||||||
|
# "Only" up to 1k stack depth, collect object that make up the "border"
|
||||||
|
#
|
||||||
|
# Collection is an empty arry that is passed on. Objects below 1k get added
|
||||||
|
# So basically it "should" be a return, but then we would keep creating and adding
|
||||||
|
# arrays, most of which would be empty
|
||||||
|
def self.mark_1k(object , depth , collection)
|
||||||
return if object.nil?
|
return if object.nil?
|
||||||
return unless add_object( object , depth )
|
if depth > 1000
|
||||||
|
collection << object
|
||||||
|
return
|
||||||
|
end
|
||||||
|
return unless position!( object )
|
||||||
return unless object.respond_to? :has_type?
|
return unless object.respond_to? :has_type?
|
||||||
type = object.get_type
|
type = object.get_type
|
||||||
keep(type , depth + 1)
|
mark_1k(type , depth + 1 , collection)
|
||||||
return if object.is_a? Symbol
|
return if object.is_a? Symbol
|
||||||
type.names.each do |name|
|
type.names.each do |name|
|
||||||
keep(name , depth + 1)
|
mark_1k(name , depth + 1, collection)
|
||||||
inst = object.get_instance_variable name
|
inst = object.get_instance_variable name
|
||||||
keep(inst , depth + 1)
|
#puts "getting name #{name}, val=#{inst} #{inst.object_id}"
|
||||||
|
mark_1k(inst , depth + 1, collection)
|
||||||
end
|
end
|
||||||
if object.is_a? Parfait::List
|
if object.is_a? Parfait::List
|
||||||
object.each do |item|
|
object.each do |item|
|
||||||
keep(item , depth + 1)
|
mark_1k(item , depth + 1, collection)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Objects are data and get assembled after functions
|
# Give the object a position. Position class keeps a list of all positions
|
||||||
def self.add_object( objekt , depth)
|
# and associated objects. The actual position is determined later, here a
|
||||||
|
# Position object is assigned.
|
||||||
|
#
|
||||||
|
# All Objects that end up in the binary must have a Position.
|
||||||
|
#
|
||||||
|
# return if the position was assigned (true) or had been assigned already (false)
|
||||||
|
def self.position!( objekt )
|
||||||
return false if Position.set?(objekt)
|
return false if Position.set?(objekt)
|
||||||
return true if objekt.is_a? ::Integer
|
return true if objekt.is_a? ::Integer
|
||||||
return true if objekt.is_a?( Risc::Label)
|
return true if objekt.is_a?( Risc::Label)
|
||||||
#puts message(objekt , depth)
|
#puts "ADD #{objekt.class.name}"
|
||||||
#puts "ADD #{objekt.inspect}, #{objekt.name}" if objekt.is_a? Parfait::CallableMethod
|
|
||||||
unless objekt.is_a?( Parfait::Object) or objekt.is_a?( Symbol)
|
unless objekt.is_a?( Parfait::Object) or objekt.is_a?( Symbol)
|
||||||
raise "adding non parfait #{objekt.class}:#{objekt}"
|
raise "adding non parfait #{objekt.class}:#{objekt}"
|
||||||
end
|
end
|
||||||
@ -46,13 +79,5 @@ module Risc
|
|||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.message(object , depth)
|
|
||||||
msg = "adding #{depth}#{' ' * depth}:"
|
|
||||||
if( object.respond_to?(:rxf_reference_name))
|
|
||||||
msg + object.rxf_reference_name.to_s
|
|
||||||
else
|
|
||||||
msg + object.class.name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -152,8 +152,10 @@ module Parfait
|
|||||||
Data8: {},
|
Data8: {},
|
||||||
Data16: {},
|
Data16: {},
|
||||||
Dictionary: {i_keys: :List , i_values: :List } ,
|
Dictionary: {i_keys: :List , i_values: :List } ,
|
||||||
Integer: {next_integer: :Integer},
|
|
||||||
FalseClass: {},
|
FalseClass: {},
|
||||||
|
Factory: { for_type: :Type , next_object: :Object ,
|
||||||
|
reserve: :Object , attribute_name: :Word },
|
||||||
|
Integer: {next_integer: :Integer},
|
||||||
List: {indexed_length: :Integer , next_list: :List} ,
|
List: {indexed_length: :Integer , next_list: :List} ,
|
||||||
Message: { next_message: :Message, receiver: :Object, frame: :NamedList ,
|
Message: { next_message: :Message, receiver: :Object, frame: :NamedList ,
|
||||||
return_address: :Integer, return_value: :Object,
|
return_address: :Integer, return_value: :Object,
|
||||||
@ -162,8 +164,6 @@ module Parfait
|
|||||||
NamedList: {},
|
NamedList: {},
|
||||||
NilClass: {},
|
NilClass: {},
|
||||||
Object: {},
|
Object: {},
|
||||||
Factory: { for_type: :Type , next_object: :Object ,
|
|
||||||
reserve: :Object , attribute_name: :Word },
|
|
||||||
ReturnAddress: {next_integer: :ReturnAddress},
|
ReturnAddress: {next_integer: :ReturnAddress},
|
||||||
Space: {classes: :Dictionary , types: :Dictionary , factories: :Dictionary,
|
Space: {classes: :Dictionary , types: :Dictionary , factories: :Dictionary,
|
||||||
true_object: :TrueClass, false_object: :FalseClass , nil_object: :NilClass},
|
true_object: :TrueClass, false_object: :FalseClass , nil_object: :NilClass},
|
||||||
|
@ -11,7 +11,7 @@ module Risc
|
|||||||
|
|
||||||
def test_simple_collect
|
def test_simple_collect
|
||||||
objects = Collector.collect_space(@linker)
|
objects = Collector.collect_space(@linker)
|
||||||
assert ((400 < objects.length) or (450 > objects.length)) , objects.length.to_s
|
assert_equal 600 , objects.length , objects.length.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_collect_all_types
|
def test_collect_all_types
|
||||||
@ -34,5 +34,40 @@ module Risc
|
|||||||
assert !position.valid?
|
assert !position.valid?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
def test_integer_positions
|
||||||
|
objects = Collector.collect_space(@linker)
|
||||||
|
int = Parfait.object_space.get_next_for(:Integer)
|
||||||
|
while(int)
|
||||||
|
assert Position.set?(int) , "INt #{int.object_id}"
|
||||||
|
int = int.next_integer
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
class TestBigCollector < MiniTest::Test
|
||||||
|
|
||||||
|
def setup
|
||||||
|
opt = Parfait.default_test_options
|
||||||
|
opt[:factory] = 4000
|
||||||
|
Parfait.boot!(opt)
|
||||||
|
Risc.boot!
|
||||||
|
@linker = Mom::MomCompiler.new.translate(:arm)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_simple_collect
|
||||||
|
objects = Collector.collect_space(@linker)
|
||||||
|
assert_equal 20329, objects.length , objects.length.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_integer_positions
|
||||||
|
objects = Collector.collect_space(@linker)
|
||||||
|
int = Parfait.object_space.get_next_for(:Integer)
|
||||||
|
count = 0
|
||||||
|
while(int)
|
||||||
|
count += 1
|
||||||
|
assert Position.set?(int) , "INT #{int.object_id} , count #{count}"
|
||||||
|
int = int.next_integer
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user