mirror of
https://github.com/rubyjs/therubyracer
synced 2023-03-27 23:21:42 -04:00
add Context#dispose() for explicit teardown.
This commit is contained in:
parent
22f21e7c86
commit
8693cddf0a
6 changed files with 116 additions and 5 deletions
|
@ -9,6 +9,7 @@ void Context::Init() {
|
|||
defineSingletonMethod("GetEntered", &GetEntered).
|
||||
defineSingletonMethod("GetCalling", &GetCalling).
|
||||
defineSingletonMethod("InContext", &InContext).
|
||||
defineMethod("Dispose", &Dispose).
|
||||
defineMethod("Global", &Global).
|
||||
defineMethod("DetachGlobal", &Global).
|
||||
defineMethod("ReattachGlobal", &ReattachGlobal).
|
||||
|
@ -28,6 +29,10 @@ void Context::Init() {
|
|||
store(&ExtensionConfiguration::Class);
|
||||
}
|
||||
|
||||
VALUE Context::Dispose(VALUE self) {
|
||||
Void(Context(self).dispose())
|
||||
}
|
||||
|
||||
VALUE Context::Global(VALUE self) {
|
||||
return Object(Context(self)->Global());
|
||||
}
|
||||
|
|
29
ext/v8/rr.h
29
ext/v8/rr.h
|
@ -131,6 +131,11 @@ public:
|
|||
return v8::Handle<T>();
|
||||
}
|
||||
}
|
||||
void dispose() {
|
||||
Holder* holder = NULL;
|
||||
Data_Get_Struct(this->value, class Holder, holder);
|
||||
holder->dispose();
|
||||
}
|
||||
|
||||
inline v8::Handle<T> operator->() const { return *this;}
|
||||
inline v8::Handle<T> operator*() const {return *this;}
|
||||
|
@ -153,15 +158,23 @@ public:
|
|||
friend class Ref;
|
||||
public:
|
||||
Holder(v8::Handle<T> handle, VALUE klass) {
|
||||
this->disposed_p = false;
|
||||
this->handle = v8::Persistent<T>::New(handle);
|
||||
this->value = Data_Wrap_Struct(klass, 0, &enqueue, this);
|
||||
}
|
||||
virtual ~Holder() {
|
||||
handle.Dispose();
|
||||
this->dispose();
|
||||
}
|
||||
void dispose() {
|
||||
if (!this->disposed_p) {
|
||||
handle.Dispose();
|
||||
this->disposed_p = true;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
VALUE value;
|
||||
v8::Persistent<T> handle;
|
||||
bool disposed_p;
|
||||
|
||||
static void enqueue(Holder* holder) {
|
||||
holder->value = Qnil;
|
||||
|
@ -225,6 +238,7 @@ class Context : public Ref<v8::Context> {
|
|||
public:
|
||||
static void Init();
|
||||
static VALUE New(int argc, VALUE argv[], VALUE self);
|
||||
static VALUE Dispose(VALUE self);
|
||||
static VALUE Enter(VALUE self);
|
||||
static VALUE Exit(VALUE self);
|
||||
static VALUE Global(VALUE self);
|
||||
|
@ -800,6 +814,19 @@ class V8 {
|
|||
public:
|
||||
static void Init();
|
||||
static VALUE IdleNotification(int argc, VALUE argv[], VALUE self);
|
||||
static VALUE SetFlagsFromString(VALUE self, VALUE string);
|
||||
static VALUE SetFlagsFromCommandLine(VALUE self, VALUE args, VALUE remove_flags);
|
||||
static VALUE AdjustAmountOfExternalAllocatedMemory(VALUE self, VALUE change_in_bytes);
|
||||
static VALUE PauseProfiler(VALUE self);
|
||||
static VALUE ResumeProfiler(VALUE self);
|
||||
static VALUE IsProfilerPaused(VALUE self);
|
||||
static VALUE GetCurrentThreadId(VALUE self);
|
||||
static VALUE TerminateExecution(VALUE self, VALUE thread_id);
|
||||
static VALUE IsExecutionTerminating(VALUE self);
|
||||
static VALUE Dispose(VALUE self);
|
||||
static VALUE LowMemoryNotification(VALUE self);
|
||||
static VALUE ContextDisposedNotification(VALUE self);
|
||||
|
||||
static VALUE SetCaptureStackTraceForUncaughtExceptions(int argc, VALUE argv[], VALUE self);
|
||||
static VALUE GetHeapStatistics(VALUE self, VALUE statistics_ptr);
|
||||
static VALUE GetVersion(VALUE self);
|
||||
|
|
57
ext/v8/v8.cc
57
ext/v8/v8.cc
|
@ -5,7 +5,18 @@ namespace rr {
|
|||
void V8::Init() {
|
||||
ClassBuilder("V8").
|
||||
defineSingletonMethod("IdleNotification", &IdleNotification).
|
||||
defineSingletonMethod("SetCaptureStackTraceForUncaughtExceptions", &SetCaptureStackTraceForUncaughtExceptions).
|
||||
defineSingletonMethod("SetFlagsFromString", &SetFlagsFromString).
|
||||
defineSingletonMethod("SetFlagsFromCommandLine", &SetFlagsFromCommandLine).
|
||||
defineSingletonMethod("PauseProfiler", &PauseProfiler).
|
||||
defineSingletonMethod("ResumeProfiler", &ResumeProfiler).
|
||||
defineSingletonMethod("IsProfilerPaused", &IsProfilerPaused).
|
||||
defineSingletonMethod("GetCurrentThreadId", &GetCurrentThreadId).
|
||||
defineSingletonMethod("TerminateExecution", &TerminateExecution).
|
||||
defineSingletonMethod("IsExecutionTerminating", &IsExecutionTerminating).
|
||||
defineSingletonMethod("Dispose", &Dispose).
|
||||
defineSingletonMethod("LowMemoryNotification", &LowMemoryNotification).
|
||||
defineSingletonMethod("AdjustAmountOfExternalAllocatedMemory", &AdjustAmountOfExternalAllocatedMemory).
|
||||
defineSingletonMethod("ContextDisposedNotification", &ContextDisposedNotification).
|
||||
defineSingletonMethod("GetHeapStatistics", &GetHeapStatistics).
|
||||
defineSingletonMethod("GetVersion", &GetVersion);
|
||||
}
|
||||
|
@ -19,18 +30,56 @@ VALUE V8::IdleNotification(int argc, VALUE argv[], VALUE self) {
|
|||
return Bool(v8::V8::IdleNotification());
|
||||
}
|
||||
}
|
||||
|
||||
VALUE V8::SetFlagsFromString(VALUE self, VALUE string) {
|
||||
Void(v8::V8::SetFlagsFromString(RSTRING_PTR(string), (int)RSTRING_LEN(string)));
|
||||
}
|
||||
VALUE V8::SetFlagsFromCommandLine(VALUE self, VALUE args, VALUE remove_flags) {
|
||||
int argc = RARRAY_LENINT(args);
|
||||
char* argv[argc];
|
||||
for(int i = 0; i < argc; i++) {
|
||||
argv[i] = RSTRING_PTR(rb_ary_entry(args, i));
|
||||
}
|
||||
Void(v8::V8::SetFlagsFromCommandLine(&argc, argv, Bool(remove_flags)));
|
||||
}
|
||||
VALUE V8::AdjustAmountOfExternalAllocatedMemory(VALUE self, VALUE change_in_bytes) {
|
||||
return SIZET2NUM(v8::V8::AdjustAmountOfExternalAllocatedMemory(NUM2SIZET(change_in_bytes)));
|
||||
}
|
||||
VALUE V8::PauseProfiler(VALUE self) {
|
||||
Void(v8::V8::PauseProfiler());
|
||||
}
|
||||
VALUE V8::ResumeProfiler(VALUE self) {
|
||||
Void(v8::V8::ResumeProfiler());
|
||||
}
|
||||
VALUE V8::IsProfilerPaused(VALUE self) {
|
||||
return Bool(v8::V8::IsProfilerPaused());
|
||||
}
|
||||
VALUE V8::GetCurrentThreadId(VALUE self) {
|
||||
return INT2FIX(v8::V8::GetCurrentThreadId());
|
||||
}
|
||||
VALUE V8::TerminateExecution(VALUE self, VALUE thread_id) {
|
||||
Void(v8::V8::TerminateExecution(NUM2INT(thread_id)));
|
||||
}
|
||||
VALUE V8::IsExecutionTerminating(VALUE self) {
|
||||
return Bool(v8::V8::IsExecutionTerminating());
|
||||
}
|
||||
VALUE V8::Dispose(VALUE self) {
|
||||
Void(v8::V8::Dispose());
|
||||
}
|
||||
VALUE V8::LowMemoryNotification(VALUE self) {
|
||||
Void(v8::V8::LowMemoryNotification());
|
||||
}
|
||||
VALUE V8::ContextDisposedNotification(VALUE self) {
|
||||
return INT2FIX(v8::V8::ContextDisposedNotification());
|
||||
}
|
||||
VALUE V8::SetCaptureStackTraceForUncaughtExceptions(int argc, VALUE argv[], VALUE self) {
|
||||
VALUE should_capture; VALUE frame_limit; VALUE options;
|
||||
rb_scan_args(argc, argv, "12", &should_capture, &frame_limit, &options);
|
||||
int limit = RTEST(frame_limit) ? NUM2INT(frame_limit) : 10;
|
||||
Void(v8::V8::SetCaptureStackTraceForUncaughtExceptions(Bool(should_capture), limit, Stack::Trace::StackTraceOptions(options)));
|
||||
}
|
||||
|
||||
VALUE V8::GetHeapStatistics(VALUE self, VALUE statistics_ptr) {
|
||||
Void(v8::V8::GetHeapStatistics(HeapStatistics(statistics_ptr)));
|
||||
}
|
||||
|
||||
VALUE V8::GetVersion(VALUE self) {
|
||||
return rb_str_new2(v8::V8::GetVersion());
|
||||
}
|
||||
|
|
|
@ -42,6 +42,16 @@ module V8
|
|||
return value
|
||||
end
|
||||
|
||||
def dispose
|
||||
return unless @native
|
||||
@native.Dispose()
|
||||
@native = nil
|
||||
V8::C::V8::ContextDisposedNotification()
|
||||
def self.enter
|
||||
fail "cannot enter a context which has already been disposed"
|
||||
end
|
||||
end
|
||||
|
||||
def scope
|
||||
enter { to_ruby @native.Global() }
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
require 'v8'
|
||||
|
||||
def run_v8_gc
|
||||
V8::C::V8::LowMemoryNotification()
|
||||
while !V8::C::V8::IdleNotification() do
|
||||
end
|
||||
end
|
||||
|
|
19
spec/v8/context_spec.rb
Normal file
19
spec/v8/context_spec.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe V8::Context do
|
||||
it "can be disposed of" do
|
||||
cxt = V8::Context.new
|
||||
cxt.enter do
|
||||
cxt['object'] = V8::Object.new
|
||||
end
|
||||
cxt.dispose()
|
||||
|
||||
lambda {cxt.eval('1 + 1')}.should raise_error
|
||||
lambda {cxt['object']}.should raise_error
|
||||
end
|
||||
|
||||
it "can be disposed of any number of times" do
|
||||
cxt = V8::Context.new
|
||||
10.times {cxt.dispose()}
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue