From e78305bd54671400dca8358340b2d3a242ff8278 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Thu, 1 Mar 2018 11:50:50 -0800 Subject: [PATCH 1/4] add 037-backport_76c3ac5.patch --- patches/v8/037-backport_76c3ac5.patch | 118 ++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 patches/v8/037-backport_76c3ac5.patch diff --git a/patches/v8/037-backport_76c3ac5.patch b/patches/v8/037-backport_76c3ac5.patch new file mode 100644 index 00000000..2c7ece1c --- /dev/null +++ b/patches/v8/037-backport_76c3ac5.patch @@ -0,0 +1,118 @@ +diff --git a/src/profiler/profiler-listener.cc b/src/profiler/profiler-listener.cc +index 540d930024..b90f5a4894 100644 +--- a/src/profiler/profiler-listener.cc ++++ b/src/profiler/profiler-listener.cc +@@ -226,11 +226,18 @@ void ProfilerListener::RecordInliningInfo(CodeEntry* entry, + SharedFunctionInfo* shared_info = SharedFunctionInfo::cast( + deopt_input_data->LiteralArray()->get(shared_info_id)); + if (!depth++) continue; // Skip the current function itself. +- CodeEntry* inline_entry = new CodeEntry( +- entry->tag(), GetFunctionName(shared_info->DebugName()), +- CodeEntry::kEmptyNamePrefix, entry->resource_name(), +- CpuProfileNode::kNoLineNumberInfo, +- CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start()); ++ const char* resource_name = ++ (shared_info->script()->IsScript() && ++ Script::cast(shared_info->script())->name()->IsName()) ++ ? GetName(Name::cast(Script::cast(shared_info->script())->name())) ++ : CodeEntry::kEmptyResourceName; ++ ++ CodeEntry* inline_entry = ++ new CodeEntry(entry->tag(), GetFunctionName(shared_info->DebugName()), ++ CodeEntry::kEmptyNamePrefix, resource_name, ++ CpuProfileNode::kNoLineNumberInfo, ++ CpuProfileNode::kNoColumnNumberInfo, nullptr, ++ code->instruction_start()); + inline_entry->FillFunctionInfo(shared_info); + inline_stack.push_back(inline_entry); + } +diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc +index f22a42a977..b441d04fdd 100644 +--- a/test/cctest/test-cpu-profiler.cc ++++ b/test/cctest/test-cpu-profiler.cc +@@ -1745,6 +1745,85 @@ TEST(FunctionDetails) { + script_a->GetUnboundScript()->GetId(), 5, 14); + } + ++TEST(FunctionDetailsInlining) { ++ if (!CcTest::i_isolate()->use_optimizer() || i::FLAG_always_opt) return; ++ i::FLAG_allow_natives_syntax = true; ++ v8::HandleScope scope(CcTest::isolate()); ++ v8::Local env = CcTest::NewContext(PROFILER_EXTENSION); ++ v8::Context::Scope context_scope(env); ++ ProfilerHelper helper(env); ++ ++ // alpha is in a_script, beta in b_script. beta is ++ // inlined in alpha, but it should be attributed to b_script. ++ ++ v8::Local script_b = CompileWithOrigin( ++ "function beta(k) {\n" ++ " let sum = 2;\n" ++ " for(let i = 0; i < k; i ++) {\n" ++ " sum += i;\n" ++ " sum = sum + 'a';\n" ++ " }\n" ++ " return sum;\n" ++ "}\n" ++ "\n", ++ "script_b"); ++ ++ v8::Local script_a = CompileWithOrigin( ++ "function alpha(p) {\n" ++ " let res = beta(p);\n" ++ " res = res + res;\n" ++ " return res;\n" ++ "}\n" ++ "let p = 2;\n" ++ "\n" ++ "\n" ++ "// Warm up before profiling or the inlining doesn't happen.\n" ++ "p = alpha(p);\n" ++ "p = alpha(p);\n" ++ "%OptimizeFunctionOnNextCall(alpha);\n" ++ "p = alpha(p);\n" ++ "\n" ++ "\n" ++ "startProfiling();\n" ++ "for(let i = 0; i < 10000; i++) {\n" ++ " p = alpha(p);\n" ++ "}\n" ++ "stopProfiling();\n" ++ "\n" ++ "\n", ++ "script_a"); ++ ++ script_b->Run(env).ToLocalChecked(); ++ script_a->Run(env).ToLocalChecked(); ++ ++ const v8::CpuProfile* profile = i::ProfilerExtension::last_profile; ++ const v8::CpuProfileNode* current = profile->GetTopDownRoot(); ++ reinterpret_cast(const_cast(current)) ++ ->Print(0); ++ // The tree should look like this: ++ // 0 (root) 0 #1 ++ // 5 (program) 0 #6 ++ // 2 14 #2 script_a:1 ++ // ;;; deopted at script_id: 14 position: 299 with reason 'Insufficient ++ // type feedback for call'. ++ // 1 alpha 14 #4 script_a:1 ++ // 9 beta 13 #5 script_b:0 ++ // 0 startProfiling 0 #3 ++ ++ const v8::CpuProfileNode* root = profile->GetTopDownRoot(); ++ const v8::CpuProfileNode* script = GetChild(env, root, ""); ++ CheckFunctionDetails(env->GetIsolate(), script, "", "script_a", ++ script_a->GetUnboundScript()->GetId(), 1, 1); ++ const v8::CpuProfileNode* alpha = FindChild(env, script, "alpha"); ++ // Return early if profiling didn't sample alpha. ++ if (!alpha) return; ++ CheckFunctionDetails(env->GetIsolate(), alpha, "alpha", "script_a", ++ script_a->GetUnboundScript()->GetId(), 1, 15); ++ const v8::CpuProfileNode* beta = FindChild(env, alpha, "beta"); ++ if (!beta) return; ++ CheckFunctionDetails(env->GetIsolate(), beta, "beta", "script_b", ++ script_b->GetUnboundScript()->GetId(), 0, 0); ++} + + TEST(DontStopOnFinishedProfileDelete) { + v8::HandleScope scope(CcTest::isolate()); From 33e3d2e41d9f79954e6f1b03934f9395c989b11b Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Thu, 1 Mar 2018 11:55:07 -0800 Subject: [PATCH 2/4] add 038-cherry_pick_dbfe4a49d8.patch --- patches/v8/038-cherry_pick_dbfe4a49d8.patch | 788 ++++++++++++++++++++ 1 file changed, 788 insertions(+) create mode 100644 patches/v8/038-cherry_pick_dbfe4a49d8.patch diff --git a/patches/v8/038-cherry_pick_dbfe4a49d8.patch b/patches/v8/038-cherry_pick_dbfe4a49d8.patch new file mode 100644 index 00000000..becb6f5b --- /dev/null +++ b/patches/v8/038-cherry_pick_dbfe4a49d8.patch @@ -0,0 +1,788 @@ +diff --git a/include/v8.h b/include/v8.h +index 918f5d86de..46fd3d50e0 100644 +--- a/include/v8.h ++++ b/include/v8.h +@@ -104,6 +104,7 @@ class String; + class StringObject; + class Symbol; + class SymbolObject; ++class PrimitiveArray; + class Private; + class Uint32; + class Utils; +@@ -978,6 +979,48 @@ class V8_EXPORT Data { + Data(); + }; + ++/** ++ * This is an unfinished experimental feature, and is only exposed ++ * here for internal testing purposes. DO NOT USE. ++ * ++ * A container type that holds relevant metadata for module loading. ++ * ++ * This is passed back to the embedder as part of ++ * HostImportDynamicallyCallback for module loading. ++ */ ++class V8_EXPORT ScriptOrModule { ++ public: ++ /** ++ * The name that was passed by the embedder as ResourceName to the ++ * ScriptOrigin. This can be either a v8::String or v8::Undefined. ++ */ ++ Local GetResourceName(); ++ ++ /** ++ * The options that were passed by the embedder as HostDefinedOptions to ++ * the ScriptOrigin. ++ */ ++ Local GetHostDefinedOptions(); ++}; ++ ++/** ++ * This is an unfinished experimental feature, and is only exposed ++ * here for internal testing purposes. DO NOT USE. ++ * ++ * An array to hold Primitive values. This is used by the embedder to ++ * pass host defined options to the ScriptOptions during compilation. ++ * ++ * This is passed back to the embedder as part of ++ * HostImportDynamicallyCallback for module loading. ++ * ++ */ ++class V8_EXPORT PrimitiveArray { ++ public: ++ static Local New(Isolate* isolate, int length); ++ int Length() const; ++ void Set(int index, Local item); ++ Local Get(int index); ++}; + + /** + * The optional attributes of ScriptOrigin. +@@ -1027,13 +1070,17 @@ class ScriptOrigin { + Local source_map_url = Local(), + Local resource_is_opaque = Local(), + Local is_wasm = Local(), +- Local is_module = Local()); ++ Local is_module = Local() /*, ++ // Backed out for ABI compatibility with V8 6.2 ++ Local host_defined_options = Local() */); + + V8_INLINE Local ResourceName() const; + V8_INLINE Local ResourceLineOffset() const; + V8_INLINE Local ResourceColumnOffset() const; + V8_INLINE Local ScriptID() const; + V8_INLINE Local SourceMapUrl() const; ++ // Backed out for ABI compatibility with V8 6.2 ++ // V8_INLINE Local HostDefinedOptions() const; + V8_INLINE ScriptOriginOptions Options() const { return options_; } + + private: +@@ -1043,6 +1090,8 @@ class ScriptOrigin { + ScriptOriginOptions options_; + Local script_id_; + Local source_map_url_; ++ // Backed out for ABI compatibility with V8 6.2 ++ // Local host_defined_options_; + }; + + /** +@@ -1289,6 +1338,7 @@ class V8_EXPORT ScriptCompiler { + Local resource_column_offset; + ScriptOriginOptions resource_options; + Local source_map_url; ++ // Local host_defined_options; + + // Cached data from previous compilation (if a kConsume*Cache flag is + // set), or hold newly generated cache data (kProduce*Cache flags) are +@@ -6209,8 +6259,8 @@ typedef void (*DeprecatedCallCompletedCallback)(); + * embedder to load a module. This is used as part of the dynamic + * import syntax. + * +- * The referrer is the name of the file which calls the dynamic +- * import. The referrer can be used to resolve the module location. ++ * The referrer contains metadata about the script/module that calls ++ * import. + * + * The specifier is the name of the module that should be imported. + * +@@ -6225,7 +6275,8 @@ typedef void (*DeprecatedCallCompletedCallback)(); + * that exception by returning an empty MaybeLocal. + */ + typedef MaybeLocal (*HostImportModuleDynamicallyCallback)( +- Local context, Local referrer, Local specifier); ++ Local context, Local referrer, ++ Local specifier); + + /** + * PromiseHook with type kInit is called when a new promise is +@@ -9548,7 +9599,9 @@ ScriptOrigin::ScriptOrigin(Local resource_name, + Local script_id, + Local source_map_url, + Local resource_is_opaque, +- Local is_wasm, Local is_module) ++ Local is_wasm, Local is_module /*, ++ // Backed out for ABI compatibility with V8 6.2 ++ Local host_defined_options */) + : resource_name_(resource_name), + resource_line_offset_(resource_line_offset), + resource_column_offset_(resource_column_offset), +@@ -9558,10 +9611,16 @@ ScriptOrigin::ScriptOrigin(Local resource_name, + !is_wasm.IsEmpty() && is_wasm->IsTrue(), + !is_module.IsEmpty() && is_module->IsTrue()), + script_id_(script_id), +- source_map_url_(source_map_url) {} ++ source_map_url_(source_map_url) /*, ++ // Backed out for ABI compatibility with V8 6.2 ++ host_defined_options_(host_defined_options) */ {} + + Local ScriptOrigin::ResourceName() const { return resource_name_; } + ++// Backed out for ABI compatibility with V8 6.2 ++// Local ScriptOrigin::HostDefinedOptions() const { ++// return host_defined_options_; ++// } + + Local ScriptOrigin::ResourceLineOffset() const { + return resource_line_offset_; +@@ -9578,7 +9637,6 @@ Local ScriptOrigin::ScriptID() const { return script_id_; } + + Local ScriptOrigin::SourceMapUrl() const { return source_map_url_; } + +- + ScriptCompiler::Source::Source(Local string, const ScriptOrigin& origin, + CachedData* data) + : source_string(string), +@@ -9587,9 +9645,10 @@ ScriptCompiler::Source::Source(Local string, const ScriptOrigin& origin, + resource_column_offset(origin.ResourceColumnOffset()), + resource_options(origin.Options()), + source_map_url(origin.SourceMapUrl()), ++ // Backed out for ABI compatibility with V8 6.2 ++ // host_defined_options(origin.HostDefinedOptions()), + cached_data(data) {} + +- + ScriptCompiler::Source::Source(Local string, + CachedData* data) + : source_string(string), cached_data(data) {} +diff --git a/src/api.cc b/src/api.cc +index e5ece56783..147ef1f755 100644 +--- a/src/api.cc ++++ b/src/api.cc +@@ -278,6 +278,9 @@ static ScriptOrigin GetScriptOriginForScript(i::Isolate* isolate, + i::Handle script) { + i::Handle scriptName(script->GetNameOrSourceURL(), isolate); + i::Handle source_map_url(script->source_mapping_url(), isolate); ++ // Backed out for ABI compatibility with V8 6.2 ++ // i::Handle host_defined_options(script->host_defined_options(), ++ // isolate); + v8::Isolate* v8_isolate = + reinterpret_cast(script->GetIsolate()); + ScriptOriginOptions options(script->origin_options()); +@@ -290,7 +293,9 @@ static ScriptOrigin GetScriptOriginForScript(i::Isolate* isolate, + Utils::ToLocal(source_map_url), + v8::Boolean::New(v8_isolate, options.IsOpaque()), + v8::Boolean::New(v8_isolate, script->type() == i::Script::TYPE_WASM), +- v8::Boolean::New(v8_isolate, options.IsModule())); ++ v8::Boolean::New(v8_isolate, options.IsModule()) /*, ++ // Backed out for ABI compatibility with V8 6.2 ++ Utils::ToLocal(host_defined_options) */); + return origin; + } + +@@ -2082,6 +2087,23 @@ Local Script::Run() { + RETURN_TO_LOCAL_UNCHECKED(Run(context), Value); + } + ++Local ScriptOrModule::GetResourceName() { ++ i::Handle obj = Utils::OpenHandle(this); ++ i::Isolate* isolate = obj->GetIsolate(); ++ ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); ++ i::Handle val(obj->name(), isolate); ++ return ToApiHandle(val); ++} ++ ++Local ScriptOrModule::GetHostDefinedOptions() { ++ i::Handle obj = Utils::OpenHandle(this); ++ i::Isolate* isolate = obj->GetIsolate(); ++ ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); ++ // Backed out for ABI compatibility with V8 6.2 ++ // i::Handle val(obj->host_defined_options(), isolate); ++ // return ToApiHandle(val); ++ return Local(); ++} + + Local Script::GetUnboundScript() { + i::Handle obj = Utils::OpenHandle(this); +@@ -2089,6 +2111,46 @@ Local Script::GetUnboundScript() { + i::Handle(i::JSFunction::cast(*obj)->shared())); + } + ++// static ++Local PrimitiveArray::New(Isolate* v8_isolate, int length) { ++ i::Isolate* isolate = reinterpret_cast(v8_isolate); ++ ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); ++ Utils::ApiCheck(length >= 0, "v8::PrimitiveArray::New", ++ "length must be equal or greater than zero"); ++ i::Handle array = isolate->factory()->NewFixedArray(length); ++ return ToApiHandle(array); ++} ++ ++int PrimitiveArray::Length() const { ++ i::Handle array = Utils::OpenHandle(this); ++ i::Isolate* isolate = array->GetIsolate(); ++ ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); ++ return array->length(); ++} ++ ++void PrimitiveArray::Set(int index, Local item) { ++ i::Handle array = Utils::OpenHandle(this); ++ i::Isolate* isolate = array->GetIsolate(); ++ ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); ++ Utils::ApiCheck(index >= 0 && index < array->length(), ++ "v8::PrimitiveArray::Set", ++ "index must be greater than or equal to 0 and less than the " ++ "array length"); ++ i::Handle i_item = Utils::OpenHandle(*item); ++ array->set(index, *i_item); ++} ++ ++Local PrimitiveArray::Get(int index) { ++ i::Handle array = Utils::OpenHandle(this); ++ i::Isolate* isolate = array->GetIsolate(); ++ ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); ++ Utils::ApiCheck(index >= 0 && index < array->length(), ++ "v8::PrimitiveArray::Get", ++ "index must be greater than or equal to 0 and less than the " ++ "array length"); ++ i::Handle i_item(array->get(index), isolate); ++ return ToApiHandle(i_item); ++} + + Module::Status Module::GetStatus() const { + i::Handle self = Utils::OpenHandle(this); +@@ -2225,11 +2287,18 @@ MaybeLocal ScriptCompiler::CompileUnboundInternal( + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileScript"); + i::Handle name_obj; + i::Handle source_map_url; ++ // Backed out for ABI compatibility with V8 6.2 ++ // i::Handle host_defined_options = ++ // isolate->factory()->empty_fixed_array(); + int line_offset = 0; + int column_offset = 0; + if (!source->resource_name.IsEmpty()) { + name_obj = Utils::OpenHandle(*(source->resource_name)); + } ++ // Backed out for ABI compatibility with V8 6.2 ++ // if (!source->host_defined_options.IsEmpty()) { ++ // host_defined_options = Utils::OpenHandle(*(source->host_defined_options)); ++ // } + if (!source->resource_line_offset.IsEmpty()) { + line_offset = static_cast(source->resource_line_offset->Value()); + } +@@ -2243,7 +2312,7 @@ MaybeLocal ScriptCompiler::CompileUnboundInternal( + result = i::Compiler::GetSharedFunctionInfoForScript( + str, name_obj, line_offset, column_offset, source->resource_options, + source_map_url, isolate->native_context(), NULL, &script_data, options, +- i::NOT_NATIVES_CODE); ++ i::NOT_NATIVES_CODE /*, host_defined_options */); + has_pending_exception = result.is_null(); + if (has_pending_exception && script_data != NULL) { + // This case won't happen during normal operation; we have compiled +@@ -2508,6 +2577,10 @@ MaybeLocal