1
0
Fork 0
mirror of https://github.com/rubyjs/therubyracer synced 2023-03-27 23:21:42 -04:00

eschew heap allocated accessor callbacks

This changes the accessor code to push as much
object allocation onto Ruby as possible. Instead
the C++ layer acts strictly as glue using stack
allocated variables to convert v8 value to ruby
objects at the moment it passes them off to Ruby.
This commit is contained in:
Charles Lowell 2012-05-21 16:36:19 -05:00
parent c66e43e438
commit 72068651f9
4 changed files with 112 additions and 127 deletions

View file

@ -2,105 +2,97 @@
namespace rr {
VALUE Accessor::Class;
VALUE Accessor::Info::Class;
void Accessor::Init() {
ClassBuilder("AccessorInfo").
defineMethod("This", &This).
defineMethod("Holder", &Holder).
defineMethod("Data", &Data).
store(&Class);
defineMethod("This", &Info::This).
defineMethod("Holder", &Info::Holder).
defineMethod("Data", &Info::Data).
store(&Info::Class);
}
Accessor::Accessor(const v8::AccessorInfo& info) {
this->thisObject = Object(info.This());
this->holder = Object(info.Holder());
this->value = Data_Wrap_Struct(Class, &mark, &sweep, this);
this->info = new Info(info.Data());
}
Accessor::~Accessor() {
delete info;
}
Accessor* Accessor::accessor(VALUE wrap) {
Accessor* info = 0;
Data_Get_Struct(wrap, class Accessor, info);
return info;
}
Accessor::operator VALUE() {
return this->value;
}
VALUE Accessor::This(VALUE self) {
return accessor(self)->thisObject;
}
VALUE Accessor::Holder(VALUE self) {
return accessor(self)->holder;
}
VALUE Accessor::Data(VALUE self) {
return accessor(self)->info->data;
}
v8::Handle<v8::Value> Accessor::get(v8::Local<v8::String> property) {
return Value(rb_funcall(info->getter, rb_intern("call"), 2, (VALUE)String(property), this->value));
}
v8::Handle<v8::Value> Accessor::set(v8::Local<v8::String> property, v8::Local<v8::Value> value) {
return Value(rb_funcall(info->setter, rb_intern("call"), 3, (VALUE)String(property), (VALUE)Value(value), this->value));
}
void Accessor::mark(Accessor* acc) {
rb_gc_mark(acc->thisObject);
rb_gc_mark(acc->holder);
acc->info->mark();
}
void Accessor::sweep(Accessor* acc) {
delete acc;
}
v8::Handle<v8::Value> Accessor::AccessorGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) {
Accessor* getter = new Accessor(info);
return getter->get(property);
}
void Accessor::AccessorSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info) {
Accessor* accessor = new Accessor(info);
accessor->set(property, value);
}
Accessor::Info::Info(VALUE getter, VALUE setter, VALUE data) {
this->getter = getter;
this->setter = setter;
Accessor::Accessor(VALUE get, VALUE set, VALUE data) {
this->get = get;
this->set = set;
this->data = data;
}
Accessor::Info::Info(v8::Local<v8::Value> data) {
v8::Local<v8::Object> wrapper = data->ToObject();
this->getter = unwrap(wrapper, 0);
this->setter = unwrap(wrapper, 1);
this->data = unwrap(wrapper, 2);
}
Accessor::Info::operator v8::Handle<v8::Value>() {
v8::Local<v8::Object> wrapper = v8::Object::New();
wrap(wrapper, 0, this->getter);
wrap(wrapper, 1, this->setter);
wrap(wrapper, 2, this->data);
return wrapper;
}
void Accessor::Info::wrap(v8::Handle<v8::Object> wrapper, uint32_t index, VALUE value) {
wrapper->Set(index, External::wrap(value));
}
VALUE Accessor::Info::unwrap(v8::Handle<v8::Object> wrapper, uint32_t index) {
v8::Local<v8::External> holder = v8::External::Cast(*(wrapper->Get(index)));
return External::unwrap(holder);
}
v8::AccessorGetter Accessor::Info::Getter() {
return &Accessor::AccessorGetter;
}
v8::AccessorSetter Accessor::Info::Setter() {
return RTEST(this->setter) ? &Accessor::AccessorSetter : 0;
Accessor::Accessor(v8::Handle<v8::Value> value) {
v8::Local<v8::Object> wrapper = value->ToObject();
this->get = unwrap(wrapper, 0);
this->set = unwrap(wrapper, 1);
v8::Handle<v8::Value> data = wrapper->Get(2);
if (!data.IsEmpty()) {
this->data = Value(data);
}
}
void Accessor::Info::mark() {
rb_gc_mark(getter);
rb_gc_mark(setter);
rb_gc_mark(data);
Accessor::operator v8::AccessorGetter() {
return &Getter;
}
Accessor::operator v8::AccessorSetter() {
return RTEST(this->set) ? &Setter : 0;
}
Accessor::operator v8::Handle<v8::Value>() {
v8::Local<v8::Object> wrapper = v8::Object::New();
wrap(wrapper, 0, this->get);
wrap(wrapper, 1, this->set);
if (RTEST(this->data)) {
wrapper->Set(2, Value(this->data));
}
return wrapper;
}
void Accessor::wrap(v8::Handle<v8::Object> wrapper, int index, VALUE value) {
wrapper->Set(index, External::wrap(value));
}
VALUE Accessor::unwrap(v8::Handle<v8::Object> wrapper, int index) {
v8::Handle<v8::External> external(v8::External::Cast(*wrapper->Get(index)));
return External::unwrap(external);
}
VALUE Accessor::Info::This(VALUE self) {
return Object(Info(self)->This());
}
VALUE Accessor::Info::Holder(VALUE self) {
return Object(Info(self)->Holder());
}
VALUE Accessor::Info::Data(VALUE self) {
return Accessor(Info(self)->Data()).data;
}
v8::Handle<v8::Value> Accessor::Getter(v8::Local<v8::String> property, const v8::AccessorInfo& info) {
return Info(info).get(property);
}
void Accessor::Setter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info) {
Info(info).set(property, value);
}
Accessor::Info::Info(const v8::AccessorInfo& info) {
this->info = &info;
}
Accessor::Info::Info(VALUE value) {
Data_Get_Struct(value, class v8::AccessorInfo, info);
}
v8::Handle<v8::Value> Accessor::Info::get(v8::Local<v8::String> property) {
Accessor accessor(info->Data());
return Value(rb_funcall(accessor.get, rb_intern("call"), 2, (VALUE)String(property), (VALUE)*this));
}
void Accessor::Info::set(v8::Local<v8::String> property, v8::Local<v8::Value> value) {
Accessor accessor(info->Data());
rb_funcall(accessor.set, rb_intern("call"), 3, (VALUE)String(property), (VALUE)Value(value), (VALUE)*this);
}
Accessor::Info::operator VALUE() {
return Data_Wrap_Struct(Class, 0, 0, (void*)this->info);
}
}

View file

@ -120,13 +120,8 @@ VALUE Object::ForceDelete(VALUE self, VALUE key) {
VALUE Object::SetAccessor(int argc, VALUE* argv, VALUE self) {
VALUE name; VALUE get; VALUE set; VALUE data; VALUE settings; VALUE attribs;
rb_scan_args(argc, argv, "24", &name, &get, &set, &data, &settings, &attribs);
Accessor::Info accessor(get, set, data);
return Bool(Object(self)->SetAccessor(String(name),
accessor.Getter(),
accessor.Setter(),
accessor,
AccessControl(settings),
PropertyAttribute(attribs)));
Accessor access(get, set, data);
return Bool(Object(self)->SetAccessor(String(name), access, access, access, AccessControl(settings), PropertyAttribute(attribs)));
}
Object::operator VALUE() {

View file

@ -223,41 +223,37 @@ public:
class Accessor {
public:
static void Init();
Accessor(const v8::AccessorInfo& info);
~Accessor();
static VALUE This(VALUE self);
static VALUE Holder(VALUE self);
static VALUE Data(VALUE self);
operator VALUE();
v8::Handle<v8::Value> get(v8::Local<v8::String> property);
v8::Handle<v8::Value> set(v8::Local<v8::String> property, v8::Local<v8::Value> value);
static v8::Handle<v8::Value> AccessorGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info);
static void AccessorSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
Accessor(VALUE get, VALUE set, VALUE data);
Accessor(v8::Handle<v8::Value> value);
operator v8::AccessorGetter();
operator v8::AccessorSetter();
operator v8::Handle<v8::Value>();
static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property, const v8::AccessorInfo& info);
static void Setter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
class Info {
public:
Info(VALUE getter, VALUE setter, VALUE data);
Info(v8::Local<v8::Value> value);
operator v8::Handle<v8::Value>();
void mark();
v8::AccessorGetter Getter();
v8::AccessorSetter Setter();
VALUE getter;
VALUE setter;
VALUE data;
Info(const v8::AccessorInfo& info);
Info(VALUE value);
static VALUE This(VALUE self);
static VALUE Holder(VALUE self);
static VALUE Data(VALUE self);
operator VALUE();
inline const v8::AccessorInfo* operator->() {return this->info;}
v8::Handle<v8::Value> get(v8::Local<v8::String> property);
void set(v8::Local<v8::String> property, v8::Local<v8::Value> value);
static VALUE Class;
private:
void wrap(v8::Handle<v8::Object> wrapper, uint32_t index, VALUE value);
VALUE unwrap(v8::Handle<v8::Object> wrapper, uint32_t index);
const v8::AccessorInfo* info;
};
friend class Info;
private:
VALUE thisObject;
VALUE holder;
VALUE value;
Info* info;
static void mark(Accessor* accessor);
static void sweep(Accessor* accessor);
static Accessor* accessor(VALUE self);
static VALUE Class;
void wrap(v8::Handle<v8::Object> wrapper, int index, VALUE value);
VALUE unwrap(v8::Handle<v8::Object> wrapper, int index);
VALUE get;
VALUE set;
VALUE data;
};
class Invocation {

View file

@ -36,6 +36,8 @@ describe V8::C::Object do
callback_data = V8::C::String::New("I am Legend")
left = V8::C::String::New("Yo! ")
getter = proc do |name, info|
info.This().StrictEquals(o).should be_true
info.Holder().StrictEquals(o).should be_true
V8::C::String::Concat(left, info.Data())
end
setter = proc do |name, value, info|