Skip to content

Commit

Permalink
incomplete Marshal.dump
Browse files Browse the repository at this point in the history
an evil ivar_as_index is added to Object to hold
the names of modules that extend the object
  • Loading branch information
Jeremy Roach committed Jan 9, 2008
1 parent 0a352c2 commit 1baa946
Show file tree
Hide file tree
Showing 8 changed files with 254 additions and 44 deletions.
4 changes: 4 additions & 0 deletions kernel/bootstrap/object.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -167,4 +167,8 @@ def freeze
def frozen? def frozen?
Ruby.primitive :object_frozen_p Ruby.primitive :object_frozen_p
end end

def add_module_name(mod_name)
Ruby.primitive :add_module_name
end
end end
154 changes: 153 additions & 1 deletion kernel/core/marshal.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -5,5 +5,157 @@ module Marshal
MAJOR_VERSION = 4 MAJOR_VERSION = 4
MINOR_VERSION = 8 MINOR_VERSION = 8


end TYPE_NIL = '0'
TYPE_TRUE = 'T'
TYPE_FALSE = 'F'
TYPE_FIXNUM = 'i'

TYPE_EXTENDED = 'e'
TYPE_UCLASS = 'C'
TYPE_OBJECT = 'o'
TYPE_DATA = 'd' # no specs
TYPE_USERDEF = 'u'
TYPE_USRMARSHAL = 'U' # no specs
TYPE_FLOAT = 'f'
TYPE_BIGNUM = 'l'
TYPE_STRING = '"'
TYPE_REGEXP = '/'
TYPE_ARRAY = '['
TYPE_HASH = '{'
TYPE_HASH_DEF = '}'
TYPE_STRUCT = 'S'
TYPE_MODULE_OLD = 'M' # no specs
TYPE_CLASS = 'c'
TYPE_MODULE = 'm'

TYPE_SYMBOL = ':'
TYPE_SYMLINK = ';'

TYPE_IVAR = 'I'
TYPE_LINK = '@'

def self.dump(obj, depth = -1, io = nil)
str = [MAJOR_VERSION, MINOR_VERSION].pack('CC')
str << serialize(obj, depth)
str
end

def self.serialize(obj, depth)
get_class_names(obj).each do |class_name|
case class_name
when 'NilClass'
return serialize_nil(obj)
when 'TrueClass'
return serialize_true(obj)
when 'FalseClass'
return serialize_false(obj)
when 'Class'
return serialize_class(obj)
when 'Module'
return serialize_module(obj)
when 'Symbol'
return serialize_symbol(obj)
when 'String'
return serialize_string(obj)
when / Integer | Fixnum | Bignum /x
if obj >= -2**30 and obj <= (2**30 - 1)
return serialize_fixnum(obj)
end
end
end
''
end

def self.serialize_integer(n)
if n == 0
s = to_byte(n)
elsif n > 0 and n < 123
s = to_byte(n + 5)
elsif n < 0 and n > -124
s = to_byte(256 + (n - 5))
elsif n < 0
s = "\x00"
else
s = "\x00"
cnt = 0
while n != 0
s << to_byte(n & 0xFF)
n >>= 8
cnt += 1
end
s[0] = to_byte(cnt)
end
s
end

def self.serialize_nil(obj)
TYPE_NIL
end

def self.serialize_true(obj)
TYPE_TRUE
end

def self.serialize_false(obj)
TYPE_FALSE
end


def self.serialize_symbol(obj)
str = obj.to_s
TYPE_SYMBOL + serialize_integer(str.length) + str
end

def self.serialize_class(obj)
TYPE_CLASS + serialize_integer(obj.name.length) + obj.name
end

def self.serialize_module(obj)
TYPE_MODULE + serialize_integer(obj.name.length) + obj.name
end

def self.serialize_extended_object(obj)
str = ''
if obj.module_names.kind_of?(Array)
obj.module_names.each do |mod_name|
str << TYPE_EXTENDED + serialize_symbol(mod_name)
end
end
str
end

def self.serialize_user_class(obj, cls)
if obj.class != cls
TYPE_UCLASS + serialize_symbol(obj.class.name)
else
''
end
end

def self.serialize_string(obj)
serialize_extended_object(obj) +
serialize_user_class(obj, String) +
TYPE_STRING + serialize_integer(obj.length) + obj
end

def self.serialize_fixnum(obj)
TYPE_FIXNUM + serialize_integer(obj)
end

def self.get_class_names(obj)
cls = obj.class
sup = get_superclass(cls)
[cls.to_s, sup.to_s]
end

def self.get_superclass(cls)
sup = cls.superclass
while sup and sup.superclass and sup.superclass != Object
sup = sup.superclass
end
sup
end

def self.to_byte(n)
[n].pack('C')
end
end
4 changes: 3 additions & 1 deletion kernel/core/object.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ class Object
RUBY_ENGINE = Rubinius::RUBY_ENGINE RUBY_ENGINE = Rubinius::RUBY_ENGINE
RBX_VERSION = Rubinius::RBX_VERSION RBX_VERSION = Rubinius::RBX_VERSION


