Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (282623 => 282624)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2021-09-17 00:53:50 UTC (rev 282623)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2021-09-17 01:04:59 UTC (rev 282624)
@@ -377,6 +377,8 @@
Base::finishCreation(vm);
finishCreationCommon(vm);
+ ASSERT(vm.heap.isDeferred());
+
auto throwScope = DECLARE_THROW_SCOPE(vm);
if (m_unlinkedCode->wasCompiledWithTypeProfilerOpcodes() || m_unlinkedCode->wasCompiledWithControlFlowProfilerOpcodes())
@@ -383,8 +385,10 @@
vm.functionHasExecutedCache()->removeUnexecutedRange(ownerExecutable->sourceID(), ownerExecutable->typeProfilingStartOffset(vm), ownerExecutable->typeProfilingEndOffset(vm));
ScriptExecutable* topLevelExecutable = ownerExecutable->topLevelExecutable();
- setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation(), topLevelExecutable);
- RETURN_IF_EXCEPTION(throwScope, false);
+ // We wait to initialize template objects until the end of finishCreation beecause it can
+ // throw. We rely on linking to put the CodeBlock into a coherent state, so we can't throw
+ // until we're all done linking.
+ Vector<unsigned> templateObjectIndices = setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation());
// We already have the cloned symbol table for the module environment since we need to instantiate
// the module environments before linking the code block. We replace the stored symbol table with the already cloned one.
@@ -435,7 +439,8 @@
// Bookkeep the strongly referenced module environments.
HashSet<JSModuleEnvironment*> stronglyReferencedModuleEnvironments;
- auto link_profile = [&](const auto& /*instruction*/, auto /*bytecode*/, auto& /*metadata*/) {
+ auto link_profile = [&](const auto& /*instruction*/, auto /*bytecode*/, auto& metadata) {
+ static_assert(std::is_same_v<ValueProfile, decltype(metadata.m_profile)>);
m_numberOfNonArgumentValueProfiles++;
};
@@ -499,9 +504,9 @@
LINK(OpGetById, profile)
- LINK(OpEnumeratorNext, profile)
- LINK(OpEnumeratorInByVal, profile)
- LINK(OpEnumeratorHasOwnProperty, profile)
+ LINK(OpEnumeratorNext)
+ LINK(OpEnumeratorInByVal)
+ LINK(OpEnumeratorHasOwnProperty)
LINK(OpEnumeratorGetByVal, profile)
LINK(OpCall, profile)
@@ -563,7 +568,6 @@
RELEASE_ASSERT(bytecode.m_resolveType != ResolvedClosureVar);
ResolveOp op = JSScope::abstractResolve(m_globalObject.get(), bytecode.m_localScopeDepth, scope, ident, Get, bytecode.m_resolveType, InitializationMode::NotInitialization);
- RETURN_IF_EXCEPTION(throwScope, false);
metadata.m_resolveType = op.type;
metadata.m_localScopeDepth = op.depth;
@@ -598,7 +602,6 @@
const Identifier& ident = identifier(bytecode.m_var);
ResolveOp op = JSScope::abstractResolve(m_globalObject.get(), bytecode.m_localScopeDepth, scope, ident, Get, bytecode.m_getPutInfo.resolveType(), InitializationMode::NotInitialization);
- RETURN_IF_EXCEPTION(throwScope, false);
metadata.m_getPutInfo = GetPutInfo(bytecode.m_getPutInfo.resolveMode(), op.type, bytecode.m_getPutInfo.initializationMode(), bytecode.m_getPutInfo.ecmaMode());
if (op.type == ModuleVar)
@@ -632,7 +635,6 @@
const Identifier& ident = identifier(bytecode.m_var);
metadata.m_watchpointSet = nullptr;
ResolveOp op = JSScope::abstractResolve(m_globalObject.get(), bytecode.m_symbolTableOrScopeDepth.scopeDepth(), scope, ident, Put, bytecode.m_getPutInfo.resolveType(), bytecode.m_getPutInfo.initializationMode());
- RETURN_IF_EXCEPTION(throwScope, false);
metadata.m_getPutInfo = GetPutInfo(bytecode.m_getPutInfo.resolveMode(), op.type, bytecode.m_getPutInfo.initializationMode(), bytecode.m_getPutInfo.ecmaMode());
if (op.type == GlobalVar || op.type == GlobalVarWithVarInjectionChecks || op.type == GlobalLexicalVar || op.type == GlobalLexicalVarWithVarInjectionChecks)
@@ -665,7 +667,6 @@
// Even though type profiling may be profiling either a Get or a Put, we can always claim a Get because
// we're abstractly "read"ing from a JSScope.
ResolveOp op = JSScope::abstractResolve(m_globalObject.get(), localScopeDepth, scope, ident, Get, bytecode.m_resolveType, InitializationMode::NotInitialization);
- RETURN_IF_EXCEPTION(throwScope, false);
if (op.type == ClosureVar || op.type == ModuleVar)
symbolTable = op.lexicalEnvironment->symbolTable();
@@ -781,6 +782,9 @@
if (m_metadata)
vm.heap.reportExtraMemoryAllocated(m_metadata->sizeInBytes());
+ initializeTemplateObjects(topLevelExecutable, templateObjectIndices);
+ RETURN_IF_EXCEPTION(throwScope, false);
+
return true;
}
@@ -869,12 +873,13 @@
#endif // ENABLE(JIT)
}
-void CodeBlock::setConstantRegisters(const FixedVector<WriteBarrier<Unknown>>& constants, const FixedVector<SourceCodeRepresentation>& constantsSourceCodeRepresentation, ScriptExecutable* topLevelExecutable)
+Vector<unsigned> CodeBlock::setConstantRegisters(const FixedVector<WriteBarrier<Unknown>>& constants, const FixedVector<SourceCodeRepresentation>& constantsSourceCodeRepresentation)
{
VM& vm = *m_vm;
- auto scope = DECLARE_THROW_SCOPE(vm);
JSGlobalObject* globalObject = m_globalObject.get();
+ Vector<unsigned> templateObjectIndices;
+
ASSERT(constants.size() == constantsSourceCodeRepresentation.size());
size_t count = constants.size();
{
@@ -905,11 +910,8 @@
clone->setRareDataCodeBlock(this);
constant = clone;
- } else if (auto* descriptor = jsDynamicCast<JSTemplateObjectDescriptor*>(vm, cell)) {
- auto* templateObject = topLevelExecutable->createTemplateObject(globalObject, descriptor);
- RETURN_IF_EXCEPTION(scope, void());
- constant = templateObject;
- }
+ } else if (jsDynamicCast<JSTemplateObjectDescriptor*>(vm, cell))
+ templateObjectIndices.append(i);
}
}
break;
@@ -916,8 +918,21 @@
}
m_constantRegisters[i].set(vm, this, constant);
}
+
+ return templateObjectIndices;
}
+void CodeBlock::initializeTemplateObjects(ScriptExecutable* topLevelExecutable, const Vector<unsigned>& templateObjectIndices)
+{
+ auto scope = DECLARE_THROW_SCOPE(vm());
+ for (unsigned i : templateObjectIndices) {
+ auto* descriptor = jsCast<JSTemplateObjectDescriptor*>(m_constantRegisters[i].get());
+ auto* templateObject = topLevelExecutable->createTemplateObject(globalObject(), descriptor);
+ RETURN_IF_EXCEPTION(scope, void());
+ m_constantRegisters[i].set(vm(), this, templateObject);
+ }
+}
+
void CodeBlock::setAlternative(VM& vm, CodeBlock* alternative)
{
RELEASE_ASSERT(alternative);
Modified: trunk/Source/_javascript_Core/runtime/JSScope.cpp (282623 => 282624)
--- trunk/Source/_javascript_Core/runtime/JSScope.cpp 2021-09-17 00:53:50 UTC (rev 282623)
+++ trunk/Source/_javascript_Core/runtime/JSScope.cpp 2021-09-17 01:04:59 UTC (rev 282624)
@@ -27,10 +27,12 @@
#include "JSScope.h"
#include "AbstractModuleRecord.h"
+#include "DeferTermination.h"
#include "JSCInlines.h"
#include "JSLexicalEnvironment.h"
#include "JSModuleEnvironment.h"
#include "JSWithScope.h"
+#include "VMTrapsInlines.h"
#include "VariableEnvironment.h"
namespace JSC {
@@ -54,7 +56,7 @@
static inline bool abstractAccess(JSGlobalObject* globalObject, JSScope* scope, const Identifier& ident, GetOrPut getOrPut, size_t depth, bool& needsVarInjectionChecks, ResolveOp& op, InitializationMode initializationMode)
{
VM& vm = globalObject->vm();
- auto throwScope = DECLARE_THROW_SCOPE(vm);
+ DeferTerminationForAWhile deferScope(vm);
if (scope->isJSLexicalEnvironment()) {
JSLexicalEnvironment* lexicalEnvironment = jsCast<JSLexicalEnvironment*>(scope);
@@ -80,8 +82,9 @@
if (scope->type() == ModuleEnvironmentType) {
JSModuleEnvironment* moduleEnvironment = jsCast<JSModuleEnvironment*>(scope);
AbstractModuleRecord* moduleRecord = moduleEnvironment->moduleRecord();
+ auto catchScope = DECLARE_CATCH_SCOPE(vm);
AbstractModuleRecord::Resolution resolution = moduleRecord->resolveImport(globalObject, ident);
- RETURN_IF_EXCEPTION(throwScope, false);
+ catchScope.releaseAssertNoException();
if (resolution.type == AbstractModuleRecord::Resolution::Type::Resolved) {
AbstractModuleRecord* importedRecord = resolution.moduleRecord;
JSModuleEnvironment* importedEnvironment = importedRecord->moduleEnvironment();
@@ -304,9 +307,6 @@
ResolveOp JSScope::abstractResolve(JSGlobalObject* globalObject, size_t depthOffset, JSScope* scope, const Identifier& ident, GetOrPut getOrPut, ResolveType unlinkedType, InitializationMode initializationMode)
{
- VM& vm = globalObject->vm();
- auto throwScope = DECLARE_THROW_SCOPE(vm);
-
ResolveOp op(Dynamic, 0, nullptr, nullptr, nullptr, 0);
if (unlinkedType == Dynamic)
return op;
@@ -315,7 +315,6 @@
size_t depth = depthOffset;
for (; scope; scope = scope->next()) {
bool success = abstractAccess(globalObject, scope, ident, getOrPut, depth, needsVarInjectionChecks, op, initializationMode);
- RETURN_IF_EXCEPTION(throwScope, ResolveOp(Dynamic, 0, nullptr, nullptr, nullptr, 0));
if (success)
break;
++depth;