mirror of
https://github.com/rubyjs/therubyracer
synced 2023-03-27 23:21:42 -04:00
handle checkpoint.
This commit is contained in:
parent
fdb62441b1
commit
0ffce72fe1
5 changed files with 140 additions and 42 deletions
|
@ -1,3 +1,4 @@
|
|||
#include "v8_handle.h"
|
||||
#include "v8_cxt.h"
|
||||
#include "v8_value.h"
|
||||
#include "v8_str.h"
|
||||
|
@ -19,27 +20,28 @@
|
|||
#include <stdio.h>
|
||||
|
||||
extern "C" {
|
||||
void Init_v8();
|
||||
void Init_v8();
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
void Init_v8() {
|
||||
rr_init_cxt();
|
||||
rr_init_value();
|
||||
rr_init_str();
|
||||
rr_init_script();
|
||||
rr_init_template();
|
||||
rr_init_obj();
|
||||
rr_init_func();
|
||||
rr_init_v8_array();
|
||||
rr_init_v8_date();
|
||||
rr_init_msg();
|
||||
rr_init_v8_try_catch();
|
||||
rr_init_v8_callbacks();
|
||||
rr_init_v8_external();
|
||||
rr_init_v8_exception();
|
||||
rr_init_v8_locker();
|
||||
rr_init_v8_debug();
|
||||
rr_init_v8_v8();
|
||||
}
|
||||
void Init_v8() {
|
||||
rr_init_handle();
|
||||
rr_init_cxt();
|
||||
rr_init_value();
|
||||
rr_init_str();
|
||||
rr_init_script();
|
||||
rr_init_template();
|
||||
rr_init_obj();
|
||||
rr_init_func();
|
||||
rr_init_v8_array();
|
||||
rr_init_v8_date();
|
||||
rr_init_msg();
|
||||
rr_init_v8_try_catch();
|
||||
rr_init_v8_callbacks();
|
||||
rr_init_v8_external();
|
||||
rr_init_v8_exception();
|
||||
rr_init_v8_locker();
|
||||
rr_init_v8_debug();
|
||||
rr_init_v8_v8();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,10 +27,8 @@ namespace {
|
|||
return (VALUE)V8_Ref_Get<External>(self)->Value();
|
||||
}
|
||||
void GCWeakReferenceCallback(Persistent<Value> object, void* parameter) {
|
||||
// printf("V8 GC!!!!\n");
|
||||
Local<External> external(External::Cast(*object));
|
||||
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);
|
||||
Local<Value> external(External::New((void *)value));
|
||||
Persistent<Value> record = Persistent<Value>::New(external);
|
||||
// V8::AdjustAmountOfExternalAllocatedMemory(100000000);
|
||||
record.MakeWeak(NULL, GCWeakReferenceCallback);
|
||||
return external;
|
||||
}
|
60
ext/v8/v8_handle.cpp
Normal file
60
ext/v8/v8_handle.cpp
Normal 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
8
ext/v8/v8_handle.h
Normal 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
|
|
@ -4,37 +4,56 @@ require 'weakref'
|
|||
|
||||
describe "Memory Usage" do
|
||||
|
||||
context "for low level C interface" do
|
||||
it "does not leak a context" do
|
||||
weak :context, V8::C::Context::New()
|
||||
context "the low level C interface" do
|
||||
context "at the very minimum" do
|
||||
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
|
||||
|
||||
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()
|
||||
context "a ruby proxy for a JavaScript object" do
|
||||
it "holds a strong reference to the JavaScript object" do
|
||||
pending
|
||||
cxt = V8::C::Context::New()
|
||||
handle = c::Handle::New(cxt)
|
||||
handle.MakeWeak()
|
||||
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
|
||||
|
||||
before(:all) {GC.stress = true}
|
||||
after(:all) {GC.stress = false}
|
||||
before(:all) {@stress = GC.stress; GC.stress = true}
|
||||
after(:all) {GC.stress = @stress}
|
||||
|
||||
before do
|
||||
@refs = {}
|
||||
end
|
||||
|
||||
after do
|
||||
GC.start
|
||||
while !V8::C::V8::IdleNotification();end
|
||||
GC.start
|
||||
while !V8::C::V8::IdleNotification();end
|
||||
for name, ref in @refs
|
||||
if ref.weakref_alive?
|
||||
fail "refererc #{name} was not garbage collected"
|
||||
gc do
|
||||
for name, ref in @refs
|
||||
if ref.weakref_alive?
|
||||
fail "reference #{name} was not garbage collected"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -45,4 +64,16 @@ describe "Memory Usage" do
|
|||
@refs[name] = WeakRef.new(ref)
|
||||
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=)
|
Loading…
Add table
Reference in a new issue