WebKit Bugzilla
Attachment 369074 Details for
Bug 190756
: TemplateObject passed to template literal tags are not always identical for the same source location.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-190756-20190504155335.patch (text/plain), 71.22 KB, created by
Yusuke Suzuki
on 2019-05-04 15:53:36 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Yusuke Suzuki
Created:
2019-05-04 15:53:36 PDT
Size:
71.22 KB
patch
obsolete
>Subversion Revision: 244950 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 7d960395584de6aa830c033c9f0c21d4162c62f6..0f239caa014f0c687e523aa38100b0fa69dc65e0 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,90 @@ >+2019-05-04 Yusuke Suzuki <ysuzuki@apple.com> >+ >+ TemplateObject passed to template literal tags are not always identical for the same source location. >+ https://bugs.webkit.org/show_bug.cgi?id=190756 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Tagged template literal requires that the site object is allocated per source location. Previously, we create the site object >+ when linking CodeBlock and cache it in CodeBlock. But this is wrong because, >+ >+ 1. CodeBlock can be jettisoned and regenerated. So every time CodeBlock is regenerated, we get the different site object. >+ 2. Call and Construct can have different CodeBlock. Even if the function is called in call-form or construct-form, we should return the same site object. >+ >+ In this patch, we start caching these site objects in the top-level ScriptExecutable, this matches the spec's per source location since the only one top-level >+ ScriptExecutable is created for the given script code. Each ScriptExecutable of JSFunction can be created multiple times because CodeBlock creates it. >+ But the top-level one is not created by CodeBlock. This top-level ScriptExecutable is well-aligned to the Script itself. The top-level ScriptExecutable has now HashMap, >+ which maps source locations to cached site objects. >+ >+ 1. This patch threads the top-level ScriptExecutable to each FunctionExecutable creation. Each FunctionExecutable has a reference to the top-level ScriptExecutable. >+ 2. We put TemplateObjectMap in ScriptExecutable, which manages cached template objects. >+ 3. We move FunctionExecutable::m_cachedPolyProtoStructure to the FunctionExecutable::RareDate to keep FunctionExecutable 128 bytes. >+ >+ * Scripts/tests/builtins/expected/JavaScriptCore-Builtin.Promise-Combined.js-result: >+ * Scripts/tests/builtins/expected/JavaScriptCore-Builtin.Promise-Separate.js-result: >+ * Scripts/tests/builtins/expected/JavaScriptCore-Builtin.prototype-Combined.js-result: >+ * Scripts/tests/builtins/expected/JavaScriptCore-Builtin.prototype-Separate.js-result: >+ * Scripts/tests/builtins/expected/JavaScriptCore-BuiltinConstructor-Combined.js-result: >+ * Scripts/tests/builtins/expected/JavaScriptCore-BuiltinConstructor-Separate.js-result: >+ * Scripts/tests/builtins/expected/JavaScriptCore-InternalClashingNames-Combined.js-result: >+ * Scripts/tests/builtins/expected/WebCore-AnotherGuardedInternalBuiltin-Separate.js-result: >+ * Scripts/tests/builtins/expected/WebCore-ArbitraryConditionalGuard-Separate.js-result: >+ * Scripts/tests/builtins/expected/WebCore-GuardedBuiltin-Separate.js-result: >+ * Scripts/tests/builtins/expected/WebCore-GuardedInternalBuiltin-Separate.js-result: >+ * Scripts/tests/builtins/expected/WebCore-UnguardedBuiltin-Separate.js-result: >+ * Scripts/tests/builtins/expected/WebCore-xmlCasingTest-Separate.js-result: >+ * Scripts/wkbuiltins/builtins_templates.py: >+ * bytecode/CodeBlock.cpp: >+ (JSC::CodeBlock::finishCreation): >+ (JSC::CodeBlock::setConstantRegisters): >+ * bytecode/CodeBlock.h: >+ * bytecode/UnlinkedFunctionExecutable.cpp: >+ (JSC::UnlinkedFunctionExecutable::link): >+ * bytecode/UnlinkedFunctionExecutable.h: >+ * bytecompiler/BytecodeGenerator.cpp: >+ (JSC::BytecodeGenerator::addTemplateObjectConstant): >+ (JSC::BytecodeGenerator::emitGetTemplateObject): >+ * bytecompiler/BytecodeGenerator.h: >+ * runtime/CachedTypes.cpp: >+ (JSC::CachedTemplateObjectDescriptor::encode): >+ (JSC::CachedTemplateObjectDescriptor::decode const): >+ (JSC::CachedJSValue::encode): >+ (JSC::CachedJSValue::decode const): >+ * runtime/EvalExecutable.cpp: >+ (JSC::EvalExecutable::ensureTemplateObjectMap): >+ (JSC::EvalExecutable::visitChildren): >+ * runtime/EvalExecutable.h: >+ * runtime/FunctionExecutable.cpp: >+ (JSC::FunctionExecutable::finishCreation): >+ (JSC::FunctionExecutable::visitChildren): >+ (JSC::FunctionExecutable::fromGlobalCode): >+ (JSC::FunctionExecutable::ensureRareDataSlow): >+ (JSC::FunctionExecutable::ensureTemplateObjectMap): >+ * runtime/FunctionExecutable.h: >+ * runtime/JSModuleRecord.cpp: >+ (JSC::JSModuleRecord::instantiateDeclarations): >+ * runtime/JSTemplateObjectDescriptor.cpp: >+ (JSC::JSTemplateObjectDescriptor::JSTemplateObjectDescriptor): >+ (JSC::JSTemplateObjectDescriptor::create): >+ * runtime/JSTemplateObjectDescriptor.h: >+ * runtime/ModuleProgramExecutable.cpp: >+ (JSC::ModuleProgramExecutable::ensureTemplateObjectMap): >+ (JSC::ModuleProgramExecutable::visitChildren): >+ * runtime/ModuleProgramExecutable.h: >+ * runtime/ProgramExecutable.cpp: >+ (JSC::ProgramExecutable::ensureTemplateObjectMap): >+ (JSC::ProgramExecutable::visitChildren): >+ * runtime/ProgramExecutable.h: >+ * runtime/ScriptExecutable.cpp: >+ (JSC::ScriptExecutable::topLevelExecutable): >+ (JSC::ScriptExecutable::createTemplateObject): >+ (JSC::ScriptExecutable::ensureTemplateObjectMap): >+ * runtime/ScriptExecutable.h: >+ * tools/JSDollarVM.cpp: >+ (JSC::functionCreateBuiltin): >+ (JSC::functionDeleteAllCodeWhenIdle): >+ (JSC::JSDollarVM::finishCreation): >+ > 2019-05-04 Tadeu Zagallo <tzagallo@apple.com> > > TypedArrays should not store properties that are canonical numeric indices >diff --git a/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-Builtin.Promise-Combined.js-result b/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-Builtin.Promise-Combined.js-result >index 8ab7656c47349c86acefc8d125dbfc0c65c4f5ca..8d30ca908f337f4e6f668cf4701b76436009e0d4 100644 >--- a/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-Builtin.Promise-Combined.js-result >+++ b/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-Builtin.Promise-Combined.js-result >@@ -141,7 +141,7 @@ s_JSCCombinedCode + 412 > #define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \ > JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \ > {\ >- return vm.builtinExecutables()->codeName##Executable()->link(vm, vm.builtinExecutables()->codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); } >+ return vm.builtinExecutables()->codeName##Executable()->link(vm, nullptr, vm.builtinExecutables()->codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); } > JSC_FOREACH_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR) > #undef DEFINE_BUILTIN_GENERATOR > >diff --git a/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-Builtin.Promise-Separate.js-result b/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-Builtin.Promise-Separate.js-result >index bcedfb9cb8c44d77946cff857a684ac19f6ca05d..048a6011bfaa783601dca1090224ab74a0ed1676 100644 >--- a/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-Builtin.Promise-Separate.js-result >+++ b/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-Builtin.Promise-Separate.js-result >@@ -158,7 +158,7 @@ const char* const s_builtinPromiseFulfillPromiseCode = > #define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \ > JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \ > {\ >- return vm.builtinExecutables()->codeName##Executable()->link(vm, vm.builtinExecutables()->codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); } >+ return vm.builtinExecutables()->codeName##Executable()->link(vm, nullptr, vm.builtinExecutables()->codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); } > JSC_FOREACH_BUILTIN.PROMISE_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR) > #undef DEFINE_BUILTIN_GENERATOR > >diff --git a/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-Builtin.prototype-Combined.js-result b/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-Builtin.prototype-Combined.js-result >index 215ec8eff998bdce458de12dd4c16cec88d31841..3dedbe198d5241ef8eb21191c21b731de8d4acfa 100644 >--- a/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-Builtin.prototype-Combined.js-result >+++ b/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-Builtin.prototype-Combined.js-result >@@ -167,7 +167,7 @@ s_JSCCombinedCode + 2694 > #define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \ > JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \ > {\ >- return vm.builtinExecutables()->codeName##Executable()->link(vm, vm.builtinExecutables()->codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); } >+ return vm.builtinExecutables()->codeName##Executable()->link(vm, nullptr, vm.builtinExecutables()->codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); } > JSC_FOREACH_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR) > #undef DEFINE_BUILTIN_GENERATOR > >diff --git a/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-Builtin.prototype-Separate.js-result b/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-Builtin.prototype-Separate.js-result >index ebb2e720bdb4933f4ca9d8f7c47e97aebd1550fe..8ff897fca92c80fa653e2791fdcf9df3ab52a63d 100644 >--- a/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-Builtin.prototype-Separate.js-result >+++ b/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-Builtin.prototype-Separate.js-result >@@ -282,7 +282,7 @@ const char* const s_builtinPrototypeTestCode = > #define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \ > JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \ > {\ >- return vm.builtinExecutables()->codeName##Executable()->link(vm, vm.builtinExecutables()->codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); } >+ return vm.builtinExecutables()->codeName##Executable()->link(vm, nullptr, vm.builtinExecutables()->codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); } > JSC_FOREACH_BUILTIN.PROTOTYPE_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR) > #undef DEFINE_BUILTIN_GENERATOR > >diff --git a/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-BuiltinConstructor-Combined.js-result b/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-BuiltinConstructor-Combined.js-result >index be3a59a3a2dd51d89a5753fa4482d7fbede05d9c..1d8345fee9ccc99e15dbf7ab2dc10b8143cae2c7 100644 >--- a/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-BuiltinConstructor-Combined.js-result >+++ b/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-BuiltinConstructor-Combined.js-result >@@ -139,7 +139,7 @@ s_JSCCombinedCode + 2046 > #define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \ > JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \ > {\ >- return vm.builtinExecutables()->codeName##Executable()->link(vm, vm.builtinExecutables()->codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); } >+ return vm.builtinExecutables()->codeName##Executable()->link(vm, nullptr, vm.builtinExecutables()->codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); } > JSC_FOREACH_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR) > #undef DEFINE_BUILTIN_GENERATOR > >diff --git a/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-BuiltinConstructor-Separate.js-result b/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-BuiltinConstructor-Separate.js-result >index 454861fd17f6529f49a56230ab5f0b3cff070cba..a6ddd91fd06717d47f03ab054f2f459f7972a2b7 100644 >--- a/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-BuiltinConstructor-Separate.js-result >+++ b/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-BuiltinConstructor-Separate.js-result >@@ -212,7 +212,7 @@ const char* const s_builtinConstructorFromCode = > #define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \ > JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \ > {\ >- return vm.builtinExecutables()->codeName##Executable()->link(vm, vm.builtinExecutables()->codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); } >+ return vm.builtinExecutables()->codeName##Executable()->link(vm, nullptr, vm.builtinExecutables()->codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); } > JSC_FOREACH_BUILTINCONSTRUCTOR_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR) > #undef DEFINE_BUILTIN_GENERATOR > >diff --git a/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-InternalClashingNames-Combined.js-result b/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-InternalClashingNames-Combined.js-result >index bfb2b2ec6bcf1b87465ae272b24afd4786b99942..b5feac2908c06326ccbf9f11c5de793137d15283 100644 >--- a/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-InternalClashingNames-Combined.js-result >+++ b/Source/JavaScriptCore/Scripts/tests/builtins/expected/JavaScriptCore-InternalClashingNames-Combined.js-result >@@ -140,7 +140,7 @@ s_JSCCombinedCode + 71 > #define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \ > JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \ > {\ >- return vm.builtinExecutables()->codeName##Executable()->link(vm, vm.builtinExecutables()->codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); } >+ return vm.builtinExecutables()->codeName##Executable()->link(vm, nullptr, vm.builtinExecutables()->codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); } > JSC_FOREACH_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR) > #undef DEFINE_BUILTIN_GENERATOR > >diff --git a/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-AnotherGuardedInternalBuiltin-Separate.js-result b/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-AnotherGuardedInternalBuiltin-Separate.js-result >index e46d23ad976fa0665545de1b69f9caedddb7dd17..043a993034f6625afc2e65b68beceb6da0fb2242 100644 >--- a/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-AnotherGuardedInternalBuiltin-Separate.js-result >+++ b/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-AnotherGuardedInternalBuiltin-Separate.js-result >@@ -220,7 +220,7 @@ const char* const s_anotherGuardedInternalBuiltinLetsFetchCode = > JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \ > {\ > JSVMClientData* clientData = static_cast<JSVMClientData*>(vm.clientData); \ >- return clientData->builtinFunctions().anotherGuardedInternalBuiltinBuiltins().codeName##Executable()->link(vm, clientData->builtinFunctions().anotherGuardedInternalBuiltinBuiltins().codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \ >+ return clientData->builtinFunctions().anotherGuardedInternalBuiltinBuiltins().codeName##Executable()->link(vm, nullptr, clientData->builtinFunctions().anotherGuardedInternalBuiltinBuiltins().codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \ > } > WEBCORE_FOREACH_ANOTHERGUARDEDINTERNALBUILTIN_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR) > #undef DEFINE_BUILTIN_GENERATOR >diff --git a/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-ArbitraryConditionalGuard-Separate.js-result b/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-ArbitraryConditionalGuard-Separate.js-result >index be0709a34ea6c52f5d60aa49f8f094e23c9320bd..a42fcfb8271f27dc8dfe5d6f39ebdf7fd6e37e05 100644 >--- a/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-ArbitraryConditionalGuard-Separate.js-result >+++ b/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-ArbitraryConditionalGuard-Separate.js-result >@@ -190,7 +190,7 @@ const char* const s_arbitraryConditionalGuardIsReadableStreamLockedCode = > JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \ > {\ > JSVMClientData* clientData = static_cast<JSVMClientData*>(vm.clientData); \ >- return clientData->builtinFunctions().arbitraryConditionalGuardBuiltins().codeName##Executable()->link(vm, clientData->builtinFunctions().arbitraryConditionalGuardBuiltins().codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \ >+ return clientData->builtinFunctions().arbitraryConditionalGuardBuiltins().codeName##Executable()->link(vm, nullptr, clientData->builtinFunctions().arbitraryConditionalGuardBuiltins().codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \ > } > WEBCORE_FOREACH_ARBITRARYCONDITIONALGUARD_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR) > #undef DEFINE_BUILTIN_GENERATOR >diff --git a/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-GuardedBuiltin-Separate.js-result b/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-GuardedBuiltin-Separate.js-result >index 5567dfa921fbd1f7fe087eeb8fc1ee06e0ff362c..5896e07d69319a077ccb98a0870b19fabc458a6a 100644 >--- a/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-GuardedBuiltin-Separate.js-result >+++ b/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-GuardedBuiltin-Separate.js-result >@@ -190,7 +190,7 @@ const char* const s_guardedBuiltinIsReadableStreamLockedCode = > JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \ > {\ > JSVMClientData* clientData = static_cast<JSVMClientData*>(vm.clientData); \ >- return clientData->builtinFunctions().guardedBuiltinBuiltins().codeName##Executable()->link(vm, clientData->builtinFunctions().guardedBuiltinBuiltins().codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \ >+ return clientData->builtinFunctions().guardedBuiltinBuiltins().codeName##Executable()->link(vm, nullptr, clientData->builtinFunctions().guardedBuiltinBuiltins().codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \ > } > WEBCORE_FOREACH_GUARDEDBUILTIN_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR) > #undef DEFINE_BUILTIN_GENERATOR >diff --git a/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-GuardedInternalBuiltin-Separate.js-result b/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-GuardedInternalBuiltin-Separate.js-result >index 6adaf32c7e1a5bf1e0c9314b7a864230539eba04..cc191ed9fbf25c7a50b8011b82699c95fea182c5 100644 >--- a/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-GuardedInternalBuiltin-Separate.js-result >+++ b/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-GuardedInternalBuiltin-Separate.js-result >@@ -222,7 +222,7 @@ const char* const s_guardedInternalBuiltinIsReadableStreamLockedCode = > JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \ > {\ > JSVMClientData* clientData = static_cast<JSVMClientData*>(vm.clientData); \ >- return clientData->builtinFunctions().guardedInternalBuiltinBuiltins().codeName##Executable()->link(vm, clientData->builtinFunctions().guardedInternalBuiltinBuiltins().codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \ >+ return clientData->builtinFunctions().guardedInternalBuiltinBuiltins().codeName##Executable()->link(vm, nullptr, clientData->builtinFunctions().guardedInternalBuiltinBuiltins().codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \ > } > WEBCORE_FOREACH_GUARDEDINTERNALBUILTIN_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR) > #undef DEFINE_BUILTIN_GENERATOR >diff --git a/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-UnguardedBuiltin-Separate.js-result b/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-UnguardedBuiltin-Separate.js-result >index 8bc20fbddc24e4078bf77730ffbc2b3ab7f0ee2d..0c091eb831aa509bd9c01567b8f172f011123f93 100644 >--- a/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-UnguardedBuiltin-Separate.js-result >+++ b/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-UnguardedBuiltin-Separate.js-result >@@ -184,7 +184,7 @@ const char* const s_unguardedBuiltinIsReadableStreamLockedCode = > JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \ > {\ > JSVMClientData* clientData = static_cast<JSVMClientData*>(vm.clientData); \ >- return clientData->builtinFunctions().unguardedBuiltinBuiltins().codeName##Executable()->link(vm, clientData->builtinFunctions().unguardedBuiltinBuiltins().codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \ >+ return clientData->builtinFunctions().unguardedBuiltinBuiltins().codeName##Executable()->link(vm, nullptr, clientData->builtinFunctions().unguardedBuiltinBuiltins().codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \ > } > WEBCORE_FOREACH_UNGUARDEDBUILTIN_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR) > #undef DEFINE_BUILTIN_GENERATOR >diff --git a/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-xmlCasingTest-Separate.js-result b/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-xmlCasingTest-Separate.js-result >index 02d4417473d9bc4e79a1567e1d3afdedaa572e97..fe2eff5bae5a06f7d766c4b468a5284a923370a0 100644 >--- a/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-xmlCasingTest-Separate.js-result >+++ b/Source/JavaScriptCore/Scripts/tests/builtins/expected/WebCore-xmlCasingTest-Separate.js-result >@@ -275,7 +275,7 @@ const char* const s_xmlCasingTestUrlCasingTestCode = > JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \ > {\ > JSVMClientData* clientData = static_cast<JSVMClientData*>(vm.clientData); \ >- return clientData->builtinFunctions().xmlCasingTestBuiltins().codeName##Executable()->link(vm, clientData->builtinFunctions().xmlCasingTestBuiltins().codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \ >+ return clientData->builtinFunctions().xmlCasingTestBuiltins().codeName##Executable()->link(vm, nullptr, clientData->builtinFunctions().xmlCasingTestBuiltins().codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \ > } > WEBCORE_FOREACH_XMLCASINGTEST_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR) > #undef DEFINE_BUILTIN_GENERATOR >diff --git a/Source/JavaScriptCore/Scripts/wkbuiltins/builtins_templates.py b/Source/JavaScriptCore/Scripts/wkbuiltins/builtins_templates.py >index 4c293cc297fbe019865c9b1c0415a22768e570b4..3665cb5eb678abaf41c67e808621c09f794f6f01 100644 >--- a/Source/JavaScriptCore/Scripts/wkbuiltins/builtins_templates.py >+++ b/Source/JavaScriptCore/Scripts/wkbuiltins/builtins_templates.py >@@ -85,7 +85,7 @@ class BuiltinsGeneratorTemplates: > #define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \\ > JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \\ > {\\ >- return vm.builtinExecutables()->codeName##Executable()->link(vm, vm.builtinExecutables()->codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \ >+ return vm.builtinExecutables()->codeName##Executable()->link(vm, nullptr, vm.builtinExecutables()->codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \ > } > ${macroPrefix}_FOREACH_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR) > #undef DEFINE_BUILTIN_GENERATOR >@@ -96,7 +96,7 @@ class BuiltinsGeneratorTemplates: > #define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \\ > JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \\ > {\\ >- return vm.builtinExecutables()->codeName##Executable()->link(vm, vm.builtinExecutables()->codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \ >+ return vm.builtinExecutables()->codeName##Executable()->link(vm, nullptr, vm.builtinExecutables()->codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \ > } > ${macroPrefix}_FOREACH_${objectMacro}_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR) > #undef DEFINE_BUILTIN_GENERATOR >@@ -108,7 +108,7 @@ class BuiltinsGeneratorTemplates: > JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \\ > {\\ > JSVMClientData* clientData = static_cast<JSVMClientData*>(vm.clientData); \\ >- return clientData->builtinFunctions().${objectNameLC}Builtins().codeName##Executable()->link(vm, clientData->builtinFunctions().${objectNameLC}Builtins().codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \\ >+ return clientData->builtinFunctions().${objectNameLC}Builtins().codeName##Executable()->link(vm, nullptr, clientData->builtinFunctions().${objectNameLC}Builtins().codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \\ > } > ${macroPrefix}_FOREACH_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR) > #undef DEFINE_BUILTIN_GENERATOR >@@ -120,7 +120,7 @@ class BuiltinsGeneratorTemplates: > JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \\ > {\\ > JSVMClientData* clientData = static_cast<JSVMClientData*>(vm.clientData); \\ >- return clientData->builtinFunctions().${objectNameLC}Builtins().codeName##Executable()->link(vm, clientData->builtinFunctions().${objectNameLC}Builtins().codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \\ >+ return clientData->builtinFunctions().${objectNameLC}Builtins().codeName##Executable()->link(vm, nullptr, clientData->builtinFunctions().${objectNameLC}Builtins().codeName##Source(), WTF::nullopt, s_##codeName##Intrinsic); \\ > } > ${macroPrefix}_FOREACH_${objectMacro}_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR) > #undef DEFINE_BUILTIN_GENERATOR >diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp >index 7b191cd2bec07ce930305cddc27376d8c67f9e5b..46f3ed72ac1193594622d59ab53b1bd49d0b7536 100644 >--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp >+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp >@@ -395,7 +395,8 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink > if (m_unlinkedCode->wasCompiledWithTypeProfilerOpcodes() || m_unlinkedCode->wasCompiledWithControlFlowProfilerOpcodes()) > vm.functionHasExecutedCache()->removeUnexecutedRange(ownerExecutable->sourceID(), ownerExecutable->typeProfilingStartOffset(vm), ownerExecutable->typeProfilingEndOffset(vm)); > >- setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation()); >+ ScriptExecutable* topLevelExecutable = ownerExecutable->topLevelExecutable(); >+ setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation(), topLevelExecutable); > RETURN_IF_EXCEPTION(throwScope, false); > > for (unsigned i = 0; i < LinkTimeConstantCount; i++) { >@@ -421,7 +422,7 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink > UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i); > if (shouldUpdateFunctionHasExecutedCache) > vm.functionHasExecutedCache()->insertUnexecutedRange(ownerExecutable->sourceID(), unlinkedExecutable->typeProfilingStartOffset(), unlinkedExecutable->typeProfilingEndOffset()); >- m_functionDecls[i].set(vm, this, unlinkedExecutable->link(vm, ownerExecutable->source())); >+ m_functionDecls[i].set(vm, this, unlinkedExecutable->link(vm, topLevelExecutable, ownerExecutable->source())); > } > > m_functionExprs = RefCountedArray<WriteBarrier<FunctionExecutable>>(unlinkedCodeBlock->numberOfFunctionExprs()); >@@ -429,7 +430,7 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink > UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionExpr(i); > if (shouldUpdateFunctionHasExecutedCache) > vm.functionHasExecutedCache()->insertUnexecutedRange(ownerExecutable->sourceID(), unlinkedExecutable->typeProfilingStartOffset(), unlinkedExecutable->typeProfilingEndOffset()); >- m_functionExprs[i].set(vm, this, unlinkedExecutable->link(vm, ownerExecutable->source())); >+ m_functionExprs[i].set(vm, this, unlinkedExecutable->link(vm, topLevelExecutable, ownerExecutable->source())); > } > > if (unlinkedCodeBlock->hasRareData()) { >@@ -870,7 +871,7 @@ void CodeBlock::setConstantIdentifierSetRegisters(VM& vm, const Vector<ConstantI > } > } > >-void CodeBlock::setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants, const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation) >+void CodeBlock::setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants, const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation, ScriptExecutable* topLevelExecutable) > { > VM& vm = *m_vm; > auto scope = DECLARE_THROW_SCOPE(vm); >@@ -898,7 +899,7 @@ void CodeBlock::setConstantRegisters(const Vector<WriteBarrier<Unknown>>& consta > > constant = clone; > } else if (auto* descriptor = jsDynamicCast<JSTemplateObjectDescriptor*>(vm, cell)) { >- auto* templateObject = descriptor->createTemplateObject(exec); >+ auto* templateObject = topLevelExecutable->createTemplateObject(exec, descriptor); > RETURN_IF_EXCEPTION(scope, void()); > constant = templateObject; > } >diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h >index 12f9082765813b5de76aeb6b8d941f2cb950ba66..406fca08a123df10d70f69e1368bfc32224b6626 100644 >--- a/Source/JavaScriptCore/bytecode/CodeBlock.h >+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h >@@ -911,7 +911,7 @@ class CodeBlock : public JSCell { > > void setConstantIdentifierSetRegisters(VM&, const Vector<ConstantIdentifierSetEntry>& constants); > >- void setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants, const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation); >+ void setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants, const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation, ScriptExecutable* topLevelExecutable); > > void replaceConstant(int index, JSValue value) > { >diff --git a/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp b/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp >index 61449db642025ff78b119fdb666c2af59d117fad..5e7148ebbc853c576b8bbb1c5a6f8ed669be7a08 100644 >--- a/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp >+++ b/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp >@@ -158,7 +158,7 @@ SourceCode UnlinkedFunctionExecutable::linkedSourceCode(const SourceCode& passed > return SourceCode(parentSource.provider(), startOffset, startOffset + m_sourceLength, firstLine, startColumn); > } > >-FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& passedParentSource, Optional<int> overrideLineNumber, Intrinsic intrinsic) >+FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, ScriptExecutable* topLevelExecutable, const SourceCode& passedParentSource, Optional<int> overrideLineNumber, Intrinsic intrinsic) > { > SourceCode source = linkedSourceCode(passedParentSource); > FunctionOverrides::OverrideInfo overrideInfo; >@@ -166,7 +166,7 @@ FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& p > if (UNLIKELY(Options::functionOverrides())) > hasFunctionOverride = FunctionOverrides::initializeOverrideFor(source, overrideInfo); > >- FunctionExecutable* result = FunctionExecutable::create(vm, source, this, intrinsic); >+ FunctionExecutable* result = FunctionExecutable::create(vm, topLevelExecutable, source, this, intrinsic); > if (overrideLineNumber) > result->setOverrideLineNumber(*overrideLineNumber); > >diff --git a/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h b/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h >index 1b035977a2bad2ca2b35ca298ca572edc5506071..8e0abed5c26ae5c66acf941eb0429b6fbe3f0cc0 100644 >--- a/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h >+++ b/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h >@@ -126,7 +126,7 @@ class UnlinkedFunctionExecutable final : public JSCell { > int overrideLineNumber, Optional<int> functionConstructorParametersEndPosition); > > SourceCode linkedSourceCode(const SourceCode&) const; >- JS_EXPORT_PRIVATE FunctionExecutable* link(VM&, const SourceCode& parentSource, Optional<int> overrideLineNumber = WTF::nullopt, Intrinsic = NoIntrinsic); >+ JS_EXPORT_PRIVATE FunctionExecutable* link(VM&, ScriptExecutable* topLevelExecutable, const SourceCode& parentSource, Optional<int> overrideLineNumber = WTF::nullopt, Intrinsic = NoIntrinsic); > > void clearCode(VM& vm) > { >diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >index 35409a6904b04e8675083c0a25b9d34c076cc98d..94de182e73f8a8578640aeaa75e15481810ad7d6 100644 >--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >@@ -2948,12 +2948,12 @@ JSString* BytecodeGenerator::addStringConstant(const Identifier& identifier) > return stringInMap; > } > >-RegisterID* BytecodeGenerator::addTemplateObjectConstant(Ref<TemplateObjectDescriptor>&& descriptor) >+RegisterID* BytecodeGenerator::addTemplateObjectConstant(Ref<TemplateObjectDescriptor>&& descriptor, int startOffset) > { >- JSTemplateObjectDescriptor* descriptorValue = m_templateObjectDescriptorMap.ensure(descriptor.copyRef(), [&] { >- return JSTemplateObjectDescriptor::create(*vm(), WTFMove(descriptor)); >+ auto result = m_templateObjectDescriptorSet.add(WTFMove(descriptor)); >+ JSTemplateObjectDescriptor* descriptorValue = m_templateDescriptorMap.ensure(startOffset, [&] { >+ return JSTemplateObjectDescriptor::create(*vm(), result.iterator->copyRef(), startOffset); > }).iterator->value; >- > int index = addConstantIndex(); > m_codeBlock->addConstant(descriptorValue); > return &m_constantPoolRegisters[index]; >@@ -4141,7 +4141,7 @@ RegisterID* BytecodeGenerator::emitGetTemplateObject(RegisterID* dst, TaggedTemp > else > cookedStrings.append(string->cooked()->impl()); > } >- RefPtr<RegisterID> constant = addTemplateObjectConstant(TemplateObjectDescriptor::create(WTFMove(rawStrings), WTFMove(cookedStrings))); >+ RefPtr<RegisterID> constant = addTemplateObjectConstant(TemplateObjectDescriptor::create(WTFMove(rawStrings), WTFMove(cookedStrings)), taggedTemplate->startOffset()); > if (!dst) > return constant.get(); > return move(dst, constant.get()); >diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >index 4426b515c432e18f65e884e8be8cb3c8d4b483b1..29ed39aad87ce09f31ff13581f86fe08aab07568 100644 >--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >@@ -1060,7 +1060,8 @@ namespace JSC { > using NumberMap = HashMap<double, JSValue>; > using IdentifierStringMap = HashMap<UniquedStringImpl*, JSString*, IdentifierRepHash>; > using IdentifierBigIntMap = HashMap<BigIntMapEntry, JSBigInt*>; >- using TemplateObjectDescriptorMap = HashMap<Ref<TemplateObjectDescriptor>, JSTemplateObjectDescriptor*>; >+ using TemplateObjectDescriptorSet = HashSet<Ref<TemplateObjectDescriptor>>; >+ using TemplateDescriptorMap = HashMap<uint64_t, JSTemplateObjectDescriptor*, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>; > > // Helper for emitCall() and emitConstruct(). This works because the set of > // expected functions have identical behavior for both call and construct >@@ -1152,7 +1153,7 @@ namespace JSC { > public: > JSString* addStringConstant(const Identifier&); > JSValue addBigIntConstant(const Identifier&, uint8_t radix, bool sign); >- RegisterID* addTemplateObjectConstant(Ref<TemplateObjectDescriptor>&&); >+ RegisterID* addTemplateObjectConstant(Ref<TemplateObjectDescriptor>&&, int); > > const InstructionStream& instructions() const { return m_writer; } > >@@ -1270,7 +1271,8 @@ namespace JSC { > JSValueMap m_jsValueMap; > IdentifierStringMap m_stringMap; > IdentifierBigIntMap m_bigIntMap; >- TemplateObjectDescriptorMap m_templateObjectDescriptorMap; >+ TemplateObjectDescriptorSet m_templateObjectDescriptorSet; >+ TemplateDescriptorMap m_templateDescriptorMap; > > StaticPropertyAnalyzer m_staticPropertyAnalyzer; > >diff --git a/Source/JavaScriptCore/runtime/CachedTypes.cpp b/Source/JavaScriptCore/runtime/CachedTypes.cpp >index 93f2224efb0c0c1e802cbfcbaa3744f3b8eaf600..7a971835dfdc71653c58b268b18d877e3f187157 100644 >--- a/Source/JavaScriptCore/runtime/CachedTypes.cpp >+++ b/Source/JavaScriptCore/runtime/CachedTypes.cpp >@@ -1152,24 +1152,26 @@ class CachedRegExp : public CachedObject<RegExp> { > > class CachedTemplateObjectDescriptor : public CachedObject<TemplateObjectDescriptor> { > public: >- void encode(Encoder& encoder, const TemplateObjectDescriptor& templateObjectDescriptor) >+ void encode(Encoder& encoder, const JSTemplateObjectDescriptor& descriptor) > { >- m_rawStrings.encode(encoder, templateObjectDescriptor.rawStrings()); >- m_cookedStrings.encode(encoder, templateObjectDescriptor.cookedStrings()); >+ m_rawStrings.encode(encoder, descriptor.descriptor().rawStrings()); >+ m_cookedStrings.encode(encoder, descriptor.descriptor().cookedStrings()); >+ m_startOffset = descriptor.startOffset(); > } > >- Ref<TemplateObjectDescriptor> decode(Decoder& decoder) const >+ JSTemplateObjectDescriptor* decode(Decoder& decoder) const > { > TemplateObjectDescriptor::StringVector decodedRawStrings; > TemplateObjectDescriptor::OptionalStringVector decodedCookedStrings; > m_rawStrings.decode(decoder, decodedRawStrings); > m_cookedStrings.decode(decoder, decodedCookedStrings); >- return TemplateObjectDescriptor::create(WTFMove(decodedRawStrings), WTFMove(decodedCookedStrings)); >+ return JSTemplateObjectDescriptor::create(decoder.vm(), TemplateObjectDescriptor::create(WTFMove(decodedRawStrings), WTFMove(decodedCookedStrings)), m_startOffset); > } > > private: > CachedVector<CachedString, 4> m_rawStrings; > CachedVector<CachedOptional<CachedString>, 4> m_cookedStrings; >+ int m_startOffset; > }; > > class CachedBigInt : public VariableLengthObject<JSBigInt> { >@@ -1243,7 +1245,7 @@ class CachedJSValue : public VariableLengthObject<WriteBarrier<Unknown>> { > > if (auto* templateObjectDescriptor = jsDynamicCast<JSTemplateObjectDescriptor*>(vm, cell)) { > m_type = EncodedType::TemplateObjectDescriptor; >- this->allocate<CachedTemplateObjectDescriptor>(encoder)->encode(encoder, templateObjectDescriptor->descriptor()); >+ this->allocate<CachedTemplateObjectDescriptor>(encoder)->encode(encoder, *templateObjectDescriptor); > return; > } > >@@ -1278,7 +1280,7 @@ class CachedJSValue : public VariableLengthObject<WriteBarrier<Unknown>> { > v = this->buffer<CachedRegExp>()->decode(decoder); > break; > case EncodedType::TemplateObjectDescriptor: >- v = JSTemplateObjectDescriptor::create(decoder.vm(), this->buffer<CachedTemplateObjectDescriptor>()->decode(decoder)); >+ v = this->buffer<CachedTemplateObjectDescriptor>()->decode(decoder); > break; > case EncodedType::BigInt: > v = this->buffer<CachedBigInt>()->decode(decoder); >diff --git a/Source/JavaScriptCore/runtime/EvalExecutable.cpp b/Source/JavaScriptCore/runtime/EvalExecutable.cpp >index 28c7f76a7ac807f45464055e4a3b42c98ce4e210..f6ddacf3cca41c16dde154f1333930c9ebea40d1 100644 >--- a/Source/JavaScriptCore/runtime/EvalExecutable.cpp >+++ b/Source/JavaScriptCore/runtime/EvalExecutable.cpp >@@ -44,6 +44,16 @@ void EvalExecutable::destroy(JSCell* cell) > static_cast<EvalExecutable*>(cell)->EvalExecutable::~EvalExecutable(); > } > >+auto EvalExecutable::ensureTemplateObjectMap(VM&) -> TemplateObjectMap& >+{ >+ if (m_templateObjectMap) >+ return *m_templateObjectMap; >+ auto result = std::make_unique<TemplateObjectMap>(); >+ WTF::storeStoreFence(); >+ m_templateObjectMap = WTFMove(result); >+ return *m_templateObjectMap; >+} >+ > void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor) > { > EvalExecutable* thisObject = jsCast<EvalExecutable*>(cell); >@@ -51,6 +61,11 @@ void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor) > Base::visitChildren(thisObject, visitor); > visitor.append(thisObject->m_unlinkedEvalCodeBlock); > visitor.append(thisObject->m_evalCodeBlock); >+ if (TemplateObjectMap* map = thisObject->m_templateObjectMap.get()) { >+ auto locker = holdLock(thisObject->cellLock()); >+ for (auto& entry : *map) >+ visitor.append(entry.value); >+ } > } > > } // namespace JSC >diff --git a/Source/JavaScriptCore/runtime/EvalExecutable.h b/Source/JavaScriptCore/runtime/EvalExecutable.h >index b9cb74d1a80c0ffcdf35647aaa9dad26bf5691d6..57b7a35f43201b9f127728ebc7bfe72d4d1ef46b 100644 >--- a/Source/JavaScriptCore/runtime/EvalExecutable.h >+++ b/Source/JavaScriptCore/runtime/EvalExecutable.h >@@ -69,6 +69,8 @@ class EvalExecutable : public GlobalExecutable { > unsigned numTopLevelFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); } > bool allowDirectEvalCache() const { return m_unlinkedEvalCodeBlock->allowDirectEvalCache(); } > >+ TemplateObjectMap& ensureTemplateObjectMap(VM&); >+ > protected: > friend class ExecutableBase; > friend class ScriptExecutable; >@@ -80,6 +82,7 @@ class EvalExecutable : public GlobalExecutable { > > WriteBarrier<ExecutableToCodeBlockEdge> m_evalCodeBlock; > WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock; >+ std::unique_ptr<TemplateObjectMap> m_templateObjectMap; > }; > > } // namespace JSC >diff --git a/Source/JavaScriptCore/runtime/FunctionExecutable.cpp b/Source/JavaScriptCore/runtime/FunctionExecutable.cpp >index 2e85f4764713b22169ca7e0d271fe1ebd18ff6d1..753405bad104cc80404d3e81c6dec441b6ba41b4 100644 >--- a/Source/JavaScriptCore/runtime/FunctionExecutable.cpp >+++ b/Source/JavaScriptCore/runtime/FunctionExecutable.cpp >@@ -54,9 +54,10 @@ FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, Unlinke > m_singletonFunctionState = ClearWatchpoint; > } > >-void FunctionExecutable::finishCreation(VM& vm) >+void FunctionExecutable::finishCreation(VM& vm, ScriptExecutable* topLevelExecutable) > { > Base::finishCreation(vm); >+ m_topLevelExecutable.set(vm, this, topLevelExecutable ? topLevelExecutable : this); > if (VM::canUseJIT()) > m_singletonFunction.set(vm, this, InferredValue::create(vm)); > } >@@ -85,12 +86,20 @@ void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor) > FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell); > ASSERT_GC_OBJECT_INHERITS(thisObject, info()); > Base::visitChildren(thisObject, visitor); >+ visitor.append(thisObject->m_topLevelExecutable); > visitor.append(thisObject->m_codeBlockForCall); > visitor.append(thisObject->m_codeBlockForConstruct); > visitor.append(thisObject->m_unlinkedExecutable); > if (VM::canUseJIT()) > visitor.append(thisObject->m_singletonFunction); >- visitor.append(thisObject->m_cachedPolyProtoStructure); >+ if (RareData* rareData = thisObject->m_rareData.get()) { >+ visitor.append(rareData->m_cachedPolyProtoStructure); >+ if (TemplateObjectMap* map = rareData->m_templateObjectMap.get()) { >+ auto locker = holdLock(thisObject->cellLock()); >+ for (auto& entry : *map) >+ visitor.append(entry.value); >+ } >+ } > } > > FunctionExecutable* FunctionExecutable::fromGlobalCode( >@@ -103,7 +112,7 @@ FunctionExecutable* FunctionExecutable::fromGlobalCode( > if (!unlinkedExecutable) > return nullptr; > >- return unlinkedExecutable->link(exec.vm(), source, overrideLineNumber); >+ return unlinkedExecutable->link(exec.vm(), nullptr, source, overrideLineNumber); > } > > FunctionExecutable::RareData& FunctionExecutable::ensureRareDataSlow() >@@ -115,6 +124,7 @@ FunctionExecutable::RareData& FunctionExecutable::ensureRareDataSlow() > rareData->m_parametersStartOffset = parametersStartOffset(); > rareData->m_typeProfilingStartOffset = typeProfilingStartOffset(); > rareData->m_typeProfilingEndOffset = typeProfilingEndOffset(); >+ WTF::storeStoreFence(); > m_rareData = WTFMove(rareData); > return *m_rareData; > } >@@ -130,4 +140,15 @@ void FunctionExecutable::overrideInfo(const FunctionOverrideInfo& overrideInfo) > rareData.m_typeProfilingEndOffset = overrideInfo.typeProfilingEndOffset; > } > >+auto FunctionExecutable::ensureTemplateObjectMap(VM&) -> TemplateObjectMap& >+{ >+ RareData& rareData = ensureRareData(); >+ if (rareData.m_templateObjectMap) >+ return *rareData.m_templateObjectMap.get(); >+ auto result = std::make_unique<TemplateObjectMap>(); >+ WTF::storeStoreFence(); >+ rareData.m_templateObjectMap = WTFMove(result); >+ return *rareData.m_templateObjectMap; >+} >+ > } // namespace JSC >diff --git a/Source/JavaScriptCore/runtime/FunctionExecutable.h b/Source/JavaScriptCore/runtime/FunctionExecutable.h >index 7cfedbd2f49a7ff2966827cbe0a4419000357f08..1063c0af446fc98dfe421361bafd994ffc4ef0d8 100644 >--- a/Source/JavaScriptCore/runtime/FunctionExecutable.h >+++ b/Source/JavaScriptCore/runtime/FunctionExecutable.h >@@ -48,10 +48,10 @@ class FunctionExecutable final : public ScriptExecutable { > return &vm.functionExecutableSpace.space; > } > >- static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, Intrinsic intrinsic) >+ static FunctionExecutable* create(VM& vm, ScriptExecutable* topLevelExecutable, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, Intrinsic intrinsic) > { > FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, intrinsic); >- executable->finishCreation(vm); >+ executable->finishCreation(vm, topLevelExecutable); > return executable; > } > static FunctionExecutable* fromGlobalCode( >@@ -282,8 +282,16 @@ class FunctionExecutable final : public ScriptExecutable { > } > > // Cached poly proto structure for the result of constructing this executable. >- Structure* cachedPolyProtoStructure() { return m_cachedPolyProtoStructure.get(); } >- void setCachedPolyProtoStructure(VM& vm, Structure* structure) { m_cachedPolyProtoStructure.set(vm, this, structure); } >+ Structure* cachedPolyProtoStructure() >+ { >+ if (UNLIKELY(m_rareData)) >+ return m_rareData->m_cachedPolyProtoStructure.get(); >+ return nullptr; >+ } >+ void setCachedPolyProtoStructure(VM& vm, Structure* structure) >+ { >+ ensureRareData().m_cachedPolyProtoStructure.set(vm, this, structure); >+ } > > InlineWatchpointSet& ensurePolyProtoWatchpoint() > { >@@ -294,11 +302,15 @@ class FunctionExecutable final : public ScriptExecutable { > > Box<InlineWatchpointSet> sharedPolyProtoWatchpoint() const { return m_polyProtoWatchpoint; } > >+ ScriptExecutable* topLevelExecutable() const { return m_topLevelExecutable.get(); } >+ >+ TemplateObjectMap& ensureTemplateObjectMap(VM&); >+ > private: > friend class ExecutableBase; > FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, Intrinsic); > >- void finishCreation(VM&); >+ void finishCreation(VM&, ScriptExecutable* topLevelExecutable); > > friend class ScriptExecutable; > >@@ -311,6 +323,8 @@ class FunctionExecutable final : public ScriptExecutable { > unsigned m_parametersStartOffset { 0 }; > unsigned m_typeProfilingStartOffset { UINT_MAX }; > unsigned m_typeProfilingEndOffset { UINT_MAX }; >+ std::unique_ptr<TemplateObjectMap> m_templateObjectMap; >+ WriteBarrier<Structure> m_cachedPolyProtoStructure; > }; > > RareData& ensureRareData() >@@ -321,7 +335,10 @@ class FunctionExecutable final : public ScriptExecutable { > } > RareData& ensureRareDataSlow(); > >+ // FIXME: We can merge rareData pointer and top-level executable pointer. First time, setting parent. If RareData is required, materialize RareData, swap it, and store >+ // top-level executable pointer inside RareData. > std::unique_ptr<RareData> m_rareData; >+ WriteBarrier<ScriptExecutable> m_topLevelExecutable; > WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable; > WriteBarrier<ExecutableToCodeBlockEdge> m_codeBlockForCall; > WriteBarrier<ExecutableToCodeBlockEdge> m_codeBlockForConstruct; >@@ -329,7 +346,6 @@ class FunctionExecutable final : public ScriptExecutable { > WriteBarrier<InferredValue> m_singletonFunction; > WatchpointState m_singletonFunctionState; > }; >- WriteBarrier<Structure> m_cachedPolyProtoStructure; > Box<InlineWatchpointSet> m_polyProtoWatchpoint; > }; > >diff --git a/Source/JavaScriptCore/runtime/JSModuleRecord.cpp b/Source/JavaScriptCore/runtime/JSModuleRecord.cpp >index c55d0d1984a244fd4abd34633faadb36f8f7181f..50057597ef823c3da6a6a519790ad09dbf8385eb 100644 >--- a/Source/JavaScriptCore/runtime/JSModuleRecord.cpp >+++ b/Source/JavaScriptCore/runtime/JSModuleRecord.cpp >@@ -200,7 +200,7 @@ void JSModuleRecord::instantiateDeclarations(ExecState* exec, ModuleProgramExecu > unlinkedFunctionExecutable->typeProfilingStartOffset(), > unlinkedFunctionExecutable->typeProfilingEndOffset()); > } >- JSFunction* function = JSFunction::create(vm, unlinkedFunctionExecutable->link(vm, moduleProgramExecutable->source()), moduleEnvironment); >+ JSFunction* function = JSFunction::create(vm, unlinkedFunctionExecutable->link(vm, moduleProgramExecutable, moduleProgramExecutable->source()), moduleEnvironment); > bool putResult = false; > symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, unlinkedFunctionExecutable->name(), function, /* shouldThrowReadOnlyError */ false, /* ignoreReadOnlyErrors */ true, putResult); > RETURN_IF_EXCEPTION(scope, void()); >diff --git a/Source/JavaScriptCore/runtime/JSTemplateObjectDescriptor.cpp b/Source/JavaScriptCore/runtime/JSTemplateObjectDescriptor.cpp >index 2a4a407fd93191088591e789297fa0b0422c6940..ed165cd0d80688c4e99edd36405459b47093d426 100644 >--- a/Source/JavaScriptCore/runtime/JSTemplateObjectDescriptor.cpp >+++ b/Source/JavaScriptCore/runtime/JSTemplateObjectDescriptor.cpp >@@ -36,15 +36,16 @@ namespace JSC { > const ClassInfo JSTemplateObjectDescriptor::s_info = { "TemplateObjectDescriptor", nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(JSTemplateObjectDescriptor) }; > > >-JSTemplateObjectDescriptor::JSTemplateObjectDescriptor(VM& vm, Ref<TemplateObjectDescriptor>&& descriptor) >+JSTemplateObjectDescriptor::JSTemplateObjectDescriptor(VM& vm, Ref<TemplateObjectDescriptor>&& descriptor, int startOffset) > : Base(vm, vm.templateObjectDescriptorStructure.get()) > , m_descriptor(WTFMove(descriptor)) >+ , m_startOffset(startOffset) > { > } > >-JSTemplateObjectDescriptor* JSTemplateObjectDescriptor::create(VM& vm, Ref<TemplateObjectDescriptor>&& descriptor) >+JSTemplateObjectDescriptor* JSTemplateObjectDescriptor::create(VM& vm, Ref<TemplateObjectDescriptor>&& descriptor, int startOffset) > { >- JSTemplateObjectDescriptor* result = new (NotNull, allocateCell<JSTemplateObjectDescriptor>(vm.heap)) JSTemplateObjectDescriptor(vm, WTFMove(descriptor)); >+ JSTemplateObjectDescriptor* result = new (NotNull, allocateCell<JSTemplateObjectDescriptor>(vm.heap)) JSTemplateObjectDescriptor(vm, WTFMove(descriptor), startOffset); > result->finishCreation(vm); > return result; > } >diff --git a/Source/JavaScriptCore/runtime/JSTemplateObjectDescriptor.h b/Source/JavaScriptCore/runtime/JSTemplateObjectDescriptor.h >index 75208bc162282b08aa2d93683535f503e718730c..0005be6be238fcc09907aed6366911ed18ab2c96 100644 >--- a/Source/JavaScriptCore/runtime/JSTemplateObjectDescriptor.h >+++ b/Source/JavaScriptCore/runtime/JSTemplateObjectDescriptor.h >@@ -38,7 +38,7 @@ class JSTemplateObjectDescriptor final : public JSCell { > static const bool needsDestruction = true; > DECLARE_INFO; > >- static JSTemplateObjectDescriptor* create(VM&, Ref<TemplateObjectDescriptor>&&); >+ static JSTemplateObjectDescriptor* create(VM&, Ref<TemplateObjectDescriptor>&&, int); > > static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) > { >@@ -49,13 +49,16 @@ class JSTemplateObjectDescriptor final : public JSCell { > > JSArray* createTemplateObject(ExecState*); > >+ int startOffset() const { return m_startOffset; } >+ > protected: > static void destroy(JSCell*); > > private: >- JSTemplateObjectDescriptor(VM&, Ref<TemplateObjectDescriptor>&&); >+ JSTemplateObjectDescriptor(VM&, Ref<TemplateObjectDescriptor>&&, int); > > Ref<TemplateObjectDescriptor> m_descriptor; >+ int m_startOffset { 0 }; > }; > > } // namespace JSC >diff --git a/Source/JavaScriptCore/runtime/ModuleProgramExecutable.cpp b/Source/JavaScriptCore/runtime/ModuleProgramExecutable.cpp >index 4373b6478c42bbd20f0ebd12ee6c3584586e8d93..6cd726f4ebae38223920e8d3ae6e91fa1bf928f9 100644 >--- a/Source/JavaScriptCore/runtime/ModuleProgramExecutable.cpp >+++ b/Source/JavaScriptCore/runtime/ModuleProgramExecutable.cpp >@@ -85,6 +85,16 @@ void ModuleProgramExecutable::destroy(JSCell* cell) > static_cast<ModuleProgramExecutable*>(cell)->ModuleProgramExecutable::~ModuleProgramExecutable(); > } > >+auto ModuleProgramExecutable::ensureTemplateObjectMap(VM&) -> TemplateObjectMap& >+{ >+ if (m_templateObjectMap) >+ return *m_templateObjectMap; >+ auto result = std::make_unique<TemplateObjectMap>(); >+ WTF::storeStoreFence(); >+ m_templateObjectMap = WTFMove(result); >+ return *m_templateObjectMap; >+} >+ > void ModuleProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor) > { > ModuleProgramExecutable* thisObject = jsCast<ModuleProgramExecutable*>(cell); >@@ -93,6 +103,11 @@ void ModuleProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor) > visitor.append(thisObject->m_unlinkedModuleProgramCodeBlock); > visitor.append(thisObject->m_moduleEnvironmentSymbolTable); > visitor.append(thisObject->m_moduleProgramCodeBlock); >+ if (TemplateObjectMap* map = thisObject->m_templateObjectMap.get()) { >+ auto locker = holdLock(thisObject->cellLock()); >+ for (auto& entry : *map) >+ visitor.append(entry.value); >+ } > } > > } // namespace JSC >diff --git a/Source/JavaScriptCore/runtime/ModuleProgramExecutable.h b/Source/JavaScriptCore/runtime/ModuleProgramExecutable.h >index 6d355b7bd6b9f98ef7d6c9092b32251bf079be6d..f9b7e2adbfe85295a2e489d52f491305bfdd3227 100644 >--- a/Source/JavaScriptCore/runtime/ModuleProgramExecutable.h >+++ b/Source/JavaScriptCore/runtime/ModuleProgramExecutable.h >@@ -69,6 +69,8 @@ class ModuleProgramExecutable final : public GlobalExecutable { > > SymbolTable* moduleEnvironmentSymbolTable() { return m_moduleEnvironmentSymbolTable.get(); } > >+ TemplateObjectMap& ensureTemplateObjectMap(VM&); >+ > private: > friend class ExecutableBase; > friend class ScriptExecutable; >@@ -80,6 +82,7 @@ class ModuleProgramExecutable final : public GlobalExecutable { > WriteBarrier<UnlinkedModuleProgramCodeBlock> m_unlinkedModuleProgramCodeBlock; > WriteBarrier<SymbolTable> m_moduleEnvironmentSymbolTable; > WriteBarrier<ExecutableToCodeBlockEdge> m_moduleProgramCodeBlock; >+ std::unique_ptr<TemplateObjectMap> m_templateObjectMap; > }; > > } // namespace JSC >diff --git a/Source/JavaScriptCore/runtime/ProgramExecutable.cpp b/Source/JavaScriptCore/runtime/ProgramExecutable.cpp >index 91054164caa86175bcac2a308869c3f8892ebff5..9450ec231c4d555ad19afe3897b38280a6d43645 100644 >--- a/Source/JavaScriptCore/runtime/ProgramExecutable.cpp >+++ b/Source/JavaScriptCore/runtime/ProgramExecutable.cpp >@@ -216,6 +216,16 @@ JSObject* ProgramExecutable::initializeGlobalProperties(VM& vm, CallFrame* callF > return nullptr; > } > >+auto ProgramExecutable::ensureTemplateObjectMap(VM&) -> TemplateObjectMap& >+{ >+ if (m_templateObjectMap) >+ return *m_templateObjectMap; >+ auto result = std::make_unique<TemplateObjectMap>(); >+ WTF::storeStoreFence(); >+ m_templateObjectMap = WTFMove(result); >+ return *m_templateObjectMap; >+} >+ > void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor) > { > ProgramExecutable* thisObject = jsCast<ProgramExecutable*>(cell); >@@ -223,6 +233,11 @@ void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor) > Base::visitChildren(thisObject, visitor); > visitor.append(thisObject->m_unlinkedProgramCodeBlock); > visitor.append(thisObject->m_programCodeBlock); >+ if (TemplateObjectMap* map = thisObject->m_templateObjectMap.get()) { >+ auto locker = holdLock(thisObject->cellLock()); >+ for (auto& entry : *map) >+ visitor.append(entry.value); >+ } > } > > } // namespace JSC >diff --git a/Source/JavaScriptCore/runtime/ProgramExecutable.h b/Source/JavaScriptCore/runtime/ProgramExecutable.h >index 60511679bf2c93768a8acf664b285bdc607bed4e..b96844456a372522c254ff87850a7d05d75d8c8f 100644 >--- a/Source/JavaScriptCore/runtime/ProgramExecutable.h >+++ b/Source/JavaScriptCore/runtime/ProgramExecutable.h >@@ -73,6 +73,8 @@ class ProgramExecutable final : public GlobalExecutable { > > ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, JSParserScriptMode::Classic, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext(), false, EvalContextType::None); } > >+ TemplateObjectMap& ensureTemplateObjectMap(VM&); >+ > private: > friend class ExecutableBase; > friend class ScriptExecutable; >@@ -83,6 +85,7 @@ class ProgramExecutable final : public GlobalExecutable { > > WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock; > WriteBarrier<ExecutableToCodeBlockEdge> m_programCodeBlock; >+ std::unique_ptr<TemplateObjectMap> m_templateObjectMap; > }; > > } // namespace JSC >diff --git a/Source/JavaScriptCore/runtime/ScriptExecutable.cpp b/Source/JavaScriptCore/runtime/ScriptExecutable.cpp >index 56a5d4876c90831d299b8de13e61d195f85316e5..679e1d2a5c95f24b3f7584a9287aa29f1b00ca58 100644 >--- a/Source/JavaScriptCore/runtime/ScriptExecutable.cpp >+++ b/Source/JavaScriptCore/runtime/ScriptExecutable.cpp >@@ -34,6 +34,7 @@ > #include "IsoCellSetInlines.h" > #include "JIT.h" > #include "JSCInlines.h" >+#include "JSTemplateObjectDescriptor.h" > #include "LLIntEntrypoint.h" > #include "ModuleProgramCodeBlock.h" > #include "Parser.h" >@@ -435,6 +436,51 @@ Exception* ScriptExecutable::prepareForExecutionImpl( > return nullptr; > } > >+ScriptExecutable* ScriptExecutable::topLevelExecutable() >+{ >+ switch (type()) { >+ case FunctionExecutableType: >+ return jsCast<FunctionExecutable*>(this)->topLevelExecutable(); >+ default: >+ return this; >+ } >+} >+ >+JSArray* ScriptExecutable::createTemplateObject(ExecState* exec, JSTemplateObjectDescriptor* descriptor) >+{ >+ VM& vm = exec->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ TemplateObjectMap& templateObjectMap = ensureTemplateObjectMap(vm); >+ TemplateObjectMap::AddResult result; >+ { >+ auto locker = holdLock(cellLock()); >+ result = templateObjectMap.add(descriptor->startOffset(), WriteBarrier<JSArray>()); >+ } >+ if (!result.isNewEntry) >+ return result.iterator->value.get(); >+ JSArray* templateObject = descriptor->createTemplateObject(exec); >+ RETURN_IF_EXCEPTION(scope, nullptr); >+ result.iterator->value.set(vm, this, templateObject); >+ return templateObject; >+} >+ >+auto ScriptExecutable::ensureTemplateObjectMap(VM& vm) -> TemplateObjectMap& >+{ >+ switch (type()) { >+ case FunctionExecutableType: >+ return static_cast<FunctionExecutable*>(this)->ensureTemplateObjectMap(vm); >+ case EvalExecutableType: >+ return static_cast<EvalExecutable*>(this)->ensureTemplateObjectMap(vm); >+ case ProgramExecutableType: >+ return static_cast<ProgramExecutable*>(this)->ensureTemplateObjectMap(vm); >+ case ModuleProgramExecutableType: >+ default: >+ ASSERT(type() == ModuleProgramExecutableType); >+ return static_cast<ModuleProgramExecutable*>(this)->ensureTemplateObjectMap(vm); >+ } >+} >+ > CodeBlockHash ScriptExecutable::hashFor(CodeSpecializationKind kind) const > { > return CodeBlockHash(source(), kind); >diff --git a/Source/JavaScriptCore/runtime/ScriptExecutable.h b/Source/JavaScriptCore/runtime/ScriptExecutable.h >index 6c3eecc850237cc7f67ee30b47909efc8b9dd2ac..2b71b4a7e7915d97d3c7b8e1580a77eb8e66c773 100644 >--- a/Source/JavaScriptCore/runtime/ScriptExecutable.h >+++ b/Source/JavaScriptCore/runtime/ScriptExecutable.h >@@ -29,6 +29,8 @@ > > namespace JSC { > >+class JSArray; >+class JSTemplateObjectDescriptor; > class IsoCellSet; > > class ScriptExecutable : public ExecutableBase { >@@ -37,6 +39,8 @@ class ScriptExecutable : public ExecutableBase { > static const unsigned StructureFlags = Base::StructureFlags; > > static void destroy(JSCell*); >+ >+ using TemplateObjectMap = HashMap<uint64_t, WriteBarrier<JSArray>, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>; > > CodeBlockHash hashFor(CodeSpecializationKind) const; > >@@ -112,12 +116,17 @@ class ScriptExecutable : public ExecutableBase { > template <typename ExecutableType> > Exception* prepareForExecution(VM&, JSFunction*, JSScope*, CodeSpecializationKind, CodeBlock*& resultCodeBlock); > >+ ScriptExecutable* topLevelExecutable(); >+ JSArray* createTemplateObject(ExecState*, JSTemplateObjectDescriptor*); >+ > private: > friend class ExecutableBase; > Exception* prepareForExecutionImpl(VM&, JSFunction*, JSScope*, CodeSpecializationKind, CodeBlock*&); > > bool hasClearableCode(VM&) const; > >+ TemplateObjectMap& ensureTemplateObjectMap(VM&); >+ > protected: > ScriptExecutable(Structure*, VM&, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isInArrowFunctionContext, EvalContextType, Intrinsic); > >diff --git a/Source/JavaScriptCore/tools/JSDollarVM.cpp b/Source/JavaScriptCore/tools/JSDollarVM.cpp >index d624a70316cb9a2f8163f73f773e227533b11a31..1458d04be4ad5b7163094b0c407f0837d03de5d8 100644 >--- a/Source/JavaScriptCore/tools/JSDollarVM.cpp >+++ b/Source/JavaScriptCore/tools/JSDollarVM.cpp >@@ -1846,7 +1846,7 @@ static EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState* exec) > RETURN_IF_EXCEPTION(scope, encodedJSValue()); > > const SourceCode& source = makeSource(functionText, { }); >- JSFunction* func = JSFunction::create(vm, createBuiltinExecutable(vm, source, Identifier::fromString(&vm, "foo"), ConstructorKind::None, ConstructAbility::CannotConstruct)->link(vm, source), exec->lexicalGlobalObject()); >+ JSFunction* func = JSFunction::create(vm, createBuiltinExecutable(vm, source, Identifier::fromString(&vm, "foo"), ConstructorKind::None, ConstructAbility::CannotConstruct)->link(vm, nullptr, source), exec->lexicalGlobalObject()); > > return JSValue::encode(func); > } >@@ -2087,6 +2087,15 @@ static EncodedJSValue JSC_HOST_CALL functionDisableDebuggerModeWhenIdle(ExecStat > return changeDebuggerModeWhenIdle(exec, { }); > } > >+static EncodedJSValue JSC_HOST_CALL functionDeleteAllCodeWhenIdle(ExecState* exec) >+{ >+ VM* vm = &exec->vm(); >+ vm->whenIdle([=] () { >+ vm->deleteAllCode(PreventCollectionAndDeleteAllCode); >+ }); >+ return JSValue::encode(jsUndefined()); >+} >+ > static EncodedJSValue JSC_HOST_CALL functionGlobalObjectCount(ExecState* exec) > { > return JSValue::encode(jsNumber(exec->vm().heap.globalObjectCount())); >@@ -2276,6 +2285,8 @@ void JSDollarVM::finishCreation(VM& vm) > addFunction(vm, "enableDebuggerModeWhenIdle", functionEnableDebuggerModeWhenIdle, 0); > addFunction(vm, "disableDebuggerModeWhenIdle", functionDisableDebuggerModeWhenIdle, 0); > >+ addFunction(vm, "deleteAllCodeWhenIdle", functionDeleteAllCodeWhenIdle, 0); >+ > addFunction(vm, "globalObjectCount", functionGlobalObjectCount, 0); > addFunction(vm, "globalObjectForObject", functionGlobalObjectForObject, 1); > >diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog >index c2316a6960e6628407f9cdb7dc3efee2b59cc899..9d255f434df81bee528aa33b75f99395907be4fe 100644 >--- a/JSTests/ChangeLog >+++ b/JSTests/ChangeLog >@@ -1,3 +1,41 @@ >+2019-05-04 Yusuke Suzuki <ysuzuki@apple.com> >+ >+ TemplateObject passed to template literal tags are not always identical for the same source location. >+ https://bugs.webkit.org/show_bug.cgi?id=190756 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * complex.yaml: >+ * complex/tagged-template-regeneration-after.js: Added. >+ (shouldBe): >+ * complex/tagged-template-regeneration.js: Added. >+ (call): >+ (test): >+ * modules/tagged-template-inside-module.js: Added. >+ (from.string_appeared_here.call): >+ * modules/tagged-template-inside-module/other-tagged-templates.js: Added. >+ (call): >+ (export.otherTaggedTemplates): >+ * stress/call-and-construct-should-return-same-tagged-templates.js: Added. >+ (shouldBe): >+ (call): >+ (poly): >+ * stress/tagged-templates-in-direct-eval-should-not-produce-same-site-object.js: Added. >+ (shouldBe): >+ (call): >+ * stress/tagged-templates-in-global-function-should-not-produce-same-site-object.js: Added. >+ (shouldBe): >+ (call): >+ * stress/tagged-templates-in-indirect-eval-should-not-produce-same-site-object.js: Added. >+ (shouldBe): >+ (call): >+ * stress/tagged-templates-in-multiple-functions.js: Added. >+ (shouldBe): >+ (call): >+ (a): >+ (b): >+ (c): >+ > 2019-05-04 Tadeu Zagallo <tzagallo@apple.com> > > TypedArrays should not store properties that are canonical numeric indices >diff --git a/JSTests/complex.yaml b/JSTests/complex.yaml >index ce038f4d6242cde75752e5ac22390fa0198831d2..10613507a2ef781be44fcb6adc0d989aab9aa703 100644 >--- a/JSTests/complex.yaml >+++ b/JSTests/complex.yaml >@@ -25,3 +25,6 @@ > > - path: complex/generator-regeneration.js > cmd: runComplexTest [], ["generator-regeneration-after.js"], "--useDollarVM=1" >+ >+- path: complex/tagged-template-regeneration.js >+ cmd: runComplexTest [], ["tagged-template-regeneration-after.js"], "--useDollarVM=1" >diff --git a/JSTests/complex/tagged-template-regeneration-after.js b/JSTests/complex/tagged-template-regeneration-after.js >new file mode 100644 >index 0000000000000000000000000000000000000000..6fc7f02fd65184cc265405fbab58bd106efae485 >--- /dev/null >+++ b/JSTests/complex/tagged-template-regeneration-after.js >@@ -0,0 +1,7 @@ >+function shouldBe(actual, expected) { >+ if (actual !== expected) >+ throw new Error('bad value: ' + actual); >+} >+ >+var second = test(); >+shouldBe(first, second); >diff --git a/JSTests/complex/tagged-template-regeneration.js b/JSTests/complex/tagged-template-regeneration.js >new file mode 100644 >index 0000000000000000000000000000000000000000..ec52ab631fb7f9d95c06d6c9ae6a32b082833f02 >--- /dev/null >+++ b/JSTests/complex/tagged-template-regeneration.js >@@ -0,0 +1,13 @@ >+function call(site) >+{ >+ return site; >+} >+ >+function test() >+{ >+ return call`Cocoa`; >+} >+ >+var first = test(); >+$vm.deleteAllCodeWhenIdle(); >+fullGC(); >diff --git a/JSTests/modules/tagged-template-inside-module.js b/JSTests/modules/tagged-template-inside-module.js >new file mode 100644 >index 0000000000000000000000000000000000000000..aa747fc2613cd85b5bd11e3f8998c66a78649cd1 >--- /dev/null >+++ b/JSTests/modules/tagged-template-inside-module.js >@@ -0,0 +1,11 @@ >+import { shouldThrow, shouldBe } from "./resources/assert.js"; >+import { otherTaggedTemplates } from "./tagged-template-inside-module/other-tagged-templates.js" >+ >+function call(site) { >+ return site; >+} >+ >+var template = otherTaggedTemplates(); >+shouldBe(call`Cocoa` !== template, true); >+shouldBe(template, otherTaggedTemplates()); >+shouldBe(template, new otherTaggedTemplates()); >diff --git a/JSTests/modules/tagged-template-inside-module/other-tagged-templates.js b/JSTests/modules/tagged-template-inside-module/other-tagged-templates.js >new file mode 100644 >index 0000000000000000000000000000000000000000..5d167a3087e7501e7231bc23241f1de4b509d57e >--- /dev/null >+++ b/JSTests/modules/tagged-template-inside-module/other-tagged-templates.js >@@ -0,0 +1,9 @@ >+function call(site) >+{ >+ return site; >+} >+ >+export function otherTaggedTemplates() >+{ >+ return call`Cocoa`; >+} >diff --git a/JSTests/stress/call-and-construct-should-return-same-tagged-templates.js b/JSTests/stress/call-and-construct-should-return-same-tagged-templates.js >new file mode 100644 >index 0000000000000000000000000000000000000000..8338ce5d8e28eb9d5824763985749a93020b37c0 >--- /dev/null >+++ b/JSTests/stress/call-and-construct-should-return-same-tagged-templates.js >@@ -0,0 +1,20 @@ >+function shouldBe(actual, expected) >+{ >+ if (actual !== expected) >+ throw new Error('bad value: ' + actual); >+} >+ >+function call(site) >+{ >+ return site; >+} >+ >+function poly() >+{ >+ return call`Cocoa`; >+} >+ >+var first = poly(); >+var second = new poly(); >+ >+shouldBe(first, second); >diff --git a/JSTests/stress/tagged-templates-in-direct-eval-should-not-produce-same-site-object.js b/JSTests/stress/tagged-templates-in-direct-eval-should-not-produce-same-site-object.js >new file mode 100644 >index 0000000000000000000000000000000000000000..fa4876043d9a4a0751c15c8d666d3a7ec8ecfeb0 >--- /dev/null >+++ b/JSTests/stress/tagged-templates-in-direct-eval-should-not-produce-same-site-object.js >@@ -0,0 +1,14 @@ >+function shouldBe(actual, expected) { >+ if (actual !== expected) >+ throw new Error('bad value: ' + actual); >+} >+ >+function call(site) >+{ >+ return site; >+} >+ >+var expr = "call`Cocoa`"; >+var first = eval(expr); >+var second = eval(expr); >+shouldBe(first !== second, true); >diff --git a/JSTests/stress/tagged-templates-in-global-function-should-not-produce-same-site-object.js b/JSTests/stress/tagged-templates-in-global-function-should-not-produce-same-site-object.js >new file mode 100644 >index 0000000000000000000000000000000000000000..53e76ed1f30b52fd9ac0bd2f30e9d7ef010c6368 >--- /dev/null >+++ b/JSTests/stress/tagged-templates-in-global-function-should-not-produce-same-site-object.js >@@ -0,0 +1,21 @@ >+function shouldBe(actual, expected) { >+ if (actual !== expected) >+ throw new Error('bad value: ' + actual); >+} >+ >+function call(site) >+{ >+ return site; >+} >+ >+var expr = "return call`Cocoa`"; >+var firstFunction = Function(expr); >+var secondFunction = Function(expr); >+var first = firstFunction(); >+var second = secondFunction(); >+shouldBe(first !== second, true); >+ >+shouldBe(first, firstFunction()); >+shouldBe(first, new firstFunction()); >+shouldBe(second, secondFunction()); >+shouldBe(second, new secondFunction()); >diff --git a/JSTests/stress/tagged-templates-in-indirect-eval-should-not-produce-same-site-object.js b/JSTests/stress/tagged-templates-in-indirect-eval-should-not-produce-same-site-object.js >new file mode 100644 >index 0000000000000000000000000000000000000000..aeacb1b5efaea4ef70e9a95f4dfc942757cc9c40 >--- /dev/null >+++ b/JSTests/stress/tagged-templates-in-indirect-eval-should-not-produce-same-site-object.js >@@ -0,0 +1,15 @@ >+function shouldBe(actual, expected) { >+ if (actual !== expected) >+ throw new Error('bad value: ' + actual); >+} >+ >+var indirectEval = eval; >+function call(site) >+{ >+ return site; >+} >+ >+var expr = "call`Cocoa`"; >+var first = indirectEval(expr); >+var second = indirectEval(expr); >+shouldBe(first !== second, true); >diff --git a/JSTests/stress/tagged-templates-in-multiple-functions.js b/JSTests/stress/tagged-templates-in-multiple-functions.js >new file mode 100644 >index 0000000000000000000000000000000000000000..3828f53b1b2f661674b49e1c32c1a59d2b9c0436 >--- /dev/null >+++ b/JSTests/stress/tagged-templates-in-multiple-functions.js >@@ -0,0 +1,33 @@ >+function shouldBe(actual, expected) >+{ >+ if (actual !== expected) >+ throw new Error('bad value: ' + actual); >+} >+ >+function call(site) >+{ >+ return site; >+} >+ >+function a() >+{ >+ return call`Cocoa`; >+} >+ >+function b() >+{ >+ return call`Cocoa`; >+} >+ >+function c() >+{ >+ return [ call`Cocoa`, call`Cocoa` ]; >+} >+ >+shouldBe(a() !== b(), true); >+shouldBe(a() === a(), true); >+shouldBe(b() === b(), true); >+var result = c(); >+shouldBe(c()[0] === result[0], true); >+shouldBe(c()[1] === result[1], true); >+shouldBe(result[0] !== result[1], true);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 190756
:
369041
|
369042
|
369043
|
369047
|
369049
|
369058
|
369066
|
369074
|
369081
|
369324