ivar_as_index :__ivars__ => 0 ivar_as_index :__ivars__ => 0, :module_names => 1
def __ivars__; @__ivars__ ; end def __ivars__; @__ivars__ ; end
def module_names; @module_names; end


def initialize def initialize
end end
Expand Down Expand Up @@ -249,6 +250,7 @@ def protected_methods(all=true)
def extend(*modules) def extend(*modules)
modules.reverse_each do |mod| modules.reverse_each do |mod|
mod.extend_object(self) mod.extend_object(self)
add_module_name(mod.name)
end end
self self
end end
Expand Down
2 changes: 1 addition & 1 deletion lib/compiler/system_hints.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module Bootstrap
:MetaClass=>{:@__ivars__=>0, :@methods=>1, :@method_cache=>2, :@name=>3, :@constants=>4, :@parent=>5, :@superclass=>6, :@instance_fields=>7, :@has_ivars=>8, :@needs_cleanup=>9, :@object_type=>10, :@attached_instance=>11}, :MetaClass=>{:@__ivars__=>0, :@methods=>1, :@method_cache=>2, :@name=>3, :@constants=>4, :@parent=>5, :@superclass=>6, :@instance_fields=>7, :@has_ivars=>8, :@needs_cleanup=>9, :@object_type=>10, :@attached_instance=>11},
:Class=>{:@__ivars__=>0, :@methods=>1, :@method_cache=>2, :@name=>3, :@constants=>4, :@parent=>5, :@superclass=>6, :@instance_fields=>7, :@has_ivars=>8, :@needs_cleanup=>9, :@object_type=>10}, :Class=>{:@__ivars__=>0, :@methods=>1, :@method_cache=>2, :@name=>3, :@constants=>4, :@parent=>5, :@superclass=>6, :@instance_fields=>7, :@has_ivars=>8, :@needs_cleanup=>9, :@object_type=>10},
:BlockContext=>{}, :BlockContext=>{},
:Object=>{:@__ivars__=>0}, :Object=>{:@__ivars__=>0, :@module_names => 1},
:Float=>{:@__ivars__=>0}, :Float=>{:@__ivars__=>0},
:Array=>{:@total=>0, :@tuple=>1, :@start => 2, :@shared => 3}, :Array=>{:@total=>0, :@tuple=>1, :@start => 2, :@shared => 3},
:String=>{:@bytes=>0, :@characters=>1, :@encoding=>2, :@data=>3, :@hash => 4, :@shared => 5}, :String=>{:@bytes=>0, :@characters=>1, :@encoding=>2, :@data=>3, :@hash => 4, :@shared => 5},
Expand Down
3 changes: 2 additions & 1 deletion shotgun/lib/primitive_names.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ class Compiler
:bignum_from_float, :bignum_from_float,
:task_stack_size, :task_stack_size,
:task_get_stack_value, :task_get_stack_value,
:fastctx_reload_method :fastctx_reload_method,
:add_module_name
] ]


FirstRuntimePrimitive = 1024 FirstRuntimePrimitive = 1024
Expand Down
16 changes: 16 additions & 0 deletions shotgun/lib/primitives.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2898,6 +2898,22 @@ def object_send
CODE CODE
end end


def add_module_name
<<-CODE
self = stack_pop();
t1 = stack_pop();
if(!RISA(self, class) && !RISA(self, module)) {
t2 = object_get_module_names(self);
if(!RISA(t2, array)) {
t2 = array_new(state, 1);
object_set_module_names(self, t2);
}
array_append(state, t2, t1);
}
stack_push(self);
CODE
end

end end


