[snapshot] extend code caching support to CompileFunctionInContext.

R=leszeks@chromium.org, mythria@chromium.org

Bug: v8:7554
Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
Change-Id: I3eb29d67dfa64887fb52ac706d069e15dd2d0e85
Reviewed-on: https://chromium-review.googlesource.com/980944
Reviewed-by: Mythri Alle <mythria@chromium.org>
Commit-Queue: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52299}
This commit is contained in:
Yang Guo 2018-03-27 12:44:13 +02:00 committed by Commit Bot
parent 9a29c90277
commit e71055211c
7 changed files with 246 additions and 160 deletions

View File

@ -1569,7 +1569,9 @@ class V8_EXPORT ScriptCompiler {
static V8_WARN_UNUSED_RESULT MaybeLocal<Function> CompileFunctionInContext(
Local<Context> context, Source* source, size_t arguments_count,
Local<String> arguments[], size_t context_extension_count,
Local<Object> context_extensions[]);
Local<Object> context_extensions[],
CompileOptions options = kNoCompileOptions,
NoCacheReason no_cache_reason = kNoCacheNoReason);
/**
* Creates and returns code cache for the specified unbound_script.
@ -1579,6 +1581,15 @@ class V8_EXPORT ScriptCompiler {
static CachedData* CreateCodeCache(Local<UnboundScript> unbound_script,
Local<String> source);
/**
* Creates and returns code cache for the specified function that was
* previously produced by CompileFunctionInContext.
* This will return nullptr if the script cannot be serialized. The
* CachedData returned by this function should be owned by the caller.
*/
static CachedData* CreateCodeCacheForFunction(Local<Function> function,
Local<String> source);
private:
static V8_WARN_UNUSED_RESULT MaybeLocal<UnboundScript> CompileUnboundInternal(
Isolate* isolate, Source* source, CompileOptions options,

View File

@ -2398,22 +2398,14 @@ MaybeLocal<UnboundScript> ScriptCompiler::CompileUnboundInternal(
source->host_defined_options);
i::MaybeHandle<i::SharedFunctionInfo> maybe_function_info =
i::Compiler::GetSharedFunctionInfoForScript(
str, script_details, source->resource_options, nullptr, &script_data,
str, script_details, source->resource_options, nullptr, script_data,
options, no_cache_reason, i::NOT_NATIVES_CODE);
has_pending_exception = !maybe_function_info.ToHandle(&result);
if (has_pending_exception && script_data != nullptr) {
// 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.
delete script_data;
script_data = nullptr;
}
RETURN_ON_FAILED_EXECUTION(UnboundScript);
if (options == kConsumeCodeCache) {
source->cached_data->rejected = script_data->rejected();
}
delete script_data;
has_pending_exception = !maybe_function_info.ToHandle(&result);
RETURN_ON_FAILED_EXECUTION(UnboundScript);
RETURN_ESCAPED(ToApiHandle<UnboundScript>(result));
}
@ -2498,15 +2490,19 @@ class IsIdentifierHelper {
DISALLOW_COPY_AND_ASSIGN(IsIdentifierHelper);
};
MaybeLocal<Function> ScriptCompiler::CompileFunctionInContext(
Local<Context> v8_context, Source* source, size_t arguments_count,
Local<String> arguments[], size_t context_extension_count,
Local<Object> context_extensions[]) {
Local<Object> context_extensions[], CompileOptions options,
NoCacheReason no_cache_reason) {
PREPARE_FOR_EXECUTION(v8_context, ScriptCompiler, CompileFunctionInContext,
Function);
TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.ScriptCompiler");
DCHECK(options == CompileOptions::kConsumeCodeCache ||
options == CompileOptions::kEagerCompile ||
options == CompileOptions::kNoCompileOptions);
i::Handle<i::Context> context = Utils::OpenHandle(*v8_context);
i::Handle<i::SharedFunctionInfo> outer_info(context->closure()->shared(),
isolate);
@ -2535,25 +2531,30 @@ MaybeLocal<Function> ScriptCompiler::CompileFunctionInContext(
extension);
}
i::Handle<i::Object> name_obj;
int line_offset = 0;
int column_offset = 0;
if (!source->resource_name.IsEmpty()) {
name_obj = Utils::OpenHandle(*(source->resource_name));
}
if (!source->resource_line_offset.IsEmpty()) {
line_offset = static_cast<int>(source->resource_line_offset->Value());
}
if (!source->resource_column_offset.IsEmpty()) {
column_offset = static_cast<int>(source->resource_column_offset->Value());
i::Compiler::ScriptDetails script_details = GetScriptDetails(
isolate, source->resource_name, source->resource_line_offset,
source->resource_column_offset, source->source_map_url,
source->host_defined_options);
i::ScriptData* script_data = nullptr;
if (options == kConsumeCodeCache) {
DCHECK(source->cached_data);
// ScriptData takes care of pointer-aligning the data.
script_data = new i::ScriptData(source->cached_data->data,
source->cached_data->length);
}
i::Handle<i::JSFunction> result;
has_pending_exception =
!i::Compiler::GetWrappedFunction(
Utils::OpenHandle(*source->source_string), arguments_list, context,
line_offset, column_offset, name_obj, source->resource_options)
script_details, source->resource_options, script_data, options,
no_cache_reason)
.ToHandle(&result);
if (options == kConsumeCodeCache) {
source->cached_data->rejected = script_data->rejected();
}
delete script_data;
RETURN_ON_FAILED_EXECUTION(Function);
RETURN_ESCAPED(Utils::CallableToLocal(result));
}
@ -2627,37 +2628,18 @@ ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCache(
i::Handle<i::SharedFunctionInfo> shared =
i::Handle<i::SharedFunctionInfo>::cast(
Utils::OpenHandle(*unbound_script));
i::Isolate* isolate = shared->GetIsolate();
TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.Execute");
base::ElapsedTimer timer;
if (i::FLAG_profile_deserialization) {
timer.Start();
}
i::HistogramTimerScope histogram_timer(
isolate->counters()->compile_serialize());
i::RuntimeCallTimerScope runtimeTimer(
isolate, i::RuntimeCallCounterId::kCompileSerialize);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileSerialize");
i::Handle<i::String> source_str = Utils::OpenHandle(*source);
DCHECK(shared->is_toplevel());
i::Handle<i::Script> script(i::Script::cast(shared->script()));
// TODO(7110): Enable serialization of Asm modules once the AsmWasmData is
// context independent.
if (script->ContainsAsmModule()) return nullptr;
if (isolate->debug()->is_loaded()) return nullptr;
return i::CodeSerializer::Serialize(shared, source_str);
}
i::ScriptData* script_data =
i::CodeSerializer::Serialize(isolate, shared, Utils::OpenHandle(*source));
CachedData* result = new CachedData(
script_data->data(), script_data->length(), CachedData::BufferOwned);
script_data->ReleaseDataOwnership();
delete script_data;
if (i::FLAG_profile_deserialization) {
i::PrintF("[Serializing took %0.3f ms]\n",
timer.Elapsed().InMillisecondsF());
}
return result;
ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCacheForFunction(
Local<Function> function, Local<String> source) {
i::Handle<i::SharedFunctionInfo> shared(
i::Handle<i::JSFunction>::cast(Utils::OpenHandle(*function))->shared());
i::Handle<i::String> source_str = Utils::OpenHandle(*source);
CHECK(shared->is_wrapped());
return i::CodeSerializer::Serialize(shared, source_str);
}
MaybeLocal<Script> Script::Compile(Local<Context> context, Local<String> source,
@ -9603,15 +9585,15 @@ MaybeLocal<UnboundScript> debug::CompileInspectorScript(Isolate* v8_isolate,
Local<String> source) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(isolate, UnboundScript);
i::ScriptData* script_data = nullptr;
i::Handle<i::String> str = Utils::OpenHandle(*source);
i::Handle<i::SharedFunctionInfo> result;
{
ScriptOriginOptions origin_options;
i::ScriptData* script_data = nullptr;
i::MaybeHandle<i::SharedFunctionInfo> maybe_function_info =
i::Compiler::GetSharedFunctionInfoForScript(
str, i::Compiler::ScriptDetails(), origin_options, nullptr,
&script_data, ScriptCompiler::kNoCompileOptions,
script_data, ScriptCompiler::kNoCompileOptions,
ScriptCompiler::kNoCacheBecauseInspector,
i::FLAG_expose_inspector_scripts ? i::NOT_NATIVES_CODE
: i::INSPECTOR_CODE);

View File

@ -1001,6 +1001,7 @@ bool Compiler::Compile(Handle<SharedFunctionInfo> shared_info,
DCHECK(!shared_info->is_compiled());
Isolate* isolate = shared_info->GetIsolate();
DCHECK(AllowCompilation::IsAllowed(isolate));
DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
DCHECK(!isolate->has_pending_exception());
DCHECK(!shared_info->HasBytecodeArray());
@ -1072,7 +1073,6 @@ bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
Isolate* isolate = function->GetIsolate();
Handle<SharedFunctionInfo> shared_info = handle(function->shared());
DCHECK(AllowCompilation::IsAllowed(isolate));
// Ensure shared function info is compiled.
if (!shared_info->is_compiled() && !Compile(shared_info, flag)) return false;
@ -1301,56 +1301,6 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
return result;
}
MaybeHandle<JSFunction> Compiler::GetWrappedFunction(
Handle<String> source, Handle<FixedArray> arguments,
Handle<Context> context, int line_offset, int column_offset,
Handle<Object> script_name, ScriptOriginOptions options) {
Isolate* isolate = source->GetIsolate();
int source_length = source->length();
isolate->counters()->total_compile_size()->Increment(source_length);
Handle<Script> script = isolate->factory()->NewScript(source);
if (isolate->NeedsSourcePositionsForProfiling()) {
Script::InitLineEnds(script);
}
if (!script_name.is_null()) {
script->set_name(*script_name);
script->set_line_offset(line_offset);
script->set_column_offset(column_offset);
}
script->set_wrapped_arguments(*arguments);
script->set_origin_options(options);
ParseInfo parse_info(script);
parse_info.set_eval(); // Use an eval scope as declaration scope.
parse_info.set_wrapped_as_function();
if (!context->IsNativeContext()) {
parse_info.set_outer_scope_info(handle(context->scope_info()));
}
Handle<SharedFunctionInfo> top_level;
ASSIGN_RETURN_ON_EXCEPTION(isolate, top_level,
CompileToplevel(&parse_info, isolate), JSFunction);
Handle<SharedFunctionInfo> wrapped;
SharedFunctionInfo::ScriptIterator infos(script);
while (SharedFunctionInfo* info = infos.Next()) {
if (info->is_wrapped()) {
wrapped = Handle<SharedFunctionInfo>(info);
break;
}
}
DCHECK(!wrapped.is_null());
Handle<JSFunction> function =
isolate->factory()->NewFunctionFromSharedFunctionInfo(wrapped, context,
NOT_TENURED);
// OnAfterCompile has to be called after we create the JSFunction, which we
// may require to recompile the eval for debugging, if we find a function
// that contains break points in the eval script.
isolate->debug()->OnAfterCompile(script);
return function;
}
bool Compiler::CodeGenerationFromStringsAllowed(Isolate* isolate,
Handle<Context> context,
@ -1631,17 +1581,17 @@ Handle<Script> NewScript(Isolate* isolate, Handle<String> source,
MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
Handle<String> source, const Compiler::ScriptDetails& script_details,
ScriptOriginOptions origin_options, v8::Extension* extension,
ScriptData** cached_data, ScriptCompiler::CompileOptions compile_options,
ScriptData* cached_data, ScriptCompiler::CompileOptions compile_options,
ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag natives) {
Isolate* isolate = source->GetIsolate();
ScriptCompileTimerScope compile_timer(isolate, no_cache_reason);
if (compile_options == ScriptCompiler::kNoCompileOptions ||
compile_options == ScriptCompiler::kEagerCompile) {
cached_data = nullptr;
DCHECK_NULL(cached_data);
} else {
DCHECK(compile_options == ScriptCompiler::kConsumeCodeCache);
DCHECK(cached_data && *cached_data);
DCHECK(cached_data);
DCHECK_NULL(extension);
}
int source_length = source->length();
@ -1677,16 +1627,13 @@ MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompileDeserialize");
Handle<SharedFunctionInfo> inner_result;
if (CodeSerializer::Deserialize(isolate, *cached_data, source)
if (CodeSerializer::Deserialize(isolate, cached_data, source)
.ToHandle(&inner_result)) {
// Promote to per-isolate compilation cache.
DCHECK(inner_result->is_compiled());
compilation_cache->PutScript(source, isolate->native_context(),
language_mode, inner_result);
Handle<Script> script(Script::cast(inner_result->script()), isolate);
if (isolate->NeedsSourcePositionsForProfiling()) {
Script::InitLineEnds(script);
}
maybe_result = inner_result;
} else {
// Deserializer failed. Fall through to compile.
@ -1730,6 +1677,91 @@ MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
return maybe_result;
}
MaybeHandle<JSFunction> Compiler::GetWrappedFunction(
Handle<String> source, Handle<FixedArray> arguments,
Handle<Context> context, const Compiler::ScriptDetails& script_details,
ScriptOriginOptions origin_options, ScriptData* cached_data,
v8::ScriptCompiler::CompileOptions compile_options,
v8::ScriptCompiler::NoCacheReason no_cache_reason) {
Isolate* isolate = source->GetIsolate();
ScriptCompileTimerScope compile_timer(isolate, no_cache_reason);
if (compile_options == ScriptCompiler::kNoCompileOptions ||
compile_options == ScriptCompiler::kEagerCompile) {
DCHECK_NULL(cached_data);
} else {
DCHECK(compile_options == ScriptCompiler::kConsumeCodeCache);
DCHECK(cached_data);
}
int source_length = source->length();
isolate->counters()->total_compile_size()->Increment(source_length);
LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
MaybeHandle<SharedFunctionInfo> maybe_result;
bool can_consume_code_cache =
compile_options == ScriptCompiler::kConsumeCodeCache &&
!isolate->debug()->is_loaded();
if (can_consume_code_cache) {
compile_timer.set_consuming_code_cache();
// Then check cached code provided by embedder.
HistogramTimerScope timer(isolate->counters()->compile_deserialize());
RuntimeCallTimerScope runtimeTimer(
isolate, RuntimeCallCounterId::kCompileDeserialize);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompileDeserialize");
maybe_result = CodeSerializer::Deserialize(isolate, cached_data, source);
if (maybe_result.is_null()) {
// Deserializer failed. Fall through to compile.
compile_timer.set_consuming_code_cache_failed();
}
}
Handle<SharedFunctionInfo> wrapped;
Handle<Script> script;
if (!maybe_result.ToHandle(&wrapped)) {
script = NewScript(isolate, source, script_details, origin_options,
NOT_NATIVES_CODE);
script->set_wrapped_arguments(*arguments);
ParseInfo parse_info(script);
parse_info.set_eval(); // Use an eval scope as declaration scope.
parse_info.set_wrapped_as_function();
// parse_info.set_eager(compile_options == ScriptCompiler::kEagerCompile);
if (!context->IsNativeContext()) {
parse_info.set_outer_scope_info(handle(context->scope_info()));
}
parse_info.set_language_mode(
stricter_language_mode(parse_info.language_mode(), language_mode));
Handle<SharedFunctionInfo> top_level;
maybe_result = CompileToplevel(&parse_info, isolate);
if (maybe_result.is_null()) isolate->ReportPendingMessages();
ASSIGN_RETURN_ON_EXCEPTION(isolate, top_level, maybe_result, JSFunction);
SharedFunctionInfo::ScriptIterator infos(script);
while (SharedFunctionInfo* info = infos.Next()) {
if (info->is_wrapped()) {
wrapped = Handle<SharedFunctionInfo>(info, isolate);
break;
}
}
DCHECK(!wrapped.is_null());
} else {
script = Handle<Script>(Script::cast(wrapped->script()), isolate);
}
Handle<JSFunction> function =
isolate->factory()->NewFunctionFromSharedFunctionInfo(wrapped, context,
NOT_TENURED);
// OnAfterCompile has to be called after we create the JSFunction, which we
// may require to recompile the eval for debugging, if we find a function
// that contains break points in the eval script.
isolate->debug()->OnAfterCompile(script);
return function;
}
ScriptCompiler::ScriptStreamingTask* Compiler::NewBackgroundCompileTask(
ScriptStreamingData* source, Isolate* isolate) {
return new BackgroundCompileTask(source, isolate);

View File

@ -96,25 +96,6 @@ class V8_EXPORT_PRIVATE Compiler : public AllStatic {
int column_offset = 0, Handle<Object> script_name = Handle<Object>(),
ScriptOriginOptions options = ScriptOriginOptions());
// Create a function that results from wrapping |source| in a function,
// with |arguments| being a list of parameters for that function.
MUST_USE_RESULT static MaybeHandle<JSFunction> GetWrappedFunction(
Handle<String> source, Handle<FixedArray> arguments,
Handle<Context> context, int line_offset = 0, int column_offset = 0,
Handle<Object> script_name = Handle<Object>(),
ScriptOriginOptions options = ScriptOriginOptions());
// Returns true if the embedder permits compiling the given source string in
// the given context.
static bool CodeGenerationFromStringsAllowed(Isolate* isolate,
Handle<Context> context,
Handle<String> source);
// Create a (bound) function for a String source within a context for eval.
MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromString(
Handle<Context> context, Handle<String> source,
ParseRestriction restriction, int parameters_end_pos);
struct ScriptDetails {
ScriptDetails() : line_offset(0), column_offset(0) {}
explicit ScriptDetails(Handle<Object> script_name)
@ -127,11 +108,32 @@ class V8_EXPORT_PRIVATE Compiler : public AllStatic {
i::MaybeHandle<i::FixedArray> host_defined_options;
};
// Create a function that results from wrapping |source| in a function,
// with |arguments| being a list of parameters for that function.
MUST_USE_RESULT static MaybeHandle<JSFunction> GetWrappedFunction(
Handle<String> source, Handle<FixedArray> arguments,
Handle<Context> context, const ScriptDetails& script_details,
ScriptOriginOptions origin_options, ScriptData* cached_data,
v8::ScriptCompiler::CompileOptions compile_options,
v8::ScriptCompiler::NoCacheReason no_cache_reason);
// Returns true if the embedder permits compiling the given source string in
// the given context.
static bool CodeGenerationFromStringsAllowed(Isolate* isolate,
Handle<Context> context,
Handle<String> source);
// Create a (bound) function for a String source within a context for eval.
MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromString(
Handle<Context> context, Handle<String> source,
ParseRestriction restriction, int parameters_end_pos);
// Create a shared function info object for a String source.
static MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScript(
Handle<String> source, const ScriptDetails& script_details,
ScriptOriginOptions origin_options, v8::Extension* extension,
ScriptData** cached_data, ScriptCompiler::CompileOptions compile_options,
ScriptData* cached_data, ScriptCompiler::CompileOptions compile_options,
ScriptCompiler::NoCacheReason no_cache_reason,
NativesFlag is_natives_code);

View File

@ -30,31 +30,49 @@ ScriptData::ScriptData(const byte* data, int length)
}
}
ScriptData* CodeSerializer::Serialize(Isolate* isolate,
Handle<SharedFunctionInfo> info,
Handle<String> source) {
// static
ScriptCompiler::CachedData* CodeSerializer::Serialize(
Handle<SharedFunctionInfo> info, Handle<String> source) {
Isolate* isolate = info->GetIsolate();
TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.Execute");
HistogramTimerScope histogram_timer(isolate->counters()->compile_serialize());
RuntimeCallTimerScope runtimeTimer(isolate,
RuntimeCallCounterId::kCompileSerialize);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileSerialize");
base::ElapsedTimer timer;
if (FLAG_profile_deserialization) timer.Start();
Handle<Script> script(Script::cast(info->script()), isolate);
if (FLAG_trace_serializer) {
PrintF("[Serializing from");
Object* script = info->script();
if (script->IsScript()) Script::cast(script)->name()->ShortPrint();
Script::cast(script)->name()->ShortPrint();
PrintF("]\n");
}
// TODO(7110): Enable serialization of Asm modules once the AsmWasmData is
// context independent.
if (script->ContainsAsmModule()) return nullptr;
if (isolate->debug()->is_loaded()) return nullptr;
// Serialize code object.
CodeSerializer cs(isolate, SerializedCodeData::SourceHash(source));
DisallowHeapAllocation no_gc;
cs.reference_map()->AddAttachedReference(*source);
ScriptData* ret = cs.Serialize(info);
ScriptData* script_data = cs.Serialize(info);
if (FLAG_profile_deserialization) {
double ms = timer.Elapsed().InMillisecondsF();
int length = ret->length();
int length = script_data->length();
PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms);
}
return ret;
ScriptCompiler::CachedData* result =
new ScriptCompiler::CachedData(script_data->data(), script_data->length(),
ScriptCompiler::CachedData::BufferOwned);
script_data->ReleaseDataOwnership();
delete script_data;
return result;
}
ScriptData* CodeSerializer::Serialize(Handle<HeapObject> obj) {
@ -247,6 +265,11 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
PROFILE(isolate, CodeCreateEvent(CodeEventListener::SCRIPT_TAG,
result->abstract_code(), *result, name));
}
if (isolate->NeedsSourcePositionsForProfiling()) {
Handle<Script> script(Script::cast(result->script()), isolate);
Script::InitLineEnds(script);
}
return scope.CloseAndEscape(result);
}

View File

@ -45,9 +45,8 @@ class ScriptData {
class CodeSerializer : public Serializer<> {
public:
static ScriptData* Serialize(Isolate* isolate,
Handle<SharedFunctionInfo> info,
Handle<String> source);
static ScriptCompiler::CachedData* Serialize(Handle<SharedFunctionInfo> info,
Handle<String> source);
ScriptData* Serialize(Handle<HeapObject> obj);

View File

@ -1220,10 +1220,9 @@ int CountBuiltins() {
return counter;
}
static Handle<SharedFunctionInfo> CompileScript(
Isolate* isolate, Handle<String> source, Handle<String> name,
ScriptData** cached_data, v8::ScriptCompiler::CompileOptions options) {
ScriptData* cached_data, v8::ScriptCompiler::CompileOptions options) {
return Compiler::GetSharedFunctionInfoForScript(
source, Compiler::ScriptDetails(name), v8::ScriptOriginOptions(),
nullptr, cached_data, options, ScriptCompiler::kNoCacheNoReason,
@ -1279,7 +1278,7 @@ TEST(CodeSerializerOnePlusOne) {
Handle<SharedFunctionInfo> copy;
{
DisallowCompilation no_compile_expected(isolate);
copy = CompileScript(isolate, copy_source, Handle<String>(), &cache,
copy = CompileScript(isolate, copy_source, Handle<String>(), cache,
v8::ScriptCompiler::kConsumeCodeCache);
}
@ -1317,7 +1316,7 @@ TEST(CodeSerializerPromotedToCompilationCache) {
DisallowCompilation no_compile_expected(isolate);
Handle<SharedFunctionInfo> copy = CompileScript(
isolate, src, src, &cache, v8::ScriptCompiler::kConsumeCodeCache);
isolate, src, src, cache, v8::ScriptCompiler::kConsumeCodeCache);
MaybeHandle<SharedFunctionInfo> shared =
isolate->compilation_cache()->LookupScript(
@ -1365,7 +1364,7 @@ TEST(CodeSerializerInternalizedString) {
Handle<SharedFunctionInfo> copy;
{
DisallowCompilation no_compile_expected(isolate);
copy = CompileScript(isolate, copy_source, Handle<String>(), &script_data,
copy = CompileScript(isolate, copy_source, Handle<String>(), script_data,
v8::ScriptCompiler::kConsumeCodeCache);
}
CHECK_NE(*orig, *copy);
@ -1418,7 +1417,7 @@ TEST(CodeSerializerLargeCodeObject) {
Handle<SharedFunctionInfo> copy;
{
DisallowCompilation no_compile_expected(isolate);
copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
copy = CompileScript(isolate, source_str, Handle<String>(), cache,
v8::ScriptCompiler::kConsumeCodeCache);
}
CHECK_NE(*orig, *copy);
@ -1492,7 +1491,7 @@ TEST(CodeSerializerLargeCodeObjectWithIncrementalMarking) {
Handle<SharedFunctionInfo> copy;
{
DisallowCompilation no_compile_expected(isolate);
copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
copy = CompileScript(isolate, source_str, Handle<String>(), cache,
v8::ScriptCompiler::kConsumeCodeCache);
}
CHECK_NE(*orig, *copy);
@ -1545,7 +1544,7 @@ TEST(CodeSerializerLargeStrings) {
Handle<SharedFunctionInfo> copy;
{
DisallowCompilation no_compile_expected(isolate);
copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
copy = CompileScript(isolate, source_str, Handle<String>(), cache,
v8::ScriptCompiler::kConsumeCodeCache);
}
CHECK_NE(*orig, *copy);
@ -1613,7 +1612,7 @@ TEST(CodeSerializerThreeBigStrings) {
Handle<SharedFunctionInfo> copy;
{
DisallowCompilation no_compile_expected(isolate);
copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
copy = CompileScript(isolate, source_str, Handle<String>(), cache,
v8::ScriptCompiler::kConsumeCodeCache);
}
CHECK_NE(*orig, *copy);
@ -1731,7 +1730,7 @@ TEST(CodeSerializerExternalString) {
Handle<SharedFunctionInfo> copy;
{
DisallowCompilation no_compile_expected(isolate);
copy = CompileScript(isolate, source_string, Handle<String>(), &cache,
copy = CompileScript(isolate, source_string, Handle<String>(), cache,
v8::ScriptCompiler::kConsumeCodeCache);
}
CHECK_NE(*orig, *copy);
@ -1788,7 +1787,7 @@ TEST(CodeSerializerLargeExternalString) {
Handle<SharedFunctionInfo> copy;
{
DisallowCompilation no_compile_expected(isolate);
copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
copy = CompileScript(isolate, source_str, Handle<String>(), cache,
v8::ScriptCompiler::kConsumeCodeCache);
}
CHECK_NE(*orig, *copy);
@ -1837,7 +1836,7 @@ TEST(CodeSerializerExternalScriptName) {
Handle<SharedFunctionInfo> copy;
{
DisallowCompilation no_compile_expected(isolate);
copy = CompileScript(isolate, source_string, name, &cache,
copy = CompileScript(isolate, source_string, name, cache,
v8::ScriptCompiler::kConsumeCodeCache);
}
CHECK_NE(*orig, *copy);
@ -2218,8 +2217,9 @@ TEST(Regress503552) {
heap::SimulateIncrementalMarking(isolate->heap());
script_data = CodeSerializer::Serialize(isolate, shared, source);
delete script_data;
v8::ScriptCompiler::CachedData* cache_data =
CodeSerializer::Serialize(shared, source);
delete cache_data;
}
TEST(SnapshotCreatorMultipleContexts) {
@ -3420,7 +3420,7 @@ TEST(WeakArraySerializationInCodeCache) {
DisallowCompilation no_compile_expected(isolate);
Handle<SharedFunctionInfo> copy = CompileScript(
isolate, src, src, &cache, v8::ScriptCompiler::kConsumeCodeCache);
isolate, src, src, cache, v8::ScriptCompiler::kConsumeCodeCache);
// Verify that the pointers in shared_function_infos are weak.
WeakFixedArray* sfis = Script::cast(copy->script())->shared_function_infos();
@ -3429,5 +3429,42 @@ TEST(WeakArraySerializationInCodeCache) {
delete cache;
}
TEST(CachedCompileFunctionInContext) {
DisableAlwaysOpt();
LocalContext env;
Isolate* isolate = CcTest::i_isolate();
isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
v8::HandleScope scope(CcTest::isolate());
v8::Local<v8::String> source = v8_str("return x*x;");
v8::Local<v8::String> arg_str = v8_str("x");
ScriptCompiler::CachedData* cache;
{
v8::ScriptCompiler::Source script_source(source);
v8::Local<v8::Function> fun =
v8::ScriptCompiler::CompileFunctionInContext(
env.local(), &script_source, 1, &arg_str, 0, nullptr,
v8::ScriptCompiler::kEagerCompile)
.ToLocalChecked();
cache = v8::ScriptCompiler::CreateCodeCacheForFunction(fun, source);
}
{
DisallowCompilation no_compile_expected(isolate);
v8::ScriptCompiler::Source script_source(source, cache);
v8::Local<v8::Function> fun =
v8::ScriptCompiler::CompileFunctionInContext(
env.local(), &script_source, 1, &arg_str, 0, nullptr,
v8::ScriptCompiler::kConsumeCodeCache)
.ToLocalChecked();
v8::Local<v8::Value> arg = v8_num(3);
v8::Local<v8::Value> result =
fun->Call(env.local(), v8::Undefined(CcTest::isolate()), 1, &arg)
.ToLocalChecked();
CHECK_EQ(9, result->Int32Value(env.local()).FromJust());
}
}
} // namespace internal
} // namespace v8