Files
2020-03-02 14:53:23 +07:00

140 lines
4.7 KiB
Diff

From d1cacb814f6d42395184beaaba906ba930e711eb Mon Sep 17 00:00:00 2001
From: Fedor Indutny <fedor@indutny.com>
Date: Wed, 20 Jan 2016 19:34:19 -0500
Subject: vm: introduce `cachedData`/`produceCachedData`
Introduce `cachedData`/`produceCachedData` options for `v8.Script`.
Could be used to consume/produce V8's code cache for speeding up
compilation of known code.
PR-URL: https://github.com/nodejs/node/pull/4777
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
diff --git a/src/node_contextify.cc b/src/node_contextify.cc
index 2e8fd2c..1b3d618 100644
--- a/src/node_contextify.cc
+++ b/src/node_contextify.cc
@@ -18,10 +18,11 @@
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "node.h"
+#include "node_buffer.h"
#include "node_internals.h"
#include "node_watchdog.h"
#include "base-object.h"
#include "base-object-inl.h"
#include "env.h"
@@ -484,28 +485,60 @@ class ContextifyScript : public BaseObject {
TryCatch try_catch;
Local<String> code = args[0]->ToString();
Local<String> filename = GetFilenameArg(args, 1);
bool display_errors = GetDisplayErrorsArg(args, 1);
+ Local<Value> cached_data_buf = GetCachedData(args, 1);
+ bool produce_cached_data = GetProduceCachedData(args, 1);
if (try_catch.HasCaught()) {
try_catch.ReThrow();
return;
}
+ ScriptCompiler::CachedData* cached_data = NULL;
+ if (!cached_data_buf.IsEmpty()) {
+ cached_data = new ScriptCompiler::CachedData(
+ reinterpret_cast<uint8_t*>(Buffer::Data(cached_data_buf)),
+ Buffer::Length(cached_data_buf));
+ }
+
ScriptOrigin origin(filename);
- ScriptCompiler::Source source(code, origin);
- Local<UnboundScript> v8_script =
- ScriptCompiler::CompileUnbound(env->isolate(), &source);
+ ScriptCompiler::Source source(code, origin, cached_data);
+ ScriptCompiler::CompileOptions compile_options =
+ ScriptCompiler::kNoCompileOptions;
+
+ if (source.GetCachedData() != NULL)
+ compile_options = ScriptCompiler::kConsumeCodeCache;
+ else if (produce_cached_data)
+ compile_options = ScriptCompiler::kProduceCodeCache;
+
+ Local<UnboundScript> v8_script = ScriptCompiler::CompileUnbound(
+ env->isolate(),
+ &source,
+ compile_options);
if (v8_script.IsEmpty()) {
if (display_errors) {
AppendExceptionLine(env, try_catch.Exception(), try_catch.Message());
}
try_catch.ReThrow();
return;
}
contextify_script->script_.Reset(env->isolate(), v8_script);
+
+ if (compile_options == ScriptCompiler::kConsumeCodeCache) {
+ // no 'rejected' field in cachedData
+ } else if (compile_options == ScriptCompiler::kProduceCodeCache) {
+ const ScriptCompiler::CachedData* cached_data = source.GetCachedData();
+ Local<Object> buf = Buffer::New(
+ env,
+ reinterpret_cast<const char*>(cached_data->data),
+ cached_data->length);
+ Local<String> cached_data_string = FIXED_ONE_BYTE_STRING(
+ args.GetIsolate(), "cachedData");
+ args.This()->Set(cached_data_string, buf);
+ }
}
static bool InstanceOf(Environment* env, const Local<Value>& value) {
return !value.IsEmpty() &&
@@ -656,10 +689,46 @@ class ContextifyScript : public BaseObject {
return value->IsUndefined() ? defaultFilename : value->ToString();
}
+ static Local<Value> GetCachedData(
+ const FunctionCallbackInfo<Value>& args,
+ const int i) {
+ if (!args[i]->IsObject()) {
+ return Local<Value>();
+ }
+ Local<String> key = FIXED_ONE_BYTE_STRING(args.GetIsolate(), "cachedData");
+ Local<Value> value = args[i].As<Object>()->Get(key);
+ if (value->IsUndefined()) {
+ return Local<Value>();
+ }
+
+ if (!Buffer::HasInstance(value)) {
+ Environment::ThrowTypeError(
+ args.GetIsolate(),
+ "options.cachedData must be a Buffer instance");
+ return Local<Value>();
+ }
+
+ return value;
+ }
+
+
+ static bool GetProduceCachedData(
+ const FunctionCallbackInfo<Value>& args,
+ const int i) {
+ if (!args[i]->IsObject()) {
+ return false;
+ }
+ Local<String> key = FIXED_ONE_BYTE_STRING(args.GetIsolate(), "produceCachedData");
+ Local<Value> value = args[i].As<Object>()->Get(key);
+
+ return value->IsTrue();
+ }
+
+
static bool EvalMachine(Environment* env,
const int64_t timeout,
const bool display_errors,
const FunctionCallbackInfo<Value>& args,
TryCatch& try_catch) {