prim = ShotgunPrimitives.new prim = ShotgunPrimitives.new
Expand Down
31 changes: 8 additions & 23 deletions spec/data/ruby/1.8/core/marshal/dump_excludes.txt
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2,42 +2,27 @@ Marshal.dump when given a recursion limit raises an ArgumentError when the recur
Marshal.dump when given an IO-Object writes the serialized data to the IO-Object Marshal.dump when given an IO-Object writes the serialized data to the IO-Object
Marshal.dump when given an IO-Object returns the IO-Object Marshal.dump when given an IO-Object returns the IO-Object
Marshal.dump when given an IO-Object raises an Error when the IO-Object does not respond to #write Marshal.dump when given an IO-Object raises an Error when the IO-Object does not respond to #write
Marshal.dump returns a string-serialized version of the given argument
Marshal.dump raises an Error when trying to dump an anonymous class/module Marshal.dump raises an Error when trying to dump an anonymous class/module
Marshal.dump with nil returns a string-serialized version of the given argument Marshal.dump with fixnum -2**8 returns a string-serialized version of the given argument
Marshal.dump with true returns a string-serialized version of the given argument Marshal.dump with fixnum -16711680 returns a string-serialized version of the given argument
Marshal.dump with false returns a string-serialized version of the given argument
Marshal.dump with empty string returns a string-serialized version of the given argument
Marshal.dump with string of length 100 returns a string-serialized version of the given argument
Marshal.dump with string of length 200 returns a string-serialized version of the given argument
Marshal.dump with string of length 300 returns a string-serialized version of the given argument
Marshal.dump with empty extended_string returns a string-serialized version of the given argument
Marshal.dump with empty user_string returns a string-serialized version of the given argument
Marshal.dump with empty extended_user_string returns a string-serialized version of the given argument
Marshal.dump with symbol of length 1 returns a string-serialized version of the given argument
Marshal.dump with symbol of length 300 returns a string-serialized version of the given argument
Marshal.dump with fixnum 0 returns a string-serialized version of the given argument
Marshal.dump with fixnum 5 returns a string-serialized version of the given argument
Marshal.dump with fixnum 2**16 returns a string-serialized version of the given argument
Marshal.dump with fixnum 2**24 returns a string-serialized version of the given argument
Marshal.dump with fixnum (2**30 - 1) returns a string-serialized version of the given argument
Marshal.dump with fixnum -2**16 returns a string-serialized version of the given argument Marshal.dump with fixnum -2**16 returns a string-serialized version of the given argument
Marshal.dump with fixnum -(2**16 - 1) returns a string-serialized version of the given argument
Marshal.dump with fixnum -(2**16 - 2) returns a string-serialized version of the given argument
Marshal.dump with fixnum -43690 returns a string-serialized version of the given argument
Marshal.dump with fixnum -2**30 returns a string-serialized version of the given argument Marshal.dump with fixnum -2**30 returns a string-serialized version of the given argument
Marshal.dump with bignum 2**30 returns a string-serialized version of the given argument Marshal.dump with bignum 2**30 returns a string-serialized version of the given argument
Marshal.dump with bignum -2**31 returns a string-serialized version of the given argument Marshal.dump with bignum -(2**31 -1) returns a string-serialized version of the given argument
Marshal.dump with bignum -2**63 returns a string-serialized version of the given argument Marshal.dump with bignum -2**63 returns a string-serialized version of the given argument
Marshal.dump with bignum 2**64 returns a string-serialized version of the given argument Marshal.dump with bignum 2**64 returns a string-serialized version of the given argument
Marshal.dump with bignum -2**64 returns a string-serialized version of the given argument Marshal.dump with bignum -2**64 returns a string-serialized version of the given argument
Marshal.dump with class returns a string-serialized version of the given argument
Marshal.dump with module returns a string-serialized version of the given argument
Marshal.dump with any object having _dump method returns a string-serialized version of the given argument Marshal.dump with any object having _dump method returns a string-serialized version of the given argument
Marshal.dump with any extended_object having _dump method returns a string-serialized version of the given argument Marshal.dump with any extended_object having _dump method returns a string-serialized version of the given argument
Marshal.dump with object returns a string-serialized version of the given argument Marshal.dump with object returns a string-serialized version of the given argument
Marshal.dump with object having ivar returns a string-serialized version of the given argument Marshal.dump with object having ivar returns a string-serialized version of the given argument
Marshal.dump with regexp returns a string-serialized version of the given argument Marshal.dump with regexp returns a string-serialized version of the given argument
Marshal.dump with extended_regexp returns a string-serialized version of the given argument Marshal.dump with extended_regexp returns a string-serialized version of the given argument
Marshal.dump with user_regexp having option Regexp::IGNORECASE returns a string-serialized version of the given argument Marshal.dump with user_regexp having option Regexp::IGNORECASE returns a string-serialized version of the given argument
Marshal.dump with extended_user_regexp returns a string-serialized version of the given argument Marshal.dump with extended_user_regexp having ivar returns a string-serialized version of the given argument
Marshal.dump with float 0.0 returns a string-serialized version of the given argument Marshal.dump with float 0.0 returns a string-serialized version of the given argument
Marshal.dump with float NaN returns a string-serialized version of the given argument Marshal.dump with float NaN returns a string-serialized version of the given argument
Marshal.dump with float -Infinity returns a string-serialized version of the given argument Marshal.dump with float -Infinity returns a string-serialized version of the given argument
Expand All @@ -50,7 +35,7 @@ Marshal.dump with extended_user_hash_default returns a string-serialized version
Marshal.dump with array returns a string-serialized version of the given argument Marshal.dump with array returns a string-serialized version of the given argument
Marshal.dump with array containing the same symbols returns a string-serialized version of the given argument Marshal.dump with array containing the same symbols returns a string-serialized version of the given argument
Marshal.dump with array containing refs to the same object returns a string-serialized version of the given argument Marshal.dump with array containing refs to the same object returns a string-serialized version of the given argument
Marshal.dump with extended_array returns a string-serialized version of the given argument Marshal.dump with extended_array having ivar returns a string-serialized version of the given argument
Marshal.dump with user_array returns a string-serialized version of the given argument Marshal.dump with user_array returns a string-serialized version of the given argument
Marshal.dump with extended_user_array returns a string-serialized version of the given argument Marshal.dump with extended_user_array returns a string-serialized version of the given argument
Marshal.dump with struct returns a string-serialized version of the given argument Marshal.dump with struct returns a string-serialized version of the given argument
Expand Down
Loading

0 comments on commit 1baa946

Please sign in to comment.