Change ScriptCompiler::CompileOptions to allow for two 'cache' modes
(parser or code) and to be explicit about cache consumption or production (rather than making presence of cached_data imply one or the other.) Also add a --cache flag to d8, to allow testing the functionality. ----------------------------- API change Reason: Currently, V8 supports a 'parser cache' for repeatedly executing the same script. We'd like to add a 2nd mode that would cache code, and would like to let the embedder decide which mode they chose (if any). Note: Previously, the 'use cached data' property was implied by the presence of the cached data itself. (That is, kNoCompileOptions and source->cached_data != NULL.) That is no longer sufficient, since the presence of data is no longer sufficient to determine /which kind/ of data is present. Changes from old behaviour: - If you previously didn't use caching, nothing changes. Example: v8::CompileUnbound(isolate, source, kNoCompileOptions); - If you previously used caching, it worked like this: - 1st run: v8::CompileUnbound(isolate, source, kProduceToCache); Then, source->cached_data would contain the data-to-be cached. This remains the same, except you need to tell V8 which type of data you want. v8::CompileUnbound(isolate, source, kProduceParserCache); - 2nd run: v8::CompileUnbound(isolate, source, kNoCompileOptions); with source->cached_data set to the data you received in the first run. This will now ignore the cached data, and you need to explicitly tell V8 to use it: v8::CompileUnbound(isolate, source, kConsumeParserCache); ----------------------------- BUG= R=marja@chromium.org, yangguo@chromium.org Review URL: https://codereview.chromium.org/389573006 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22431 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
5963ae48a8
commit
a42612b4a7
16
include/v8.h
16
include/v8.h
@ -1074,15 +1074,21 @@ class V8_EXPORT ScriptCompiler {
|
||||
Handle<Integer> resource_column_offset;
|
||||
Handle<Boolean> resource_is_shared_cross_origin;
|
||||
|
||||
// Cached data from previous compilation (if any), or generated during
|
||||
// compilation (if the generate_cached_data flag is passed to
|
||||
// ScriptCompiler).
|
||||
// Cached data from previous compilation (if a kConsume*Cache flag is
|
||||
// set), or hold newly generated cache data (kProduce*Cache flags) are
|
||||
// set when calling a compile method.
|
||||
CachedData* cached_data;
|
||||
};
|
||||
|
||||
enum CompileOptions {
|
||||
kNoCompileOptions,
|
||||
kProduceDataToCache = 1 << 0
|
||||
kNoCompileOptions = 0,
|
||||
kProduceParserCache,
|
||||
kConsumeParserCache,
|
||||
kProduceCodeCache,
|
||||
kConsumeCodeCache,
|
||||
|
||||
// Support the previous API for a transition period.
|
||||
kProduceDataToCache
|
||||
};
|
||||
|
||||
/**
|
||||
|
30
src/api.cc
30
src/api.cc
@ -1699,16 +1699,22 @@ Local<UnboundScript> ScriptCompiler::CompileUnbound(
|
||||
Isolate* v8_isolate,
|
||||
Source* source,
|
||||
CompileOptions options) {
|
||||
i::ScriptData* script_data = NULL;
|
||||
i::CachedDataMode cached_data_mode = i::NO_CACHED_DATA;
|
||||
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
|
||||
ON_BAILOUT(isolate, "v8::ScriptCompiler::CompileUnbound()",
|
||||
return Local<UnboundScript>());
|
||||
if (options & kProduceDataToCache) {
|
||||
cached_data_mode = i::PRODUCE_CACHED_DATA;
|
||||
CHECK(source->cached_data == NULL);
|
||||
} else if (source->cached_data) {
|
||||
cached_data_mode = i::CONSUME_CACHED_DATA;
|
||||
|
||||
// Support the old API for a transition period:
|
||||
// - kProduceToCache -> kProduceParserCache
|
||||
// - kNoCompileOptions + cached_data != NULL -> kConsumeParserCache
|
||||
if (options == kProduceDataToCache) {
|
||||
options = kProduceParserCache;
|
||||
} else if (options == kNoCompileOptions && source->cached_data) {
|
||||
options = kConsumeParserCache;
|
||||
}
|
||||
|
||||
i::ScriptData* script_data = NULL;
|
||||
if (options == kConsumeParserCache || options == kConsumeCodeCache) {
|
||||
ASSERT(source->cached_data);
|
||||
// ScriptData takes care of pointer-aligning the data.
|
||||
script_data = new i::ScriptData(source->cached_data->data,
|
||||
source->cached_data->length);
|
||||
@ -1741,10 +1747,10 @@ Local<UnboundScript> ScriptCompiler::CompileUnbound(
|
||||
EXCEPTION_PREAMBLE(isolate);
|
||||
i::Handle<i::SharedFunctionInfo> result = i::Compiler::CompileScript(
|
||||
str, name_obj, line_offset, column_offset, is_shared_cross_origin,
|
||||
isolate->global_context(), NULL, &script_data, cached_data_mode,
|
||||
isolate->global_context(), NULL, &script_data, options,
|
||||
i::NOT_NATIVES_CODE);
|
||||
has_pending_exception = result.is_null();
|
||||
if (has_pending_exception && cached_data_mode == i::CONSUME_CACHED_DATA) {
|
||||
if (has_pending_exception && script_data != NULL) {
|
||||
// This case won't happen during normal operation; we have compiled
|
||||
// successfully and produced cached data, and but the second compilation
|
||||
// of the same source code fails.
|
||||
@ -1753,8 +1759,10 @@ Local<UnboundScript> ScriptCompiler::CompileUnbound(
|
||||
}
|
||||
EXCEPTION_BAILOUT_CHECK(isolate, Local<UnboundScript>());
|
||||
raw_result = *result;
|
||||
if ((options & kProduceDataToCache) && script_data != NULL) {
|
||||
// script_data_impl now contains the data that was generated. source will
|
||||
|
||||
if ((options == kProduceParserCache || options == kProduceCodeCache) &&
|
||||
script_data != NULL) {
|
||||
// script_data now contains the data that was generated. source will
|
||||
// take the ownership.
|
||||
source->cached_data = new CachedData(
|
||||
script_data->data(), script_data->length(), CachedData::BufferOwned);
|
||||
|
@ -1504,15 +1504,8 @@ bool Genesis::CompileScriptCached(Isolate* isolate,
|
||||
Handle<String> script_name =
|
||||
factory->NewStringFromUtf8(name).ToHandleChecked();
|
||||
function_info = Compiler::CompileScript(
|
||||
source,
|
||||
script_name,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
top_context,
|
||||
extension,
|
||||
NULL,
|
||||
NO_CACHED_DATA,
|
||||
source, script_name, 0, 0, false, top_context, extension, NULL,
|
||||
ScriptCompiler::kNoCompileOptions,
|
||||
use_runtime_context ? NATIVES_CODE : NOT_NATIVES_CODE);
|
||||
if (function_info.is_null()) return false;
|
||||
if (cache != NULL) cache->Add(name, function_info);
|
||||
|
@ -113,7 +113,7 @@ void CompilationInfo::Initialize(Isolate* isolate,
|
||||
global_scope_ = NULL;
|
||||
extension_ = NULL;
|
||||
cached_data_ = NULL;
|
||||
cached_data_mode_ = NO_CACHED_DATA;
|
||||
compile_options_ = ScriptCompiler::kNoCompileOptions;
|
||||
zone_ = zone;
|
||||
deferred_handles_ = NULL;
|
||||
code_stub_ = NULL;
|
||||
@ -800,18 +800,20 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
|
||||
ASSERT(info->is_eval() || info->is_global());
|
||||
|
||||
bool parse_allow_lazy =
|
||||
(info->cached_data_mode() == CONSUME_CACHED_DATA ||
|
||||
(info->compile_options() == ScriptCompiler::kConsumeParserCache ||
|
||||
String::cast(script->source())->length() > FLAG_min_preparse_length) &&
|
||||
!DebuggerWantsEagerCompilation(info);
|
||||
|
||||
if (!parse_allow_lazy && info->cached_data_mode() != NO_CACHED_DATA) {
|
||||
if (!parse_allow_lazy &&
|
||||
(info->compile_options() == ScriptCompiler::kProduceParserCache ||
|
||||
info->compile_options() == ScriptCompiler::kConsumeParserCache)) {
|
||||
// We are going to parse eagerly, but we either 1) have cached data produced
|
||||
// by lazy parsing or 2) are asked to generate cached data. We cannot use
|
||||
// the existing data, since it won't contain all the symbols we need for
|
||||
// eager parsing. In addition, it doesn't make sense to produce the data
|
||||
// when parsing eagerly. That data would contain all symbols, but no
|
||||
// functions, so it cannot be used to aid lazy parsing later.
|
||||
info->SetCachedData(NULL, NO_CACHED_DATA);
|
||||
info->SetCachedData(NULL, ScriptCompiler::kNoCompileOptions);
|
||||
}
|
||||
|
||||
Handle<SharedFunctionInfo> result;
|
||||
@ -932,23 +934,19 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
|
||||
|
||||
|
||||
Handle<SharedFunctionInfo> Compiler::CompileScript(
|
||||
Handle<String> source,
|
||||
Handle<Object> script_name,
|
||||
int line_offset,
|
||||
int column_offset,
|
||||
bool is_shared_cross_origin,
|
||||
Handle<Context> context,
|
||||
v8::Extension* extension,
|
||||
ScriptData** cached_data,
|
||||
CachedDataMode cached_data_mode,
|
||||
NativesFlag natives) {
|
||||
if (cached_data_mode == NO_CACHED_DATA) {
|
||||
Handle<String> source, Handle<Object> script_name, int line_offset,
|
||||
int column_offset, bool is_shared_cross_origin, Handle<Context> context,
|
||||
v8::Extension* extension, ScriptData** cached_data,
|
||||
ScriptCompiler::CompileOptions compile_options, NativesFlag natives) {
|
||||
if (compile_options == ScriptCompiler::kNoCompileOptions) {
|
||||
cached_data = NULL;
|
||||
} else if (cached_data_mode == PRODUCE_CACHED_DATA) {
|
||||
} else if (compile_options == ScriptCompiler::kProduceParserCache ||
|
||||
compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
ASSERT(cached_data && !*cached_data);
|
||||
ASSERT(extension == NULL);
|
||||
} else {
|
||||
ASSERT(cached_data_mode == CONSUME_CACHED_DATA);
|
||||
ASSERT(compile_options == ScriptCompiler::kConsumeParserCache ||
|
||||
compile_options == ScriptCompiler::kConsumeCodeCache);
|
||||
ASSERT(cached_data && *cached_data);
|
||||
ASSERT(extension == NULL);
|
||||
}
|
||||
@ -967,7 +965,7 @@ Handle<SharedFunctionInfo> Compiler::CompileScript(
|
||||
source, script_name, line_offset, column_offset,
|
||||
is_shared_cross_origin, context);
|
||||
if (maybe_result.is_null() && FLAG_serialize_toplevel &&
|
||||
cached_data_mode == CONSUME_CACHED_DATA) {
|
||||
compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
return CodeSerializer::Deserialize(isolate, *cached_data, source);
|
||||
}
|
||||
}
|
||||
@ -990,10 +988,11 @@ Handle<SharedFunctionInfo> Compiler::CompileScript(
|
||||
// Compile the function and add it to the cache.
|
||||
CompilationInfoWithZone info(script);
|
||||
info.MarkAsGlobal();
|
||||
info.SetCachedData(cached_data, cached_data_mode);
|
||||
info.SetCachedData(cached_data, compile_options);
|
||||
info.SetExtension(extension);
|
||||
info.SetContext(context);
|
||||
if (FLAG_serialize_toplevel && cached_data_mode == PRODUCE_CACHED_DATA) {
|
||||
if (FLAG_serialize_toplevel &&
|
||||
compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
info.PrepareForSerializing();
|
||||
}
|
||||
if (FLAG_use_strict) info.SetStrictMode(STRICT);
|
||||
@ -1001,10 +1000,12 @@ Handle<SharedFunctionInfo> Compiler::CompileScript(
|
||||
result = CompileToplevel(&info);
|
||||
if (extension == NULL && !result.is_null() && !result->dont_cache()) {
|
||||
compilation_cache->PutScript(source, context, result);
|
||||
if (FLAG_serialize_toplevel && cached_data_mode == PRODUCE_CACHED_DATA) {
|
||||
if (FLAG_serialize_toplevel &&
|
||||
compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
*cached_data = CodeSerializer::Serialize(isolate, result, source);
|
||||
}
|
||||
}
|
||||
|
||||
if (result.is_null()) isolate->ReportPendingMessages();
|
||||
} else if (result->ic_age() != isolate->heap()->global_ic_age()) {
|
||||
result->ResetForNewContext(isolate->heap()->global_ic_age());
|
||||
|
@ -22,12 +22,6 @@ enum ParseRestriction {
|
||||
ONLY_SINGLE_FUNCTION_LITERAL // Only a single FunctionLiteral expression.
|
||||
};
|
||||
|
||||
enum CachedDataMode {
|
||||
NO_CACHED_DATA,
|
||||
CONSUME_CACHED_DATA,
|
||||
PRODUCE_CACHED_DATA
|
||||
};
|
||||
|
||||
struct OffsetRange {
|
||||
OffsetRange(int from, int to) : from(from), to(to) {}
|
||||
int from;
|
||||
@ -90,8 +84,8 @@ class CompilationInfo {
|
||||
HydrogenCodeStub* code_stub() const {return code_stub_; }
|
||||
v8::Extension* extension() const { return extension_; }
|
||||
ScriptData** cached_data() const { return cached_data_; }
|
||||
CachedDataMode cached_data_mode() const {
|
||||
return cached_data_mode_;
|
||||
ScriptCompiler::CompileOptions compile_options() const {
|
||||
return compile_options_;
|
||||
}
|
||||
Handle<Context> context() const { return context_; }
|
||||
BailoutId osr_ast_id() const { return osr_ast_id_; }
|
||||
@ -227,9 +221,9 @@ class CompilationInfo {
|
||||
extension_ = extension;
|
||||
}
|
||||
void SetCachedData(ScriptData** cached_data,
|
||||
CachedDataMode cached_data_mode) {
|
||||
cached_data_mode_ = cached_data_mode;
|
||||
if (cached_data_mode == NO_CACHED_DATA) {
|
||||
ScriptCompiler::CompileOptions compile_options) {
|
||||
compile_options_ = compile_options;
|
||||
if (compile_options == ScriptCompiler::kNoCompileOptions) {
|
||||
cached_data_ = NULL;
|
||||
} else {
|
||||
ASSERT(!is_lazy());
|
||||
@ -461,7 +455,7 @@ class CompilationInfo {
|
||||
// Fields possibly needed for eager compilation, NULL by default.
|
||||
v8::Extension* extension_;
|
||||
ScriptData** cached_data_;
|
||||
CachedDataMode cached_data_mode_;
|
||||
ScriptCompiler::CompileOptions compile_options_;
|
||||
|
||||
// The context of the caller for eval code, and the global context for a
|
||||
// global script. Will be a null handle otherwise.
|
||||
@ -692,15 +686,10 @@ class Compiler : public AllStatic {
|
||||
|
||||
// Compile a String source within a context.
|
||||
static Handle<SharedFunctionInfo> CompileScript(
|
||||
Handle<String> source,
|
||||
Handle<Object> script_name,
|
||||
int line_offset,
|
||||
int column_offset,
|
||||
bool is_shared_cross_origin,
|
||||
Handle<Context> context,
|
||||
v8::Extension* extension,
|
||||
ScriptData** cached_data,
|
||||
CachedDataMode cached_data_mode,
|
||||
Handle<String> source, Handle<Object> script_name, int line_offset,
|
||||
int column_offset, bool is_shared_cross_origin, Handle<Context> context,
|
||||
v8::Extension* extension, ScriptData** cached_data,
|
||||
ScriptCompiler::CompileOptions compile_options,
|
||||
NativesFlag is_natives_code);
|
||||
|
||||
// Create a shared function info object (the code may be lazily compiled).
|
||||
|
49
src/d8.cc
49
src/d8.cc
@ -170,6 +170,36 @@ const char* Shell::ToCString(const v8::String::Utf8Value& value) {
|
||||
}
|
||||
|
||||
|
||||
// Compile a string within the current v8 context.
|
||||
Local<UnboundScript> Shell::CompileString(
|
||||
Isolate* isolate, Local<String> source, Local<Value> name,
|
||||
v8::ScriptCompiler::CompileOptions compile_options) {
|
||||
ScriptOrigin origin(name);
|
||||
ScriptCompiler::Source script_source(source, origin);
|
||||
Local<UnboundScript> script =
|
||||
ScriptCompiler::CompileUnbound(isolate, &script_source, compile_options);
|
||||
|
||||
// Was caching requested & successful? Then compile again, now with cache.
|
||||
if (script_source.GetCachedData()) {
|
||||
if (compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
compile_options = ScriptCompiler::kConsumeCodeCache;
|
||||
} else if (compile_options == ScriptCompiler::kProduceParserCache) {
|
||||
compile_options = ScriptCompiler::kConsumeParserCache;
|
||||
} else {
|
||||
ASSERT(false); // A new compile option?
|
||||
}
|
||||
ScriptCompiler::Source cached_source(
|
||||
source, origin, new v8::ScriptCompiler::CachedData(
|
||||
script_source.GetCachedData()->data,
|
||||
script_source.GetCachedData()->length,
|
||||
v8::ScriptCompiler::CachedData::BufferNotOwned));
|
||||
script = ScriptCompiler::CompileUnbound(isolate, &cached_source,
|
||||
compile_options);
|
||||
}
|
||||
return script;
|
||||
}
|
||||
|
||||
|
||||
// Executes a string within the current v8 context.
|
||||
bool Shell::ExecuteString(Isolate* isolate,
|
||||
Handle<String> source,
|
||||
@ -188,10 +218,9 @@ bool Shell::ExecuteString(Isolate* isolate,
|
||||
// When debugging make exceptions appear to be uncaught.
|
||||
try_catch.SetVerbose(true);
|
||||
}
|
||||
ScriptOrigin origin(name);
|
||||
ScriptCompiler::Source script_source(source, origin);
|
||||
|
||||
Handle<UnboundScript> script =
|
||||
ScriptCompiler::CompileUnbound(isolate, &script_source);
|
||||
Shell::CompileString(isolate, source, name, options.compile_options);
|
||||
if (script.IsEmpty()) {
|
||||
// Print errors that happened during compilation.
|
||||
if (report_exceptions && !FLAG_debugger)
|
||||
@ -1340,6 +1369,20 @@ bool Shell::SetOptions(int argc, char* argv[]) {
|
||||
options.snapshot_blob = argv[i] + 16;
|
||||
argv[i] = NULL;
|
||||
#endif // V8_USE_EXTERNAL_STARTUP_DATA
|
||||
} else if (strcmp(argv[i], "--cache") == 0 ||
|
||||
strncmp(argv[i], "--cache=", 8) == 0) {
|
||||
const char* value = argv[i] + 7;
|
||||
if (!*value || strncmp(value, "=code", 6) == 0) {
|
||||
options.compile_options = v8::ScriptCompiler::kProduceCodeCache;
|
||||
} else if (strncmp(value, "=parse", 7) == 0) {
|
||||
options.compile_options = v8::ScriptCompiler::kProduceParserCache;
|
||||
} else if (strncmp(value, "=none", 6) == 0) {
|
||||
options.compile_options = v8::ScriptCompiler::kNoCompileOptions;
|
||||
} else {
|
||||
printf("Unknown option to --cache.\n");
|
||||
return false;
|
||||
}
|
||||
argv[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
39
src/d8.h
39
src/d8.h
@ -194,23 +194,24 @@ class BinaryResource : public v8::String::ExternalAsciiStringResource {
|
||||
|
||||
class ShellOptions {
|
||||
public:
|
||||
ShellOptions() :
|
||||
script_executed(false),
|
||||
last_run(true),
|
||||
send_idle_notification(false),
|
||||
invoke_weak_callbacks(false),
|
||||
stress_opt(false),
|
||||
stress_deopt(false),
|
||||
interactive_shell(false),
|
||||
test_shell(false),
|
||||
dump_heap_constants(false),
|
||||
expected_to_throw(false),
|
||||
mock_arraybuffer_allocator(false),
|
||||
num_isolates(1),
|
||||
isolate_sources(NULL),
|
||||
icu_data_file(NULL),
|
||||
natives_blob(NULL),
|
||||
snapshot_blob(NULL) { }
|
||||
ShellOptions()
|
||||
: script_executed(false),
|
||||
last_run(true),
|
||||
send_idle_notification(false),
|
||||
invoke_weak_callbacks(false),
|
||||
stress_opt(false),
|
||||
stress_deopt(false),
|
||||
interactive_shell(false),
|
||||
test_shell(false),
|
||||
dump_heap_constants(false),
|
||||
expected_to_throw(false),
|
||||
mock_arraybuffer_allocator(false),
|
||||
num_isolates(1),
|
||||
compile_options(v8::ScriptCompiler::kNoCompileOptions),
|
||||
isolate_sources(NULL),
|
||||
icu_data_file(NULL),
|
||||
natives_blob(NULL),
|
||||
snapshot_blob(NULL) {}
|
||||
|
||||
~ShellOptions() {
|
||||
delete[] isolate_sources;
|
||||
@ -232,6 +233,7 @@ class ShellOptions {
|
||||
bool expected_to_throw;
|
||||
bool mock_arraybuffer_allocator;
|
||||
int num_isolates;
|
||||
v8::ScriptCompiler::CompileOptions compile_options;
|
||||
SourceGroup* isolate_sources;
|
||||
const char* icu_data_file;
|
||||
const char* natives_blob;
|
||||
@ -245,6 +247,9 @@ class Shell : public i::AllStatic {
|
||||
#endif // V8_SHARED
|
||||
|
||||
public:
|
||||
static Local<UnboundScript> CompileString(
|
||||
Isolate* isolate, Local<String> source, Local<Value> name,
|
||||
v8::ScriptCompiler::CompileOptions compile_options);
|
||||
static bool ExecuteString(Isolate* isolate,
|
||||
Handle<String> source,
|
||||
Handle<Value> name,
|
||||
|
@ -738,12 +738,9 @@ bool Debug::CompileDebuggerScript(Isolate* isolate, int index) {
|
||||
|
||||
// Compile the script.
|
||||
Handle<SharedFunctionInfo> function_info;
|
||||
function_info = Compiler::CompileScript(source_code,
|
||||
script_name, 0, 0,
|
||||
false,
|
||||
context,
|
||||
NULL, NULL, NO_CACHED_DATA,
|
||||
NATIVES_CODE);
|
||||
function_info = Compiler::CompileScript(
|
||||
source_code, script_name, 0, 0, false, context, NULL, NULL,
|
||||
ScriptCompiler::kNoCompileOptions, NATIVES_CODE);
|
||||
|
||||
// Silently ignore stack overflows during compilation.
|
||||
if (function_info.is_null()) {
|
||||
|
@ -254,11 +254,11 @@ int ParseData::FunctionsSize() {
|
||||
|
||||
|
||||
void Parser::SetCachedData() {
|
||||
if (cached_data_mode() == NO_CACHED_DATA) {
|
||||
if (compile_options() == ScriptCompiler::kNoCompileOptions) {
|
||||
cached_parse_data_ = NULL;
|
||||
} else {
|
||||
ASSERT(info_->cached_data() != NULL);
|
||||
if (cached_data_mode() == CONSUME_CACHED_DATA) {
|
||||
if (compile_options() == ScriptCompiler::kConsumeParserCache) {
|
||||
cached_parse_data_ = new ParseData(*info_->cached_data());
|
||||
}
|
||||
}
|
||||
@ -741,9 +741,10 @@ FunctionLiteral* Parser::ParseProgram() {
|
||||
|
||||
// Initialize parser state.
|
||||
CompleteParserRecorder recorder;
|
||||
if (cached_data_mode() == PRODUCE_CACHED_DATA) {
|
||||
|
||||
if (compile_options() == ScriptCompiler::kProduceParserCache) {
|
||||
log_ = &recorder;
|
||||
} else if (cached_data_mode() == CONSUME_CACHED_DATA) {
|
||||
} else if (compile_options() == ScriptCompiler::kConsumeParserCache) {
|
||||
cached_parse_data_->Initialize();
|
||||
}
|
||||
|
||||
@ -776,7 +777,7 @@ FunctionLiteral* Parser::ParseProgram() {
|
||||
}
|
||||
PrintF(" - took %0.3f ms]\n", ms);
|
||||
}
|
||||
if (cached_data_mode() == PRODUCE_CACHED_DATA) {
|
||||
if (compile_options() == ScriptCompiler::kProduceParserCache) {
|
||||
if (result != NULL) *info_->cached_data() = recorder.GetScriptData();
|
||||
log_ = NULL;
|
||||
}
|
||||
@ -3608,7 +3609,7 @@ void Parser::SkipLazyFunctionBody(const AstRawString* function_name,
|
||||
int* expected_property_count,
|
||||
bool* ok) {
|
||||
int function_block_pos = position();
|
||||
if (cached_data_mode() == CONSUME_CACHED_DATA) {
|
||||
if (compile_options() == ScriptCompiler::kConsumeParserCache) {
|
||||
// If we have cached data, we use it to skip parsing the function body. The
|
||||
// data contains the information we need to construct the lazy function.
|
||||
FunctionEntry entry =
|
||||
@ -3658,7 +3659,7 @@ void Parser::SkipLazyFunctionBody(const AstRawString* function_name,
|
||||
*materialized_literal_count = logger.literals();
|
||||
*expected_property_count = logger.properties();
|
||||
scope_->SetStrictMode(logger.strict_mode());
|
||||
if (cached_data_mode() == PRODUCE_CACHED_DATA) {
|
||||
if (compile_options() == ScriptCompiler::kProduceParserCache) {
|
||||
ASSERT(log_);
|
||||
// Position right after terminal '}'.
|
||||
int body_end = scanner()->location().end_pos;
|
||||
|
@ -642,7 +642,9 @@ class Parser : public ParserBase<ParserTraits> {
|
||||
void SetCachedData();
|
||||
|
||||
bool inside_with() const { return scope_->inside_with(); }
|
||||
CachedDataMode cached_data_mode() const { return info_->cached_data_mode(); }
|
||||
ScriptCompiler::CompileOptions compile_options() const {
|
||||
return info_->compile_options();
|
||||
}
|
||||
Scope* DeclarationScope(VariableMode mode) {
|
||||
return IsLexicalVariableMode(mode)
|
||||
? scope_ : scope_->DeclarationScope();
|
||||
@ -790,7 +792,6 @@ class Parser : public ParserBase<ParserTraits> {
|
||||
Scope* original_scope_; // for ES5 function declarations in sloppy eval
|
||||
Target* target_stack_; // for break, continue statements
|
||||
ParseData* cached_parse_data_;
|
||||
CachedDataMode cached_data_mode_;
|
||||
AstValueFactory* ast_value_factory_;
|
||||
|
||||
CompilationInfo* info_;
|
||||
|
@ -371,14 +371,20 @@ static inline v8::Local<v8::Value> CompileRun(v8::Local<v8::String> source) {
|
||||
}
|
||||
|
||||
|
||||
static inline v8::Local<v8::Value> PreCompileCompileRun(const char* source) {
|
||||
static inline v8::Local<v8::Value> ParserCacheCompileRun(const char* source) {
|
||||
// Compile once just to get the preparse data, then compile the second time
|
||||
// using the data.
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
v8::ScriptCompiler::Source script_source(v8_str(source));
|
||||
v8::ScriptCompiler::Compile(isolate, &script_source,
|
||||
v8::ScriptCompiler::kProduceDataToCache);
|
||||
return v8::ScriptCompiler::Compile(isolate, &script_source)->Run();
|
||||
v8::ScriptCompiler::kProduceParserCache);
|
||||
|
||||
// Check whether we received cached data, and if so use it.
|
||||
v8::ScriptCompiler::CompileOptions options =
|
||||
script_source.GetCachedData() ? v8::ScriptCompiler::kConsumeParserCache
|
||||
: v8::ScriptCompiler::kNoCompileOptions;
|
||||
|
||||
return v8::ScriptCompiler::Compile(isolate, &script_source, options)->Run();
|
||||
}
|
||||
|
||||
|
||||
|
@ -14811,7 +14811,7 @@ TEST(PreCompileSerialization) {
|
||||
const char* script = "function foo(a) { return a+1; }";
|
||||
v8::ScriptCompiler::Source source(v8_str(script));
|
||||
v8::ScriptCompiler::Compile(isolate, &source,
|
||||
v8::ScriptCompiler::kProduceDataToCache);
|
||||
v8::ScriptCompiler::kProduceParserCache);
|
||||
// Serialize.
|
||||
const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
|
||||
i::byte* serialized_data = i::NewArray<i::byte>(cd->length);
|
||||
|
@ -59,15 +59,10 @@ static Handle<JSFunction> Compile(const char* source) {
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
Handle<String> source_code = isolate->factory()->NewStringFromUtf8(
|
||||
CStrVector(source)).ToHandleChecked();
|
||||
Handle<SharedFunctionInfo> shared_function =
|
||||
Compiler::CompileScript(source_code,
|
||||
Handle<String>(),
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
Handle<Context>(isolate->native_context()),
|
||||
NULL, NULL, NO_CACHED_DATA,
|
||||
NOT_NATIVES_CODE);
|
||||
Handle<SharedFunctionInfo> shared_function = Compiler::CompileScript(
|
||||
source_code, Handle<String>(), 0, 0, false,
|
||||
Handle<Context>(isolate->native_context()), NULL, NULL,
|
||||
v8::ScriptCompiler::kNoCompileOptions, NOT_NATIVES_CODE);
|
||||
return isolate->factory()->NewFunctionFromSharedFunctionInfo(
|
||||
shared_function, isolate->native_context());
|
||||
}
|
||||
|
@ -7321,7 +7321,7 @@ TEST(PrecompiledFunction) {
|
||||
"}; \n"
|
||||
"a = b = c = 2; \n"
|
||||
"bar(); \n";
|
||||
v8::Local<v8::Value> result = PreCompileCompileRun(source);
|
||||
v8::Local<v8::Value> result = ParserCacheCompileRun(source);
|
||||
CHECK(result->IsString());
|
||||
v8::String::Utf8Value utf8(result);
|
||||
CHECK_EQ("bar", *utf8);
|
||||
|
@ -219,15 +219,17 @@ TEST(UsingCachedData) {
|
||||
isolate, new ScriptResource(source, source_length)));
|
||||
i::FLAG_min_preparse_length = 0;
|
||||
v8::ScriptCompiler::Compile(isolate, &script_source,
|
||||
v8::ScriptCompiler::kProduceDataToCache);
|
||||
v8::ScriptCompiler::kProduceParserCache);
|
||||
CHECK(script_source.GetCachedData());
|
||||
|
||||
// Compile the script again, using the cached data.
|
||||
bool lazy_flag = i::FLAG_lazy;
|
||||
i::FLAG_lazy = true;
|
||||
v8::ScriptCompiler::Compile(isolate, &script_source);
|
||||
v8::ScriptCompiler::Compile(isolate, &script_source,
|
||||
v8::ScriptCompiler::kConsumeParserCache);
|
||||
i::FLAG_lazy = false;
|
||||
v8::ScriptCompiler::CompileUnbound(isolate, &script_source);
|
||||
v8::ScriptCompiler::CompileUnbound(isolate, &script_source,
|
||||
v8::ScriptCompiler::kConsumeParserCache);
|
||||
i::FLAG_lazy = lazy_flag;
|
||||
}
|
||||
|
||||
@ -255,7 +257,7 @@ TEST(PreparseFunctionDataIsUsed) {
|
||||
|
||||
v8::ScriptCompiler::Source good_source(v8_str(good_code));
|
||||
v8::ScriptCompiler::Compile(isolate, &good_source,
|
||||
v8::ScriptCompiler::kProduceDataToCache);
|
||||
v8::ScriptCompiler::kProduceParserCache);
|
||||
|
||||
const v8::ScriptCompiler::CachedData* cached_data =
|
||||
good_source.GetCachedData();
|
||||
@ -268,7 +270,8 @@ TEST(PreparseFunctionDataIsUsed) {
|
||||
v8_str(bad_code), new v8::ScriptCompiler::CachedData(
|
||||
cached_data->data, cached_data->length));
|
||||
v8::Local<v8::Value> result =
|
||||
v8::ScriptCompiler::Compile(isolate, &bad_source)->Run();
|
||||
v8::ScriptCompiler::Compile(
|
||||
isolate, &bad_source, v8::ScriptCompiler::kConsumeParserCache)->Run();
|
||||
CHECK(result->IsInt32());
|
||||
CHECK_EQ(25, result->Int32Value());
|
||||
}
|
||||
@ -355,7 +358,7 @@ TEST(PreparsingObjectLiterals) {
|
||||
|
||||
{
|
||||
const char* source = "var myo = {if: \"foo\"}; myo.if;";
|
||||
v8::Local<v8::Value> result = PreCompileCompileRun(source);
|
||||
v8::Local<v8::Value> result = ParserCacheCompileRun(source);
|
||||
CHECK(result->IsString());
|
||||
v8::String::Utf8Value utf8(result);
|
||||
CHECK_EQ("foo", *utf8);
|
||||
@ -363,7 +366,7 @@ TEST(PreparsingObjectLiterals) {
|
||||
|
||||
{
|
||||
const char* source = "var myo = {\"bar\": \"foo\"}; myo[\"bar\"];";
|
||||
v8::Local<v8::Value> result = PreCompileCompileRun(source);
|
||||
v8::Local<v8::Value> result = ParserCacheCompileRun(source);
|
||||
CHECK(result->IsString());
|
||||
v8::String::Utf8Value utf8(result);
|
||||
CHECK_EQ("foo", *utf8);
|
||||
@ -371,7 +374,7 @@ TEST(PreparsingObjectLiterals) {
|
||||
|
||||
{
|
||||
const char* source = "var myo = {1: \"foo\"}; myo[1];";
|
||||
v8::Local<v8::Value> result = PreCompileCompileRun(source);
|
||||
v8::Local<v8::Value> result = ParserCacheCompileRun(source);
|
||||
CHECK(result->IsString());
|
||||
v8::String::Utf8Value utf8(result);
|
||||
CHECK_EQ("foo", *utf8);
|
||||
@ -2251,7 +2254,7 @@ TEST(DontRegressPreParserDataSizes) {
|
||||
i::Handle<i::Script> script = factory->NewScript(source);
|
||||
i::CompilationInfoWithZone info(script);
|
||||
i::ScriptData* sd = NULL;
|
||||
info.SetCachedData(&sd, i::PRODUCE_CACHED_DATA);
|
||||
info.SetCachedData(&sd, v8::ScriptCompiler::kProduceParserCache);
|
||||
i::Parser::Parse(&info, true);
|
||||
i::ParseData pd(sd);
|
||||
|
||||
|
@ -697,21 +697,22 @@ TEST(SerializeToplevelOnePlusOne) {
|
||||
|
||||
ScriptData* cache = NULL;
|
||||
|
||||
Handle<SharedFunctionInfo> orig =
|
||||
Compiler::CompileScript(orig_source, Handle<String>(), 0, 0, false,
|
||||
Handle<Context>(isolate->native_context()), NULL,
|
||||
&cache, PRODUCE_CACHED_DATA, NOT_NATIVES_CODE);
|
||||
Handle<SharedFunctionInfo> orig = Compiler::CompileScript(
|
||||
orig_source, Handle<String>(), 0, 0, false,
|
||||
Handle<Context>(isolate->native_context()), NULL, &cache,
|
||||
v8::ScriptCompiler::kProduceCodeCache, NOT_NATIVES_CODE);
|
||||
|
||||
int builtins_count = CountBuiltins();
|
||||
|
||||
Handle<SharedFunctionInfo> copy;
|
||||
{
|
||||
DisallowCompilation no_compile_expected(isolate);
|
||||
copy = Compiler::CompileScript(copy_source, Handle<String>(), 0, 0, false,
|
||||
Handle<Context>(isolate->native_context()),
|
||||
NULL, &cache, CONSUME_CACHED_DATA,
|
||||
NOT_NATIVES_CODE);
|
||||
copy = Compiler::CompileScript(
|
||||
copy_source, Handle<String>(), 0, 0, false,
|
||||
Handle<Context>(isolate->native_context()), NULL, &cache,
|
||||
v8::ScriptCompiler::kConsumeCodeCache, NOT_NATIVES_CODE);
|
||||
}
|
||||
|
||||
CHECK_NE(*orig, *copy);
|
||||
CHECK(Script::cast(copy->script())->source() == *copy_source);
|
||||
|
||||
@ -751,10 +752,10 @@ TEST(SerializeToplevelInternalizedString) {
|
||||
Handle<JSObject> global(isolate->context()->global_object());
|
||||
ScriptData* cache = NULL;
|
||||
|
||||
Handle<SharedFunctionInfo> orig =
|
||||
Compiler::CompileScript(orig_source, Handle<String>(), 0, 0, false,
|
||||
Handle<Context>(isolate->native_context()), NULL,
|
||||
&cache, PRODUCE_CACHED_DATA, NOT_NATIVES_CODE);
|
||||
Handle<SharedFunctionInfo> orig = Compiler::CompileScript(
|
||||
orig_source, Handle<String>(), 0, 0, false,
|
||||
Handle<Context>(isolate->native_context()), NULL, &cache,
|
||||
v8::ScriptCompiler::kProduceCodeCache, NOT_NATIVES_CODE);
|
||||
Handle<JSFunction> orig_fun =
|
||||
isolate->factory()->NewFunctionFromSharedFunctionInfo(
|
||||
orig, isolate->native_context());
|
||||
@ -767,10 +768,10 @@ TEST(SerializeToplevelInternalizedString) {
|
||||
Handle<SharedFunctionInfo> copy;
|
||||
{
|
||||
DisallowCompilation no_compile_expected(isolate);
|
||||
copy = Compiler::CompileScript(copy_source, Handle<String>(), 0, 0, false,
|
||||
Handle<Context>(isolate->native_context()),
|
||||
NULL, &cache, CONSUME_CACHED_DATA,
|
||||
NOT_NATIVES_CODE);
|
||||
copy = Compiler::CompileScript(
|
||||
copy_source, Handle<String>(), 0, 0, false,
|
||||
Handle<Context>(isolate->native_context()), NULL, &cache,
|
||||
v8::ScriptCompiler::kConsumeCodeCache, NOT_NATIVES_CODE);
|
||||
}
|
||||
CHECK_NE(*orig, *copy);
|
||||
CHECK(Script::cast(copy->script())->source() == *copy_source);
|
||||
|
@ -90,7 +90,8 @@ std::pair<v8::base::TimeDelta, v8::base::TimeDelta> RunBaselineParser(
|
||||
{
|
||||
CompilationInfoWithZone info(script);
|
||||
info.MarkAsGlobal();
|
||||
info.SetCachedData(&cached_data_impl, i::PRODUCE_CACHED_DATA);
|
||||
info.SetCachedData(&cached_data_impl,
|
||||
v8::ScriptCompiler::kProduceParserCache);
|
||||
v8::base::ElapsedTimer timer;
|
||||
timer.Start();
|
||||
// Allow lazy parsing; otherwise we won't produce cached data.
|
||||
@ -105,7 +106,8 @@ std::pair<v8::base::TimeDelta, v8::base::TimeDelta> RunBaselineParser(
|
||||
{
|
||||
CompilationInfoWithZone info(script);
|
||||
info.MarkAsGlobal();
|
||||
info.SetCachedData(&cached_data_impl, i::CONSUME_CACHED_DATA);
|
||||
info.SetCachedData(&cached_data_impl,
|
||||
v8::ScriptCompiler::kConsumeParserCache);
|
||||
v8::base::ElapsedTimer timer;
|
||||
timer.Start();
|
||||
// Allow lazy parsing; otherwise cached data won't help.
|
||||
|
Loading…
Reference in New Issue
Block a user