Cleanup Array and add Reflector #2077

Closed
wants to merge 2 commits into from
View
13 kernel/bootstrap/array.rb
@@ -1,18 +1,21 @@
# -*- encoding: us-ascii -*-
class Array
- attr_accessor :total
- attr_accessor :tuple
- attr_accessor :start
+ attr_reader :tuple
- alias_method :size, :total
- alias_method :length, :total
+ attr_reader_specific :total, :size
+ alias_method :length, :size
def self.allocate
Rubinius.primitive :array_allocate
raise PrimitiveFailure, "Array.allocate primitive failed"
end
+ def self.wrap(tuple, total)
+ Rubinius.primitive :array_wrap
+ raise PrimitiveFailure, "Array.wrap primitive failed"
+ end
+
def new_range(start, count)
Rubinius.primitive :array_new_range
raise PrimitiveFailure, "Array.new_range primitive failed"
View
8 kernel/bootstrap/array18.rb
@@ -5,21 +5,19 @@ class Array
# each element in self to the supplied block.
def map
return dup unless block_given?
- out = Array.new size
+ tup = Rubinius::Tuple.new size
i = @start
total = i + @total
tuple = @tuple
- out_tuple = out.tuple
-
j = 0
while i < total
- out_tuple[j] = yield tuple.at(i)
+ tup[j] = yield tuple.at(i)
i += 1
j += 1
end
- out
+ Array.wrap tup, size
end
end
View
8 kernel/bootstrap/array19.rb
@@ -5,21 +5,19 @@ class Array
# each element in self to the supplied block.
def map
return to_enum :map unless block_given?
- out = Array.new size
+ out = Rubinius::Tuple.new size
i = @start
total = i + @total
tuple = @tuple
- out_tuple = out.tuple
-
j = 0
while i < total
- out_tuple[j] = yield tuple.at(i)
+ out[j] = yield tuple.at(i)
i += 1
j += 1
end
- out
+ Array.wrap out, size
end
end
View
1 kernel/bootstrap/load_order18.txt
@@ -29,6 +29,7 @@ process.rbc
regexp.rbc
rubinius.rbc
constant_scope.rbc
+reflector.rbc
string.rbc
symbol.rbc
thread.rbc
View
1 kernel/bootstrap/load_order19.txt
@@ -32,6 +32,7 @@ regexp.rbc
regexp19.rbc
rubinius.rbc
constant_scope.rbc
+reflector.rbc
string.rbc
string19.rbc
symbol.rbc
View
19 kernel/bootstrap/reflector.rb
@@ -0,0 +1,19 @@
+module Rubinius
+ class Reflector
+
+ def self.new(target)
+ Rubinius.primitive :reflector_create
+ raise PrimitiveFailure, "Reflector.new failed"
+ end
+
+ def get(ivar)
+ Rubinius.primitive :reflector_get
+ raise PrimitiveFailure, "Reflector#get failed"
+ end
+
+ def set(ivar, name)
+ Rubinius.primitive :reflector_set
+ raise TypeError, "'#{name}' is not a ivar name"
+ end
+ end
+end
View
30 kernel/common/array.rb
@@ -34,8 +34,10 @@ def initialize(size_or_array=undefined, obj=undefined)
if size_or_array.respond_to? :to_ary
ary = Rubinius::Type.coerce_to size_or_array, Array, :to_ary
- @tuple = ary.tuple.dup
- @start = ary.start
+ ref = Rubinius::Reflector.new ary
+
+ @tuple = ref.get(:@tuple).dup
+ @start = ref.get :@start
@total = ary.size
return self
@@ -70,9 +72,11 @@ def replace(other)
other = Rubinius::Type.coerce_to other, Array, :to_ary
- @tuple = other.tuple.dup
- @total = other.total
- @start = other.start
+ ref = Rubinius::Reflector.new other
+
+ @tuple = ref.get(:@tuple).dup
+ @start = ref.get(:@start)
+ @total = other.size
Rubinius::Type.infect(self, other)
self
@@ -220,7 +224,7 @@ def <=>(other)
return 0 if equal? other
return nil if other.nil?
- other_total = other.total
+ other_total = other.size
Thread.detect_recursion self, other do
i = 0
total = other_total < @total ? other_total : @total
@@ -249,11 +253,13 @@ def ==(other)
return false unless size == other.size
Thread.detect_recursion self, other do
+ ref = Rubinius::Reflector.new other
+
md = @tuple
- od = other.tuple
+ od = ref.get :@tuple
i = @start
- j = other.start
+ j = ref.get :@start
total = i + @total
@@ -1077,9 +1083,11 @@ def recursively_flatten(array, out, max_levels = -1)
max_levels -= 1
recursion = Thread.detect_recursion(array) do
- i = array.start
- total = i + array.total
- tuple = array.tuple
+ ref = Rubinius::Reflector.new array
+
+ i = ref.get :@start
+ total = i + array.size
+ tuple = ref.get :@tuple
while i < total
o = tuple.at i
View
45 kernel/common/array18.rb
@@ -122,7 +122,8 @@ def set_index(index, ent, fin=undefined)
when 0
# nothing
else
- new_tuple.copy_from(replacement.tuple, replacement.start,
+ ref = Rubinius::Reflector.new replacement
+ new_tuple.copy_from(ref.get(:@tuple), ref.get(:@start),
replace_count, index)
end
@@ -150,7 +151,8 @@ def set_index(index, ent, fin=undefined)
when 0
# nothing
else
- @tuple.copy_from(replacement.tuple, replacement.start,
+ ref = Rubinius::Reflector.new replacement
+ @tuple.copy_from(ref.get(:@tuple), ref.get(:@start),
replace_count, @start + index)
end
@@ -193,19 +195,15 @@ def *(multiplier)
when 1
# Easy case
tuple = Rubinius::Tuple.pattern multiplier, at(0)
- out = self.class.allocate
- out.tuple = tuple
- out.total = multiplier
+ out = self.class.wrap tuple, multiplier
Rubinius::Type.infect(out, self) if multiplier != 0.0
return out
end
new_total = multiplier * @total
new_tuple = Rubinius::Tuple.new(new_total)
- out = self.class.allocate
- out.tuple = new_tuple
- out.total = new_total
+ out = self.class.wrap new_tuple, new_total
Rubinius::Type.infect(out, self) if multiplier != 0.0
offset = 0
@@ -470,9 +468,12 @@ def uniq!
Rubinius.check_frozen
array = im.to_array
- @tuple = array.tuple
- @start = array.start
- @total = array.total
+
+ ref = Rubinius::Reflector.new array
+
+ @tuple = ref.get :@tuple
+ @start = ref.get :@start
+ @total = array.size
self
end
@@ -500,19 +501,27 @@ def unshift(*values)
Rubinius.check_frozen
- if @start > values.size
+ sz = values.size
+
+ if @start > sz
# fit the new values in between 0 and @start if possible
- @start -= values.size
- @tuple.copy_from(values.tuple, 0, values.size, @start)
+ @start -= sz
+ if sz == 1
+ @tuple.put @start, values.at(0)
+ else
+ ref = Rubinius::Reflector.new values
+ @tuple.copy_from(ref.get(:@tuple), 0, sz, @start)
+ end
else
- new_tuple = Rubinius::Tuple.new @total + values.size
- new_tuple.copy_from values.tuple, 0, values.size, 0
- new_tuple.copy_from @tuple, @start, @total, values.size
+ ref = Rubinius::Reflector.new values
+ new_tuple = Rubinius::Tuple.new @total + sz
+ new_tuple.copy_from ref.get(:@tuple), 0, sz, 0
+ new_tuple.copy_from @tuple, @start, @total, sz
@start = 0
@tuple = new_tuple
end
- @total += values.size
+ @total += sz
self
end
end
View
52 kernel/common/array19.rb
@@ -97,7 +97,9 @@ def set_index(index, ent, fin=undefined)
when 0
# nothing
else
- new_tuple.copy_from(replacement.tuple, replacement.start,
+ ref = Rubinius::Reflector.new replacement
+
+ new_tuple.copy_from(ref.get(:@tuple), ref.get(:@start),
replace_count, index)
end
@@ -125,7 +127,9 @@ def set_index(index, ent, fin=undefined)
when 0
# nothing
else
- @tuple.copy_from(replacement.tuple, replacement.start,
+ ref = Rubinius::Reflector.new(replacement)
+
+ @tuple.copy_from(ref.get(:@tuple), ref.get(:@start),
replace_count, @start + index)
end
@@ -168,19 +172,15 @@ def *(multiplier)
when 1
# Easy case
tuple = Rubinius::Tuple.pattern multiplier, at(0)
- out = self.class.allocate
- out.tuple = tuple
- out.total = multiplier
+ out = self.class.wrap tuple, multiplier
Rubinius::Type.infect(out, self)
return out
end
new_total = multiplier * @total
new_tuple = Rubinius::Tuple.new(new_total)
- out = self.class.allocate
- out.tuple = new_tuple
- out.total = new_total
+ out = self.class.wrap new_tuple, new_total
Rubinius::Type.infect(out, self)
offset = 0
@@ -465,11 +465,14 @@ def sample(*args)
return at(random_generator.rand(size)) unless n
n = size if n > size
+
result = Array.new(self)
+ ref = Rubinius::Reflector.new(result)
+ tuple = ref.get(:@tuple)
n.times do |i|
r = i + random_generator.rand(size - i)
- result.tuple.swap(i, r)
+ tuple.swap(i, r)
end
result[n..size] = []
@@ -633,9 +636,12 @@ def uniq!(&block)
return if im.size == size
array = im.to_array
- @tuple = array.tuple
- @start = array.start
- @total = array.total
+
+ ref = Rubinius::Reflector.new array
+
+ @tuple = ref.get(:@tuple)
+ @start = ref.get(:@start)
+ @total = array.size
self
end
@@ -671,19 +677,27 @@ def unshift(*values)
return self if values.empty?
- if @start > values.size
+ sz = values.size
+
+ if @start > sz
# fit the new values in between 0 and @start if possible
- @start -= values.size
- @tuple.copy_from(values.tuple, 0, values.size, @start)
+ @start -= sz
+ if sz == 1
+ @tuple.put @start, values.at(0)
+ else
+ ref = Rubinius::Reflector.new values
+ @tuple.copy_from(ref.get(:@tuple), 0, sz, @start)
+ end
else
- new_tuple = Rubinius::Tuple.new @total + values.size
- new_tuple.copy_from values.tuple, 0, values.size, 0
- new_tuple.copy_from @tuple, @start, @total, values.size
+ ref = Rubinius::Reflector.new values
+ new_tuple = Rubinius::Tuple.new @total + sz
+ new_tuple.copy_from ref.get(:@tuple), 0, sz, 0
+ new_tuple.copy_from @tuple, @start, @total, sz
@start = 0
@tuple = new_tuple
end
- @total += values.size
+ @total += sz
self
end
end
View
12 kernel/common/tuple.rb
@@ -13,9 +13,12 @@ class Tuple
include Enumerable
def self.[](*args)
- start = args.start
+ ref = Rubinius::Reflector.new args
+ start = ref.get(:@start)
+ tuple = ref.get(:@tuple)
+
tot = args.size
- return new(tot).copy_from(args.tuple, start, tot, 0)
+ return new(tot).copy_from(tuple, start, tot, 0)
end
def to_s
@@ -97,10 +100,7 @@ def ===(other)
end
def to_a
- ary = Array.allocate
- ary.tuple = dup
- ary.total = fields
- return ary
+ Array.wrap dup , fields
end
def shift
View
1 rakelib/vm.rake
@@ -110,6 +110,7 @@ field_extract_headers = %w[
vm/builtin/cache.hpp
vm/builtin/atomic.hpp
vm/builtin/character.hpp
+ vm/builtin/reflector.hpp
]
transcoders_src_dir = File.expand_path "../../vendor/oniguruma/enc/trans", __FILE__
View
8 vm/builtin/array.cpp
@@ -53,6 +53,14 @@ namespace rubinius {
return ary;
}
+ Array* Array::wrap(STATE, Object* self, Tuple* tup, Fixnum* siz) {
+ Array* ary = allocate(state, self);
+ ary->tuple(state, tup);
+ ary->total(state, siz);
+
+ return ary;
+ }
+
Array* Array::new_range(STATE, Fixnum* start, Fixnum* count) {
Array* ary = state->new_object<Array>(class_object(state));
ary->total(state, count);
View
3 vm/builtin/array.hpp
@@ -38,6 +38,9 @@ namespace rubinius {
// Rubinius.primitive :array_allocate
static Array* allocate(STATE, Object* self);
+ // Rubinius.primitive :array_wrap
+ static Array* wrap(STATE, Object* self, Tuple* tup, Fixnum* size);
+
// Rubinius.primitive :array_new_range
Array* new_range(STATE, Fixnum* start, Fixnum* count);
View
41 vm/builtin/reflector.cpp
@@ -0,0 +1,41 @@
+#include "vm.hpp"
+#include "vm/object_utils.hpp"
+
+#include "builtin/object.hpp"
+
+#include "builtin/reflector.hpp"
+
+#include "ontology.hpp"
+#include "builtin/class.hpp"
+#include "builtin/symbol.hpp"
+#include "primitives.hpp"
+
+namespace rubinius {
+ void Reflector::init(STATE) {
+ GO(reflector).set(ontology::new_class(state, "Reflector",
+ G(object), G(rubinius)));
+ G(reflector)->set_object_type(state, Reflector::type);
+ }
+
+ Reflector* Reflector::create(STATE, Object* target) {
+ Reflector* ref = state->new_object<Reflector>(G(reflector));
+ ref->target(state, target);
+ return ref;
+ }
+
+ Object* Reflector::get(STATE, Symbol* name) {
+ if(name->is_ivar_p(state)->false_p()) return cNil;
+ return target_->get_ivar(state, name);
+ }
+
+ Object* Reflector::set(STATE, Symbol* name, Object* val) {
+ if(name->is_ivar_p(state)->false_p()) {
+ return Primitives::failure();
+ }
+
+ target_->check_frozen(state);
+ target_->set_ivar(state, name, val);
+
+ return val;
+ }
+}
View
36 vm/builtin/reflector.hpp
@@ -0,0 +1,36 @@
+#ifndef RBX_BUILTIN_REFLECTOR_HPP
+#define RBX_BUILTIN_REFLECTOR_HPP
+
+#include "builtin/object.hpp"
+#include "type_info.hpp"
+
+#include "virtual.hpp" // ObjectCallback
+#include "gc/root.hpp" // TypedRoot
+
+#include "builtin/thread.hpp"
+
+namespace rubinius {
+ class Reflector : public Object {
+ public:
+ static void init(STATE);
+
+ const static object_type type = ReflectorType;
+
+ private:
+ Object* target_;
+
+ public:
+ attr_accessor(target, Object);
+
+ // Rubinius.primitive :reflector_create
+ static Reflector* create(STATE, Object* obj);
+
+ // Rubinius.primitive :reflector_get
+ Object* get(STATE, Symbol* name);
+
+ // Rubinius.primitive :reflector_set
+ Object* set(STATE, Symbol* name, Object* val);
+ };
+}
+
+#endif
View
4 vm/globals.hpp
@@ -113,6 +113,7 @@ namespace rubinius {
TypedRoot<Module*> type;
TypedRoot<Class*> vm_class;
TypedRoot<Class*> atomic_ref;
+ TypedRoot<Class*> reflector;
/* Add new globals above this line. */
@@ -223,7 +224,8 @@ namespace rubinius {
encoding(&roots),
type(&roots),
vm_class(&roots),
- atomic_ref(&roots)
+ atomic_ref(&roots),
+ reflector(&roots)
/* Add initialize of globals above this line. */
{ }
View
3 vm/ontology.cpp
@@ -51,6 +51,7 @@
#include "builtin/module.hpp"
#include "builtin/class.hpp"
#include "builtin/atomic.hpp"
+#include "builtin/reflector.hpp"
#include "environment.hpp"
#include "configuration.hpp"
@@ -338,6 +339,8 @@ namespace rubinius {
Encoding::init(state);
kcode::init(state);
+
+ Reflector::init(state);
}
// @todo document all the sections of bootstrap_ontology