mirror of
https://github.com/rubyjs/mini_racer
synced 2023-03-27 23:21:28 -04:00
Making it possible to set V8 runtime flags
Only caveat: such flags can only be set before the V8 platform gets initialized. Comes in handy to deactivate for example V8's aggressive use of `pthread` which somehow seems to not play too nice with Unicorn: ``` MiniRacer::Platform.set_flag! '--noconcurrent_recompilation' MiniRacer::Platform.set_flag! '--noconcurrent_sweeping' ``` Also protecting the platform initialization with a mutex, not sure how/why current concurrent tests never seem to hit bugs without that mutex. Added just one test on the new `MiniRacer::Platform.set_flag!` method, and unsure how to make other tests without making tests run in order (bad), given that flags can only be set before anything else is done.
This commit is contained in:
parent
bddbdcd284
commit
42475db467
3 changed files with 52 additions and 4 deletions
|
@ -6,6 +6,7 @@
|
|||
#include <ruby/encoding.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <mutex>
|
||||
|
||||
using namespace v8;
|
||||
|
||||
|
@ -52,18 +53,48 @@ static VALUE rb_eParseError;
|
|||
static VALUE rb_eScriptRuntimeError;
|
||||
static VALUE rb_cJavaScriptFunction;
|
||||
static VALUE rb_eSnapshotError;
|
||||
static VALUE rb_ePlatformAlreadyInitializedError;
|
||||
|
||||
static VALUE rb_cDateTime = Qnil;
|
||||
|
||||
static Platform* current_platform = NULL;
|
||||
static std::mutex platform_lock;
|
||||
|
||||
static VALUE rb_platform_set_flag(VALUE _klass, VALUE flag_as_str) {
|
||||
bool platform_already_initialized = false;
|
||||
|
||||
platform_lock.lock();
|
||||
|
||||
if (current_platform == NULL) {
|
||||
V8::SetFlagsFromString(RSTRING_PTR(flag_as_str), (int)RSTRING_LEN(flag_as_str));
|
||||
} else {
|
||||
platform_already_initialized = true;
|
||||
}
|
||||
|
||||
platform_lock.unlock();
|
||||
|
||||
// important to raise outside of the lock
|
||||
if (platform_already_initialized) {
|
||||
rb_raise(rb_ePlatformAlreadyInitializedError, "The V8 platform is already initialized");
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static void init_v8() {
|
||||
// no need to wait for the lock if already initialized
|
||||
if (current_platform != NULL) return;
|
||||
|
||||
platform_lock.lock();
|
||||
|
||||
if (current_platform == NULL) {
|
||||
V8::InitializeICU();
|
||||
current_platform = platform::CreateDefaultPlatform();
|
||||
V8::InitializePlatform(current_platform);
|
||||
V8::Initialize();
|
||||
V8::InitializeICU();
|
||||
current_platform = platform::CreateDefaultPlatform();
|
||||
V8::InitializePlatform(current_platform);
|
||||
V8::Initialize();
|
||||
}
|
||||
|
||||
platform_lock.unlock();
|
||||
}
|
||||
|
||||
void* breaker(void *d) {
|
||||
|
@ -720,6 +751,7 @@ extern "C" {
|
|||
VALUE rb_mMiniRacer = rb_define_module("MiniRacer");
|
||||
VALUE rb_cContext = rb_define_class_under(rb_mMiniRacer, "Context", rb_cObject);
|
||||
VALUE rb_cSnapshot = rb_define_class_under(rb_mMiniRacer, "Snapshot", rb_cObject);
|
||||
VALUE rb_cPlatform = rb_define_class_under(rb_mMiniRacer, "Platform", rb_cObject);
|
||||
|
||||
VALUE rb_eEvalError = rb_define_class_under(rb_mMiniRacer, "EvalError", rb_eStandardError);
|
||||
rb_eScriptTerminatedError = rb_define_class_under(rb_mMiniRacer, "ScriptTerminatedError", rb_eEvalError);
|
||||
|
@ -727,6 +759,7 @@ extern "C" {
|
|||
rb_eScriptRuntimeError = rb_define_class_under(rb_mMiniRacer, "RuntimeError", rb_eEvalError);
|
||||
rb_cJavaScriptFunction = rb_define_class_under(rb_mMiniRacer, "JavaScriptFunction", rb_cObject);
|
||||
rb_eSnapshotError = rb_define_class_under(rb_mMiniRacer, "SnapshotError", rb_eStandardError);
|
||||
rb_ePlatformAlreadyInitializedError = rb_define_class_under(rb_mMiniRacer, "PlatformAlreadyInitialized", rb_eStandardError);
|
||||
|
||||
VALUE rb_cExternalFunction = rb_define_class_under(rb_cContext, "ExternalFunction", rb_cObject);
|
||||
rb_define_method(rb_cContext, "stop", (VALUE(*)(...))&rb_context_stop, 0);
|
||||
|
@ -741,6 +774,8 @@ extern "C" {
|
|||
rb_define_method(rb_cSnapshot, "size", (VALUE(*)(...))&rb_snapshot_size, 0);
|
||||
rb_define_method(rb_cSnapshot, "warmup", (VALUE(*)(...))&rb_snapshot_warmup, 1);
|
||||
rb_define_private_method(rb_cSnapshot, "load", (VALUE(*)(...))&rb_snapshot_load, 1);
|
||||
|
||||
rb_define_singleton_method(rb_cPlatform, "set_flag!", (VALUE(*)(...))&rb_platform_set_flag, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ module MiniRacer
|
|||
class ScriptTerminatedError < EvalError; end
|
||||
class ParseError < EvalError; end
|
||||
class SnapshotError < StandardError; end
|
||||
class PlatformAlreadyInitialized < StandardError; end
|
||||
|
||||
class RuntimeError < EvalError
|
||||
def initialize(message)
|
||||
|
@ -39,6 +40,9 @@ module MiniRacer
|
|||
end
|
||||
end
|
||||
|
||||
# `::set_flag!` is defined in the C class
|
||||
class Platform; end
|
||||
|
||||
# eval is defined in the C class
|
||||
class Context
|
||||
|
||||
|
|
|
@ -357,4 +357,13 @@ raise FooError, "I like foos"
|
|||
|
||||
assert_equal 1, context.eval("Math.sin")
|
||||
end
|
||||
|
||||
def test_platform_set_flag_raises_an_exception_if_already_initialized
|
||||
# makes sure it's initialized
|
||||
MiniRacer::Snapshot.new
|
||||
|
||||
assert_raises(MiniRacer::PlatformAlreadyInitialized) do
|
||||
MiniRacer::Platform.set_flag!("--noconcurrent_recompilation")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue