Revert "Add support to produce code cache after execute."
This reverts commit 5d4a090377
.
Reason for revert: Speculative revert due to timeouts on testing with
--isolates:
https://build.chromium.org/p/client.v8/builders/V8%20Linux/builds/21889
https://build.chromium.org/p/client.v8/builders/V8%20Linux%20-%20debug/builds/18138
Original change's description:
> Add support to produce code cache after execute.
>
> Adds new API function to request code cache. Earlier code cache was
> produced along with compile requests. This new API allows us to request
> code cache after executing. Also adds support in the code serializer to
> serialize after executing the script.
>
> Bug: chromium:783124
> Cq-Include-Trybots: master.tryserver.chromium.linux:linux_chromium_rel_ng
> Change-Id: Id7b972a2b4c8dcf7a6d9f5ea210890ae968320bd
> Reviewed-on: https://chromium-review.googlesource.com/781767
> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Yang Guo <yangguo@chromium.org>
> Commit-Queue: Mythri Alle <mythria@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#49717}
TBR=ulan@chromium.org,rmcilroy@chromium.org,yangguo@chromium.org,mythria@chromium.org
Change-Id: Id9e0285e73bbc3ea3908b4b7bbf6599e4f7cd76e
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: chromium:783124
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_chromium_rel_ng
Reviewed-on: https://chromium-review.googlesource.com/796870
Reviewed-by: Michael Achenbach <machenbach@chromium.org>
Commit-Queue: Michael Achenbach <machenbach@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49722}
This commit is contained in:
parent
27fd921a28
commit
5ff7af939e
@ -1576,14 +1576,6 @@ class V8_EXPORT ScriptCompiler {
|
||||
Local<String> arguments[], size_t context_extension_count,
|
||||
Local<Object> context_extensions[]);
|
||||
|
||||
/**
|
||||
* Creates and returns code cache for the specified unbound_script.
|
||||
* This will return nullptr if the script cannot be serialized. The
|
||||
* CachedData returned by this function should be owned by the caller.
|
||||
*/
|
||||
static CachedData* CreateCodeCache(Local<UnboundScript> unbound_script,
|
||||
Local<String> source);
|
||||
|
||||
private:
|
||||
static V8_WARN_UNUSED_RESULT MaybeLocal<UnboundScript> CompileUnboundInternal(
|
||||
Isolate* isolate, Source* source, CompileOptions options,
|
||||
|
20
src/api.cc
20
src/api.cc
@ -2660,26 +2660,6 @@ uint32_t ScriptCompiler::CachedDataVersionTag() {
|
||||
static_cast<uint32_t>(internal::CpuFeatures::SupportedFeatures())));
|
||||
}
|
||||
|
||||
ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCache(
|
||||
Local<UnboundScript> unbound_script, Local<String> source) {
|
||||
i::Handle<i::SharedFunctionInfo> shared =
|
||||
i::Handle<i::SharedFunctionInfo>::cast(
|
||||
Utils::OpenHandle(*unbound_script));
|
||||
DCHECK(shared->is_toplevel());
|
||||
i::Handle<i::Script> script(i::Script::cast(shared->script()));
|
||||
i::Isolate* isolate = shared->GetIsolate();
|
||||
// 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;
|
||||
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;
|
||||
return result;
|
||||
}
|
||||
|
||||
MaybeLocal<Script> Script::Compile(Local<Context> context, Local<String> source,
|
||||
ScriptOrigin* origin) {
|
||||
|
@ -1176,6 +1176,15 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
|
||||
|
||||
namespace {
|
||||
|
||||
bool ContainsAsmModule(Handle<Script> script) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
SharedFunctionInfo::ScriptIterator iter(script);
|
||||
while (SharedFunctionInfo* info = iter.Next()) {
|
||||
if (info->HasAsmWasmData()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ShouldProduceCodeCache(ScriptCompiler::CompileOptions options) {
|
||||
return options == ScriptCompiler::kProduceCodeCache ||
|
||||
options == ScriptCompiler::kProduceFullCodeCache;
|
||||
@ -1563,7 +1572,7 @@ MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
|
||||
compilation_cache->PutScript(source, context, language_mode, result,
|
||||
vector);
|
||||
if (ShouldProduceCodeCache(compile_options) &&
|
||||
!script->ContainsAsmModule()) {
|
||||
!ContainsAsmModule(script)) {
|
||||
compile_timer.set_producing_code_cache();
|
||||
|
||||
HistogramTimerScope histogram_timer(
|
||||
|
199
src/d8.cc
199
src/d8.cc
@ -506,8 +506,6 @@ std::vector<Worker*> Shell::workers_;
|
||||
std::vector<ExternalizedContents> Shell::externalized_contents_;
|
||||
base::LazyMutex Shell::isolate_status_lock_;
|
||||
std::map<v8::Isolate*, bool> Shell::isolate_status_;
|
||||
std::map<std::string, std::unique_ptr<ScriptCompiler::CachedData>>
|
||||
Shell::cached_code_map_;
|
||||
|
||||
Global<Context> Shell::evaluation_context_;
|
||||
ArrayBuffer::Allocator* Shell::array_buffer_allocator;
|
||||
@ -568,37 +566,95 @@ class BackgroundCompileThread : public base::Thread {
|
||||
std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask> task_;
|
||||
};
|
||||
|
||||
ScriptCompiler::CachedData* Shell::LookupCodeCache(Isolate* isolate,
|
||||
Local<Value> name) {
|
||||
CHECK(name->IsString());
|
||||
v8::String::Utf8Value key(isolate, name);
|
||||
DCHECK(*key);
|
||||
auto entry = cached_code_map_.find(*key);
|
||||
if (entry != cached_code_map_.end() && entry->second) {
|
||||
int length = entry->second->length;
|
||||
uint8_t* cache = new uint8_t[length];
|
||||
memcpy(cache, entry->second->data, length);
|
||||
ScriptCompiler::CachedData* cached_data = new ScriptCompiler::CachedData(
|
||||
cache, length, ScriptCompiler::CachedData::BufferOwned);
|
||||
return cached_data;
|
||||
ScriptCompiler::CachedData* CompileForCachedData(
|
||||
Local<String> source, Local<Value> name,
|
||||
ScriptCompiler::CompileOptions compile_options) {
|
||||
int source_length = source->Length();
|
||||
uint16_t* source_buffer = new uint16_t[source_length];
|
||||
source->Write(source_buffer, 0, source_length);
|
||||
int name_length = 0;
|
||||
uint16_t* name_buffer = nullptr;
|
||||
if (name->IsString()) {
|
||||
Local<String> name_string = Local<String>::Cast(name);
|
||||
name_length = name_string->Length();
|
||||
name_buffer = new uint16_t[name_length];
|
||||
name_string->Write(name_buffer, 0, name_length);
|
||||
}
|
||||
return nullptr;
|
||||
Isolate::CreateParams create_params;
|
||||
create_params.array_buffer_allocator = Shell::array_buffer_allocator;
|
||||
i::FLAG_hash_seed ^= 1337; // Use a different hash seed.
|
||||
Isolate* temp_isolate = Isolate::New(create_params);
|
||||
i::FLAG_hash_seed ^= 1337; // Restore old hash seed.
|
||||
temp_isolate->SetHostImportModuleDynamicallyCallback(
|
||||
Shell::HostImportModuleDynamically);
|
||||
temp_isolate->SetHostInitializeImportMetaObjectCallback(
|
||||
Shell::HostInitializeImportMetaObject);
|
||||
ScriptCompiler::CachedData* result = nullptr;
|
||||
{
|
||||
Isolate::Scope isolate_scope(temp_isolate);
|
||||
HandleScope handle_scope(temp_isolate);
|
||||
Context::Scope context_scope(Context::New(temp_isolate));
|
||||
Local<String> source_copy =
|
||||
v8::String::NewFromTwoByte(temp_isolate, source_buffer,
|
||||
v8::NewStringType::kNormal, source_length)
|
||||
.ToLocalChecked();
|
||||
Local<Value> name_copy;
|
||||
if (name_buffer) {
|
||||
name_copy =
|
||||
v8::String::NewFromTwoByte(temp_isolate, name_buffer,
|
||||
v8::NewStringType::kNormal, name_length)
|
||||
.ToLocalChecked();
|
||||
} else {
|
||||
name_copy = v8::Undefined(temp_isolate);
|
||||
}
|
||||
ScriptCompiler::Source script_source(source_copy, ScriptOrigin(name_copy));
|
||||
if (!ScriptCompiler::CompileUnboundScript(temp_isolate, &script_source,
|
||||
compile_options)
|
||||
.IsEmpty() &&
|
||||
script_source.GetCachedData()) {
|
||||
int length = script_source.GetCachedData()->length;
|
||||
uint8_t* cache = new uint8_t[length];
|
||||
memcpy(cache, script_source.GetCachedData()->data, length);
|
||||
result = new ScriptCompiler::CachedData(
|
||||
cache, length, ScriptCompiler::CachedData::BufferOwned);
|
||||
}
|
||||
}
|
||||
temp_isolate->Dispose();
|
||||
delete[] source_buffer;
|
||||
delete[] name_buffer;
|
||||
return result;
|
||||
}
|
||||
|
||||
void Shell::StoreInCodeCache(Isolate* isolate, Local<Value> name,
|
||||
const ScriptCompiler::CachedData* cache_data) {
|
||||
CHECK(name->IsString());
|
||||
if (cache_data == nullptr) return;
|
||||
v8::String::Utf8Value key(isolate, name);
|
||||
DCHECK(*key);
|
||||
int length = cache_data->length;
|
||||
uint8_t* cache = new uint8_t[length];
|
||||
memcpy(cache, cache_data->data, length);
|
||||
cached_code_map_[*key] = std::unique_ptr<ScriptCompiler::CachedData>(
|
||||
new ScriptCompiler::CachedData(cache, length,
|
||||
ScriptCompiler::CachedData::BufferOwned));
|
||||
|
||||
// Compile a string within the current v8 context.
|
||||
MaybeLocal<Script> Shell::CompileString(
|
||||
Isolate* isolate, Local<String> source, Local<Value> name,
|
||||
ScriptCompiler::CompileOptions compile_options) {
|
||||
Local<Context> context(isolate->GetCurrentContext());
|
||||
ScriptOrigin origin(name);
|
||||
if (compile_options == ScriptCompiler::kNoCompileOptions) {
|
||||
ScriptCompiler::Source script_source(source, origin);
|
||||
return ScriptCompiler::Compile(context, &script_source, compile_options);
|
||||
}
|
||||
|
||||
ScriptCompiler::CachedData* data =
|
||||
CompileForCachedData(source, name, compile_options);
|
||||
ScriptCompiler::Source cached_source(source, origin, data);
|
||||
if (compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
compile_options = ScriptCompiler::kConsumeCodeCache;
|
||||
} else if (compile_options == ScriptCompiler::kProduceParserCache) {
|
||||
compile_options = ScriptCompiler::kConsumeParserCache;
|
||||
} else {
|
||||
DCHECK(false); // A new compile option?
|
||||
}
|
||||
if (data == nullptr) compile_options = ScriptCompiler::kNoCompileOptions;
|
||||
MaybeLocal<Script> result =
|
||||
ScriptCompiler::Compile(context, &cached_source, compile_options);
|
||||
CHECK(data == nullptr || !data->rejected);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Executes a string within the current v8 context.
|
||||
bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
|
||||
Local<Value> name, bool print_result,
|
||||
@ -615,22 +671,7 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
|
||||
Local<Context>::New(isolate, data->realms_[data->realm_current_]);
|
||||
Context::Scope context_scope(realm);
|
||||
MaybeLocal<Script> maybe_script;
|
||||
Local<Context> context(isolate->GetCurrentContext());
|
||||
ScriptOrigin origin(name);
|
||||
|
||||
if (options.compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
ScriptCompiler::CachedData* cached_code = LookupCodeCache(isolate, name);
|
||||
if (cached_code != nullptr) {
|
||||
ScriptCompiler::Source script_source(source, origin, cached_code);
|
||||
maybe_script = ScriptCompiler::Compile(context, &script_source,
|
||||
options.compile_options);
|
||||
CHECK(!cached_code->rejected);
|
||||
} else {
|
||||
ScriptCompiler::Source script_source(source, origin);
|
||||
maybe_script = ScriptCompiler::Compile(
|
||||
context, &script_source, ScriptCompiler::kNoCompileOptions);
|
||||
}
|
||||
} else if (options.stress_background_compile) {
|
||||
if (options.stress_background_compile) {
|
||||
// Start a background thread compiling the script.
|
||||
BackgroundCompileThread background_compile_thread(isolate, source);
|
||||
background_compile_thread.Start();
|
||||
@ -638,26 +679,18 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
|
||||
// In parallel, compile on the main thread to flush out any data races.
|
||||
{
|
||||
TryCatch ignore_try_catch(isolate);
|
||||
ScriptCompiler::Source script_source(source, origin);
|
||||
USE(ScriptCompiler::Compile(context, &script_source,
|
||||
ScriptCompiler::kNoCompileOptions));
|
||||
Shell::CompileString(isolate, source, name, options.compile_options);
|
||||
}
|
||||
|
||||
// Join with background thread and finalize compilation.
|
||||
background_compile_thread.Join();
|
||||
ScriptOrigin origin(name);
|
||||
maybe_script = v8::ScriptCompiler::Compile(
|
||||
context, background_compile_thread.streamed_source(), source, origin);
|
||||
isolate->GetCurrentContext(),
|
||||
background_compile_thread.streamed_source(), source, origin);
|
||||
} else {
|
||||
ScriptCompiler::Source script_source(source, origin);
|
||||
ScriptCompiler::CompileOptions compile_options =
|
||||
options.cache_code_after_execute ? ScriptCompiler::kNoCompileOptions
|
||||
: options.compile_options;
|
||||
maybe_script =
|
||||
ScriptCompiler::Compile(context, &script_source, compile_options);
|
||||
if (compile_options == ScriptCompiler::kProduceCodeCache ||
|
||||
compile_options == ScriptCompiler::kProduceParserCache) {
|
||||
StoreInCodeCache(isolate, name, script_source.GetCachedData());
|
||||
}
|
||||
Shell::CompileString(isolate, source, name, options.compile_options);
|
||||
}
|
||||
|
||||
Local<Script> script;
|
||||
@ -668,14 +701,6 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
|
||||
}
|
||||
|
||||
maybe_result = script->Run(realm);
|
||||
if (options.compile_options == ScriptCompiler::kProduceCodeCache &&
|
||||
options.cache_code_after_execute) {
|
||||
// Serialize and store it in memory for the next execution.
|
||||
ScriptCompiler::CachedData* cached_data =
|
||||
ScriptCompiler::CreateCodeCache(script->GetUnboundScript(), source);
|
||||
StoreInCodeCache(isolate, name, cached_data);
|
||||
delete cached_data;
|
||||
}
|
||||
if (!EmptyMessageQueues(isolate)) success = false;
|
||||
data->realm_current_ = data->realm_switch_;
|
||||
}
|
||||
@ -2843,9 +2868,6 @@ bool Shell::SetOptions(int argc, char* argv[]) {
|
||||
options.compile_options = v8::ScriptCompiler::kProduceParserCache;
|
||||
} else if (strncmp(value, "=none", 6) == 0) {
|
||||
options.compile_options = v8::ScriptCompiler::kNoCompileOptions;
|
||||
} else if (strncmp(value, "=after-execute", 10) == 0) {
|
||||
options.compile_options = v8::ScriptCompiler::kProduceCodeCache;
|
||||
options.cache_code_after_execute = true;
|
||||
} else {
|
||||
printf("Unknown option to --cache.\n");
|
||||
return false;
|
||||
@ -3391,47 +3413,6 @@ int Shell::Main(int argc, char* argv[]) {
|
||||
bool last_run = i == options.stress_runs - 1;
|
||||
result = RunMain(isolate, argc, argv, last_run);
|
||||
}
|
||||
} else if (options.compile_options ==
|
||||
v8::ScriptCompiler::kProduceCodeCache ||
|
||||
options.compile_options ==
|
||||
v8::ScriptCompiler::kProduceParserCache) {
|
||||
printf("============ Run: Produce code cache ============\n");
|
||||
// First run to produce the cache
|
||||
result = RunMain(isolate, argc, argv, false);
|
||||
|
||||
// Change the options to consume cache
|
||||
if (options.compile_options == v8::ScriptCompiler::kProduceCodeCache) {
|
||||
options.compile_options = v8::ScriptCompiler::kConsumeCodeCache;
|
||||
} else if (options.compile_options ==
|
||||
v8::ScriptCompiler::kProduceParserCache) {
|
||||
options.compile_options = v8::ScriptCompiler::kConsumeParserCache;
|
||||
} else {
|
||||
// We only expect ProduceCodeCache or ProduceParserCache here.
|
||||
// compile_options cannot be NoCompileOptions.
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
printf("============ Run: Consume code cache ============\n");
|
||||
// Second run to consume the cache in new isolate
|
||||
Isolate::CreateParams create_params;
|
||||
create_params.array_buffer_allocator = Shell::array_buffer_allocator;
|
||||
i::FLAG_hash_seed ^= 1337; // Use a different hash seed.
|
||||
Isolate* isolate2 = Isolate::New(create_params);
|
||||
i::FLAG_hash_seed ^= 1337; // Restore old hash seed.
|
||||
isolate2->SetHostImportModuleDynamicallyCallback(
|
||||
Shell::HostImportModuleDynamically);
|
||||
isolate2->SetHostInitializeImportMetaObjectCallback(
|
||||
Shell::HostInitializeImportMetaObject);
|
||||
{
|
||||
D8Console console(isolate2);
|
||||
debug::SetConsoleDelegate(isolate2, &console);
|
||||
PerIsolateData data(isolate2);
|
||||
Isolate::Scope isolate_scope(isolate2);
|
||||
|
||||
result = RunMain(isolate2, argc, argv, false);
|
||||
}
|
||||
cached_code_map_.clear();
|
||||
isolate2->Dispose();
|
||||
} else {
|
||||
bool last_run = true;
|
||||
result = RunMain(isolate, argc, argv, last_run);
|
||||
|
11
src/d8.h
11
src/d8.h
@ -296,7 +296,6 @@ class ShellOptions {
|
||||
num_isolates(1),
|
||||
compile_options(v8::ScriptCompiler::kNoCompileOptions),
|
||||
stress_background_compile(false),
|
||||
cache_code_after_execute(false),
|
||||
isolate_sources(nullptr),
|
||||
icu_data_file(nullptr),
|
||||
natives_blob(nullptr),
|
||||
@ -330,7 +329,6 @@ class ShellOptions {
|
||||
int num_isolates;
|
||||
v8::ScriptCompiler::CompileOptions compile_options;
|
||||
bool stress_background_compile;
|
||||
bool cache_code_after_execute;
|
||||
SourceGroup* isolate_sources;
|
||||
const char* icu_data_file;
|
||||
const char* natives_blob;
|
||||
@ -346,6 +344,9 @@ class ShellOptions {
|
||||
|
||||
class Shell : public i::AllStatic {
|
||||
public:
|
||||
static MaybeLocal<Script> CompileString(
|
||||
Isolate* isolate, Local<String> source, Local<Value> name,
|
||||
v8::ScriptCompiler::CompileOptions compile_options);
|
||||
static bool ExecuteString(Isolate* isolate, Local<String> source,
|
||||
Local<Value> name, bool print_result,
|
||||
bool report_exceptions);
|
||||
@ -503,16 +504,10 @@ class Shell : public i::AllStatic {
|
||||
int index);
|
||||
static MaybeLocal<Module> FetchModuleTree(v8::Local<v8::Context> context,
|
||||
const std::string& file_name);
|
||||
static ScriptCompiler::CachedData* LookupCodeCache(Isolate* isolate,
|
||||
Local<Value> name);
|
||||
static void StoreInCodeCache(Isolate* isolate, Local<Value> name,
|
||||
const ScriptCompiler::CachedData* data);
|
||||
// We may have multiple isolates running concurrently, so the access to
|
||||
// the isolate_status_ needs to be concurrency-safe.
|
||||
static base::LazyMutex isolate_status_lock_;
|
||||
static std::map<Isolate*, bool> isolate_status_;
|
||||
static std::map<std::string, std::unique_ptr<ScriptCompiler::CachedData>>
|
||||
cached_code_map_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -13263,15 +13263,6 @@ bool Script::GetPositionInfo(Handle<Script> script, int position,
|
||||
|
||||
bool Script::IsUserJavaScript() { return type() == Script::TYPE_NORMAL; }
|
||||
|
||||
bool Script::ContainsAsmModule() {
|
||||
DisallowHeapAllocation no_gc;
|
||||
SharedFunctionInfo::ScriptIterator iter(Handle<Script>(this));
|
||||
while (SharedFunctionInfo* info = iter.Next()) {
|
||||
if (info->HasAsmWasmData()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool GetPositionInfoSlow(const Script* script, int position,
|
||||
Script::PositionInfo* info) {
|
||||
|
@ -635,14 +635,6 @@ ByteArray* BytecodeArray::SourcePositionTable() {
|
||||
->source_position_table();
|
||||
}
|
||||
|
||||
void BytecodeArray::ClearFrameCacheFromSourcePositionTable() {
|
||||
Object* maybe_table = source_position_table();
|
||||
if (maybe_table->IsByteArray()) return;
|
||||
DCHECK(maybe_table->IsSourcePositionTableWithFrameCache());
|
||||
set_source_position_table(SourcePositionTableWithFrameCache::cast(maybe_table)
|
||||
->source_position_table());
|
||||
}
|
||||
|
||||
int BytecodeArray::BytecodeArraySize() { return SizeFor(this->length()); }
|
||||
|
||||
int BytecodeArray::SizeIncludingMetadata() {
|
||||
|
@ -790,7 +790,6 @@ class BytecodeArray : public FixedArrayBase {
|
||||
DECL_ACCESSORS(source_position_table, Object)
|
||||
|
||||
inline ByteArray* SourcePositionTable();
|
||||
inline void ClearFrameCacheFromSourcePositionTable();
|
||||
|
||||
DECL_CAST(BytecodeArray)
|
||||
|
||||
|
@ -118,9 +118,6 @@ class Script : public Struct {
|
||||
// Retrieve source position from where eval was called.
|
||||
int GetEvalPosition();
|
||||
|
||||
// Check if the script contains any Asm modules.
|
||||
bool ContainsAsmModule();
|
||||
|
||||
// Init line_ends array with source code positions of line ends.
|
||||
static void InitLineEnds(Handle<Script> script);
|
||||
|
||||
|
@ -106,37 +106,12 @@ void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
|
||||
}
|
||||
|
||||
if (obj->IsScript()) {
|
||||
Script* script_obj = Script::cast(obj);
|
||||
DCHECK_NE(script_obj->compilation_type(), Script::COMPILATION_TYPE_EVAL);
|
||||
// Wrapper object is a context-dependent JSValue. Reset it here.
|
||||
script_obj->set_wrapper(isolate()->heap()->undefined_value());
|
||||
// We want to differentiate between undefined and uninitialized_symbol for
|
||||
// context_data for now. It is hack to allow debugging for scripts that are
|
||||
// included as a part of custom snapshot. (see debug::Script::IsEmbedded())
|
||||
Object* context_data = script_obj->context_data();
|
||||
if (context_data != isolate()->heap()->undefined_value() &&
|
||||
context_data != isolate()->heap()->uninitialized_symbol()) {
|
||||
script_obj->set_context_data(isolate()->heap()->undefined_value());
|
||||
}
|
||||
// We don't want to serialize host options to avoid serializing unnecessary
|
||||
// object graph.
|
||||
FixedArray* host_options = script_obj->host_defined_options();
|
||||
script_obj->set_host_defined_options(
|
||||
isolate()->heap()->empty_fixed_array());
|
||||
SerializeGeneric(obj, how_to_code, where_to_point);
|
||||
script_obj->set_host_defined_options(host_options);
|
||||
script_obj->set_context_data(context_data);
|
||||
return;
|
||||
Script::cast(obj)->set_wrapper(isolate()->heap()->undefined_value());
|
||||
}
|
||||
|
||||
if (obj->IsSharedFunctionInfo()) {
|
||||
SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj);
|
||||
// TODO(7110): Enable serializing of Asm modules once the AsmWasmData
|
||||
// is context independent.
|
||||
DCHECK(!sfi->IsApiFunction() && !sfi->HasAsmWasmData());
|
||||
// Do not serialize when a debugger is active.
|
||||
DCHECK(sfi->debug_info()->IsSmi());
|
||||
|
||||
// Mark SFI to indicate whether the code is cached.
|
||||
bool was_deserialized = sfi->deserialized();
|
||||
sfi->set_deserialized(sfi->is_compiled());
|
||||
@ -145,11 +120,6 @@ void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj->IsBytecodeArray()) {
|
||||
// Clear the stack frame cache if present
|
||||
BytecodeArray::cast(obj)->ClearFrameCacheFromSourcePositionTable();
|
||||
}
|
||||
|
||||
// Past this point we should not see any (context-specific) maps anymore.
|
||||
CHECK(!obj->IsMap());
|
||||
// There should be no references to the global object embedded.
|
||||
|
@ -234,13 +234,6 @@ HeapObject* Deserializer<AllocatorT>::PostProcessNewObject(HeapObject* obj,
|
||||
void* backing_store = off_heap_backing_stores_[store_index->value()];
|
||||
fta->set_external_pointer(backing_store);
|
||||
}
|
||||
} else if (obj->IsBytecodeArray()) {
|
||||
// TODO(mythria): Remove these once we store the default values for these
|
||||
// fields in the serializer.
|
||||
BytecodeArray* bytecode_array = BytecodeArray::cast(obj);
|
||||
bytecode_array->set_interrupt_budget(
|
||||
interpreter::Interpreter::kInterruptBudget);
|
||||
bytecode_array->set_osr_loop_nesting_level(0);
|
||||
}
|
||||
// Check alignment.
|
||||
DCHECK_EQ(0, Heap::GetFillToAlign(obj->address(), obj->RequiredAlignment()));
|
||||
|
@ -57,8 +57,6 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
enum CodeCacheType { kLazy, kEager, kAfterExecute };
|
||||
|
||||
void DisableLazyDeserialization() {
|
||||
// UNINITIALIZED tests do not set up the isolate sufficiently for lazy
|
||||
// deserialization to work.
|
||||
@ -1840,8 +1838,8 @@ static void SerializerCodeEventListener(const v8::JitCodeEvent* event) {
|
||||
}
|
||||
}
|
||||
|
||||
v8::ScriptCompiler::CachedData* ProduceCache(
|
||||
const char* source, CodeCacheType cacheType = CodeCacheType::kLazy) {
|
||||
v8::ScriptCompiler::CachedData* ProduceCache(const char* source,
|
||||
bool eager = false) {
|
||||
v8::ScriptCompiler::CachedData* cache;
|
||||
v8::Isolate::CreateParams create_params;
|
||||
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
|
||||
@ -1855,23 +1853,19 @@ v8::ScriptCompiler::CachedData* ProduceCache(
|
||||
v8::Local<v8::String> source_str = v8_str(source);
|
||||
v8::ScriptOrigin origin(v8_str("test"));
|
||||
v8::ScriptCompiler::Source source(source_str, origin);
|
||||
v8::ScriptCompiler::CompileOptions options;
|
||||
switch (cacheType) {
|
||||
case CodeCacheType::kLazy:
|
||||
options = v8::ScriptCompiler::kProduceCodeCache;
|
||||
break;
|
||||
case CodeCacheType::kEager:
|
||||
options = v8::ScriptCompiler::kProduceFullCodeCache;
|
||||
break;
|
||||
case CodeCacheType::kAfterExecute:
|
||||
options = v8::ScriptCompiler::kNoCompileOptions;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
v8::ScriptCompiler::CompileOptions options =
|
||||
eager ? v8::ScriptCompiler::kProduceFullCodeCache
|
||||
: v8::ScriptCompiler::kProduceCodeCache;
|
||||
v8::Local<v8::UnboundScript> script =
|
||||
v8::ScriptCompiler::CompileUnboundScript(isolate1, &source, options)
|
||||
.ToLocalChecked();
|
||||
const v8::ScriptCompiler::CachedData* data = source.GetCachedData();
|
||||
CHECK(data);
|
||||
// Persist cached data.
|
||||
uint8_t* buffer = NewArray<uint8_t>(data->length);
|
||||
MemCopy(buffer, data->data, data->length);
|
||||
cache = new v8::ScriptCompiler::CachedData(
|
||||
buffer, data->length, v8::ScriptCompiler::CachedData::BufferOwned);
|
||||
|
||||
v8::Local<v8::Value> result = script->BindToCurrentContext()
|
||||
->Run(isolate1->GetCurrentContext())
|
||||
@ -1880,18 +1874,6 @@ v8::ScriptCompiler::CachedData* ProduceCache(
|
||||
result->ToString(isolate1->GetCurrentContext()).ToLocalChecked();
|
||||
CHECK(result_string->Equals(isolate1->GetCurrentContext(), v8_str("abcdef"))
|
||||
.FromJust());
|
||||
|
||||
if (cacheType == CodeCacheType::kAfterExecute) {
|
||||
cache = ScriptCompiler::CreateCodeCache(script, source_str);
|
||||
} else {
|
||||
const ScriptCompiler::CachedData* data = source.GetCachedData();
|
||||
CHECK(data);
|
||||
uint8_t* buffer = NewArray<uint8_t>(data->length);
|
||||
MemCopy(buffer, data->data, data->length);
|
||||
cache = new v8::ScriptCompiler::CachedData(
|
||||
buffer, data->length, v8::ScriptCompiler::CachedData::BufferOwned);
|
||||
}
|
||||
CHECK(cache);
|
||||
}
|
||||
isolate1->Dispose();
|
||||
return cache;
|
||||
@ -1954,8 +1936,7 @@ TEST(CodeSerializerIsolatesEager) {
|
||||
" }"
|
||||
"}"
|
||||
"f()() + 'def'";
|
||||
v8::ScriptCompiler::CachedData* cache =
|
||||
ProduceCache(source, CodeCacheType::kEager);
|
||||
v8::ScriptCompiler::CachedData* cache = ProduceCache(source, true);
|
||||
|
||||
v8::Isolate::CreateParams create_params;
|
||||
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
|
||||
@ -1993,68 +1974,6 @@ TEST(CodeSerializerIsolatesEager) {
|
||||
isolate2->Dispose();
|
||||
}
|
||||
|
||||
TEST(CodeSerializerAfterExecute) {
|
||||
// We test that no compilations happen when running this code. Forcing
|
||||
// to always optimize breaks this test.
|
||||
bool prev_opt_value = FLAG_opt;
|
||||
bool prev_always_opt_value = FLAG_always_opt;
|
||||
FLAG_always_opt = false;
|
||||
FLAG_opt = false;
|
||||
const char* source = "function f() { return 'abc'; }; f() + 'def'";
|
||||
v8::ScriptCompiler::CachedData* cache =
|
||||
ProduceCache(source, CodeCacheType::kAfterExecute);
|
||||
|
||||
v8::Isolate::CreateParams create_params;
|
||||
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
|
||||
v8::Isolate* isolate2 = v8::Isolate::New(create_params);
|
||||
|
||||
{
|
||||
v8::Isolate::Scope iscope(isolate2);
|
||||
v8::HandleScope scope(isolate2);
|
||||
v8::Local<v8::Context> context = v8::Context::New(isolate2);
|
||||
v8::Context::Scope context_scope(context);
|
||||
|
||||
v8::Local<v8::String> source_str = v8_str(source);
|
||||
v8::ScriptOrigin origin(v8_str("test"));
|
||||
v8::ScriptCompiler::Source source(source_str, origin, cache);
|
||||
v8::Local<v8::UnboundScript> script;
|
||||
{
|
||||
DisallowCompilation no_compile_expected(
|
||||
reinterpret_cast<Isolate*>(isolate2));
|
||||
script = v8::ScriptCompiler::CompileUnboundScript(
|
||||
isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
|
||||
.ToLocalChecked();
|
||||
}
|
||||
CHECK(!cache->rejected);
|
||||
CheckDeserializedFlag(script);
|
||||
|
||||
Handle<SharedFunctionInfo> sfi = v8::Utils::OpenHandle(*script);
|
||||
CHECK(sfi->HasBytecodeArray());
|
||||
BytecodeArray* bytecode = sfi->bytecode_array();
|
||||
CHECK_EQ(bytecode->interrupt_budget(),
|
||||
interpreter::Interpreter::kInterruptBudget);
|
||||
CHECK_EQ(bytecode->osr_loop_nesting_level(), 0);
|
||||
|
||||
{
|
||||
DisallowCompilation no_compile_expected(
|
||||
reinterpret_cast<Isolate*>(isolate2));
|
||||
v8::Local<v8::Value> result = script->BindToCurrentContext()
|
||||
->Run(isolate2->GetCurrentContext())
|
||||
.ToLocalChecked();
|
||||
v8::Local<v8::String> result_string =
|
||||
result->ToString(isolate2->GetCurrentContext()).ToLocalChecked();
|
||||
CHECK(
|
||||
result_string->Equals(isolate2->GetCurrentContext(), v8_str("abcdef"))
|
||||
.FromJust());
|
||||
}
|
||||
}
|
||||
isolate2->Dispose();
|
||||
|
||||
// Restore the flags.
|
||||
FLAG_always_opt = prev_always_opt_value;
|
||||
FLAG_opt = prev_opt_value;
|
||||
}
|
||||
|
||||
TEST(CodeSerializerFlagChange) {
|
||||
const char* source = "function f() { return 'abc'; }; f() + 'def'";
|
||||
v8::ScriptCompiler::CachedData* cache = ProduceCache(source);
|
||||
|
@ -1,15 +0,0 @@
|
||||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --cache=after-execute
|
||||
|
||||
function g() {
|
||||
function h() {
|
||||
function k() { return 0; };
|
||||
return k;
|
||||
}
|
||||
return h();
|
||||
}
|
||||
|
||||
g();
|
Loading…
Reference in New Issue
Block a user