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

handle checkpoint.

This commit is contained in:
Charles Lowell 2011-04-07 11:49:47 -05:00
parent fdb62441b1
commit 0ffce72fe1
5 changed files with 140 additions and 42 deletions

View file

@ -1,3 +1,4 @@
#include "v8_handle.h"
#include "v8_cxt.h" #include "v8_cxt.h"
#include "v8_value.h" #include "v8_value.h"
#include "v8_str.h" #include "v8_str.h"
@ -19,27 +20,28 @@
#include <stdio.h> #include <stdio.h>
extern "C" { extern "C" {
void Init_v8(); void Init_v8();
} }
extern "C" { extern "C" {
void Init_v8() { void Init_v8() {
rr_init_cxt(); rr_init_handle();
rr_init_value(); rr_init_cxt();
rr_init_str(); rr_init_value();
rr_init_script(); rr_init_str();
rr_init_template(); rr_init_script();
rr_init_obj(); rr_init_template();
rr_init_func(); rr_init_obj();
rr_init_v8_array(); rr_init_func();
rr_init_v8_date(); rr_init_v8_array();
rr_init_msg(); rr_init_v8_date();
rr_init_v8_try_catch(); rr_init_msg();
rr_init_v8_callbacks(); rr_init_v8_try_catch();
rr_init_v8_external(); rr_init_v8_callbacks();
rr_init_v8_exception(); rr_init_v8_external();
rr_init_v8_locker(); rr_init_v8_exception();
rr_init_v8_debug(); rr_init_v8_locker();
rr_init_v8_v8(); rr_init_v8_debug();
} rr_init_v8_v8();
}
} }

View file

@ -27,10 +27,8 @@ namespace {
return (VALUE)V8_Ref_Get<External>(self)->Value(); return (VALUE)V8_Ref_Get<External>(self)->Value();
} }
void GCWeakReferenceCallback(Persistent<Value> object, void* parameter) { void GCWeakReferenceCallback(Persistent<Value> object, void* parameter) {
// printf("V8 GC!!!!\n");
Local<External> external(External::Cast(*object)); Local<External> external(External::Cast(*object));
rb_hash_delete(references, rb_obj_id((VALUE)external->Value())); rb_hash_delete(references, rb_obj_id((VALUE)external->Value()));
// V8::AdjustAmountOfExternalAllocatedMemory(-100000000);
} }
} }
@ -51,7 +49,6 @@ Handle<Value> rr_v8_external_create(VALUE value) {
rb_hash_aset(references, rb_obj_id(value), value); rb_hash_aset(references, rb_obj_id(value), value);
Local<Value> external(External::New((void *)value)); Local<Value> external(External::New((void *)value));
Persistent<Value> record = Persistent<Value>::New(external); Persistent<Value> record = Persistent<Value>::New(external);
// V8::AdjustAmountOfExternalAllocatedMemory(100000000);
record.MakeWeak(NULL, GCWeakReferenceCallback); record.MakeWeak(NULL, GCWeakReferenceCallback);
return external; return external;
} }

60
ext/v8/v8_handle.cpp Normal file
View file

@ -0,0 +1,60 @@
#include "rr.h"
#include "v8_ref.h"
using namespace v8;
namespace {
VALUE New(VALUE self, VALUE handle) {
return rr_v8_ref_create(self, rr_v8_handle(handle));
}
VALUE IsEmpty(VALUE self) {
return rr_v82rb(rr_v8_handle(self).IsEmpty());
}
VALUE Clear(VALUE self) {
rr_v8_handle(self).Clear();
return Qnil;
}
VALUE Dispose(VALUE self) {
rr_v8_handle(self).Dispose();
return Qnil;
}
void NoopWeakReferenceCallback(Persistent<Value> object, void* parameter) {}
VALUE MakeWeak(VALUE self) {
rr_v8_handle(self).MakeWeak(0, NoopWeakReferenceCallback);
return Qnil;
}
VALUE ClearWeak(VALUE self) {
rr_v8_handle(self).ClearWeak();
return Qnil;
}
VALUE IsNearDeath(VALUE self) {
return rr_v82rb(rr_v8_handle(self).IsNearDeath());
}
VALUE IsWeak(VALUE self) {
return rr_v82rb(rr_v8_handle(self).IsWeak());
}
}
void rr_init_handle() {
VALUE HandleClass = rr_define_class("Handle");
rr_define_singleton_method(HandleClass, "New", New, 1);
rr_define_method(HandleClass, "IsEmpty", IsEmpty, 0);
rr_define_method(HandleClass, "Clear", Clear, 0);
rr_define_method(HandleClass, "Dispose", Dispose, 0);
rr_define_method(HandleClass, "MakeWeak", MakeWeak, 0);
rr_define_method(HandleClass, "ClearWeak", ClearWeak, 0);
rr_define_method(HandleClass, "IsNearDeath", IsNearDeath, 0);
rr_define_method(HandleClass, "IsWeak", IsWeak, 0);
}

8
ext/v8/v8_handle.h Normal file
View file

@ -0,0 +1,8 @@
#ifndef _RR_V8_HANDLE_
#define _RR_V8_HANDLE_
void rr_init_handle();
VALUE rr_v8_handle_new(v8::Local<void>& handle);
VALUE rr_v8_handle_new(v8::Persistent<void>& handle);
#endif

View file

@ -4,37 +4,56 @@ require 'weakref'
describe "Memory Usage" do describe "Memory Usage" do
context "for low level C interface" do context "the low level C interface" do
it "does not leak a context" do context "at the very minimum" do
weak :context, V8::C::Context::New() it "does not leak a context" do
weak :context, V8::C::Context::New()
end
it "does not leak a simple object either" do
cxt = V8::C::Context::New()
cxt.Enter()
begin
weak :object, V8::C::Object::New()
ensure
cxt.Exit()
end
end
end end
it "does not leak a simple object either" do context "a ruby proxy for a JavaScript object" do
cxt = V8::C::Context::New() it "holds a strong reference to the JavaScript object" do
cxt.Enter() pending
begin cxt = V8::C::Context::New()
weak :object, V8::C::Object::New() handle = c::Handle::New(cxt)
ensure handle.MakeWeak()
cxt.Exit() gc do
handle.IsEmpty().should be_false
handle.IsNearDeath().should be_false
handle.IsWeak().should be_true
end
cxt = nil
gc do
# handle.IsEmpty().should be_true
handle.IsNearDeath().should be_true
end
end end
end end
end end
before(:all) {GC.stress = true} before(:all) {@stress = GC.stress; GC.stress = true}
after(:all) {GC.stress = false} after(:all) {GC.stress = @stress}
before do before do
@refs = {} @refs = {}
end end
after do after do
GC.start gc do
while !V8::C::V8::IdleNotification();end for name, ref in @refs
GC.start if ref.weakref_alive?
while !V8::C::V8::IdleNotification();end fail "reference #{name} was not garbage collected"
for name, ref in @refs end
if ref.weakref_alive?
fail "refererc #{name} was not garbage collected"
end end
end end
end end
@ -45,4 +64,16 @@ describe "Memory Usage" do
@refs[name] = WeakRef.new(ref) @refs[name] = WeakRef.new(ref)
end end
def gc
GC.start
while !V8::C::V8::IdleNotification();end
GC.start
while !V8::C::V8::IdleNotification();end
yield
end
def c
V8::C
end
end if GC.respond_to?(:stress=) end if GC.respond_to?(:stress=)