WebKit Bugzilla
Attachment 369043 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-20190503212952.patch (text/plain), 51.48 KB, created by
Yusuke Suzuki
on 2019-05-03 21:29:53 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Yusuke Suzuki
Created:
2019-05-03 21:29:53 PDT
Size:
51.48 KB
patch
obsolete
>Subversion Revision: 244946 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index ac70cb61f481bf89008ab6697a6fb2849a56fd7e..15dbe3415463139607076a142290c8e66834c69b 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,67 @@ >+2019-05-03 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!). >+ >+ * 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/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::FunctionExecutable): >+ (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): >+ > 2019-05-03 Yusuke Suzuki <ysuzuki@apple.com> > > [JSC] Need to emit SetLocal if we emit MovHint in DFGByteCodeParser >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/wkbuiltins/builtins_templates.py b/Source/JavaScriptCore/Scripts/wkbuiltins/builtins_templates.py >index 4c293cc297fbe019865c9b1c0415a22768e570b4..b1e391b5b2c9aeb50b16695beb0fd048a8be4755 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 >diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp >index 7b191cd2bec07ce930305cddc27376d8c67f9e5b..f8a7076d96a27616de6e3881a19a291ae159b012 100644 >--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp >+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp >@@ -395,7 +395,7 @@ 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()); >+ setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation(), ownerExecutable); > RETURN_IF_EXCEPTION(throwScope, false); > > for (unsigned i = 0; i < LinkTimeConstantCount; i++) { >@@ -421,7 +421,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, ownerExecutable, ownerExecutable->source())); > } > > m_functionExprs = RefCountedArray<WriteBarrier<FunctionExecutable>>(unlinkedCodeBlock->numberOfFunctionExprs()); >@@ -429,7 +429,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, ownerExecutable, ownerExecutable->source())); > } > > if (unlinkedCodeBlock->hasRareData()) { >@@ -870,7 +870,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* ownerExecutable) > { > VM& vm = *m_vm; > auto scope = DECLARE_THROW_SCOPE(vm); >@@ -880,6 +880,13 @@ void CodeBlock::setConstantRegisters(const Vector<WriteBarrier<Unknown>>& consta > ASSERT(constants.size() == constantsSourceCodeRepresentation.size()); > size_t count = constants.size(); > m_constantRegisters.resizeToFit(count); >+ ScriptExecutable* cachedTopLevelExecutable = nullptr; >+ auto topLevelExecutable = [&] { >+ if (cachedTopLevelExecutable) >+ return cachedTopLevelExecutable; >+ cachedTopLevelExecutable = ownerExecutable->topLevelExecutable(); >+ return cachedTopLevelExecutable; >+ }; > for (size_t i = 0; i < count; i++) { > JSValue constant = constants[i].get(); > >@@ -898,7 +905,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..0192acd24c36500d6bc93e1c3162d7610a279d96 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* ownerExecutable); > > void replaceConstant(int index, JSValue value) > { >diff --git a/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp b/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp >index 61449db642025ff78b119fdb666c2af59d117fad..488d40e58986c01839a393a10953213c82940906 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* parentExecutable, 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, parentExecutable, source, this, intrinsic); > if (overrideLineNumber) > result->setOverrideLineNumber(*overrideLineNumber); > >diff --git a/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h b/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h >index 1b035977a2bad2ca2b35ca298ca572edc5506071..2b986e2d07b3424f707b037f377eb2f805a5c118 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* parentExecutable, 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..03d0b0872aab43af8afafc3c459909b0dfcf186f 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<int, JSTemplateObjectDescriptor*>; > > // 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..0ec49bb684dbba1865c8ad03e37e886cea473db4 100644 >--- a/Source/JavaScriptCore/runtime/FunctionExecutable.cpp >+++ b/Source/JavaScriptCore/runtime/FunctionExecutable.cpp >@@ -42,8 +42,9 @@ namespace JSC { > > const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(FunctionExecutable) }; > >-FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, Intrinsic intrinsic) >+FunctionExecutable::FunctionExecutable(VM& vm, ScriptExecutable* parentExecutable, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, Intrinsic intrinsic) > : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable->isInStrictContext(), unlinkedExecutable->derivedContextType(), false, EvalContextType::None, intrinsic) >+ , m_parentExecutable(vm, this, parentExecutable, WriteBarrier<ScriptExecutable>::MayBeNull) > , m_unlinkedExecutable(vm, this, unlinkedExecutable) > { > RELEASE_ASSERT(!source.isNull()); >@@ -90,7 +91,14 @@ void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor) > 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 +111,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 +123,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 +139,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..ef542155c1a3afed941bf4fb7ee520210a880595 100644 >--- a/Source/JavaScriptCore/runtime/FunctionExecutable.h >+++ b/Source/JavaScriptCore/runtime/FunctionExecutable.h >@@ -48,9 +48,9 @@ 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* parentExecutable, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, Intrinsic intrinsic) > { >- FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, intrinsic); >+ FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, parentExecutable, source, unlinkedExecutable, intrinsic); > executable->finishCreation(vm); > return executable; > } >@@ -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,9 +302,13 @@ class FunctionExecutable final : public ScriptExecutable { > > Box<InlineWatchpointSet> sharedPolyProtoWatchpoint() const { return m_polyProtoWatchpoint; } > >+ ScriptExecutable* parentExecutable() const { return m_parentExecutable.get(); } >+ >+ TemplateObjectMap& ensureTemplateObjectMap(VM&); >+ > private: > friend class ExecutableBase; >- FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, Intrinsic); >+ FunctionExecutable(VM&, ScriptExecutable*, const SourceCode&, UnlinkedFunctionExecutable*, Intrinsic); > > void finishCreation(VM&); > >@@ -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 parent pointer. First time, setting parent. If RareData is required, materialize RareData, swap it, and store >+ // parent pointer inside RareData. > std::unique_ptr<RareData> m_rareData; >+ WriteBarrier<ScriptExecutable> m_parentExecutable; > 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..6b59354e20cf70597aa8767c2f4a8645ddebfc58 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); >@@ -92,7 +102,11 @@ void ModuleProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor) > Base::visitChildren(thisObject, 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..5192df9c01139c30f3ed137c3b356f908900c4dd 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,60 @@ Exception* ScriptExecutable::prepareForExecutionImpl( > return nullptr; > } > >+ScriptExecutable* ScriptExecutable::topLevelExecutable() >+{ >+ ScriptExecutable* current = this; >+ while (true) { >+ switch (current->type()) { >+ case FunctionExecutableType: { >+ FunctionExecutable* functionExecutable = jsCast<FunctionExecutable*>(current); >+ ScriptExecutable* parentExecutable = functionExecutable->parentExecutable(); >+ if (!parentExecutable) >+ return functionExecutable; >+ current = parentExecutable; >+ break; >+ } >+ default: >+ return current; >+ } >+ } >+} >+ >+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..d11ceac8ff9e0de959f4f7f1956d7b796a4482eb 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); > }
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