Do all closed variable access through the local lexical object
https://bugs.webkit.org/show_bug.cgi?id=136869
Reviewed by Filip Pizlo.
This patch makes all reads and writes from captured registers
go through the lexical record, and by doing so removes the
need for record tearoff.
To keep the patch simple we still number variables as though
they are local stack allocated registers, but ::local() will
fail. When local fails we perform a generic resolve, and in
that resolve we now use a ResolveScopeInfo struct to pass
around information about whether a lookup is a statically
known captured variable, and its location in the activation.
To ensure correct behaviour during codeblock linking we also
add a LocalClosureVariable resolution type.
To ensure correct semantics for the Arguments object, we now
have to eagerly create the Arguments object for any function
that uses both the Arguments object and requires a lexical
record.
* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::finalizeUnconditionally):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::initializeCapturedVariable):
During the entry to a function we are not yet in a position
to allocate temporaries so we directly use the lexical
environment register.
(JSC::BytecodeGenerator::resolveCallee):
(JSC::BytecodeGenerator::emitMove):
(JSC::BytecodeGenerator::local):
(JSC::BytecodeGenerator::constLocal):
(JSC::BytecodeGenerator::emitResolveScope):
(JSC::BytecodeGenerator::emitResolveConstantLocal):
The two resolve scope operations could technically skip
the op_resolve_scope, and simply perform
op_mov dst, recordRegister
but for now it seemed best to maintain the same basic
behaviour.
(JSC::BytecodeGenerator::emitGetFromScope):
(JSC::BytecodeGenerator::emitPutToScope):
(JSC::BytecodeGenerator::createArgumentsIfNecessary):
If we have an environment we've already created Arguments
so no need to check again.
(JSC::BytecodeGenerator::emitReturn):
Don't need to emit tearoff_environment
* bytecompiler/BytecodeGenerator.h:
(JSC::Local::Local):
(JSC::Local::operator bool):
(JSC::Local::get):
(JSC::Local::isReadOnly):
(JSC::Local::isSpecial):
(JSC::ResolveScopeInfo::ResolveScopeInfo):
(JSC::ResolveScopeInfo::isLocal):
(JSC::ResolveScopeInfo::localIndex):
(JSC::BytecodeGenerator::shouldCreateArgumentsEagerly):
(JSC::Local::isCaptured): Deleted.
(JSC::Local::captureMode): Deleted.
* bytecompiler/NodesCodegen.cpp:
(JSC::ResolveNode::emitBytecode):
(JSC::EvalFunctionCallNode::emitBytecode):
(JSC::FunctionCallResolveNode::emitBytecode):
(JSC::PostfixNode::emitResolve):
(JSC::DeleteResolveNode::emitBytecode):
(JSC::TypeOfResolveNode::emitBytecode):
(JSC::PrefixNode::emitResolve):
(JSC::ReadModifyResolveNode::emitBytecode):
(JSC::AssignResolveNode::emitBytecode):
(JSC::ConstDeclNode::emitCodeSingle):
(JSC::EmptyVarExpression::emitBytecode):
(JSC::ForInNode::tryGetBoundLocal):
(JSC::ForInNode::emitLoopHeader):
(JSC::ForOfNode::emitBytecode):
(JSC::BindingNode::bindValue):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::tryGetRegisters):
* dfg/DFGNodeType.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* interpreter/Interpreter.cpp:
(JSC::unwindCallFrame):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_captured_mov): Deleted.
(JSC::JIT::emit_op_tear_off_lexical_environment): Deleted.
(JSC::JIT::emitSlow_op_captured_mov): Deleted.
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_captured_mov): Deleted.
(JSC::JIT::emit_op_tear_off_lexical_environment): Deleted.
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_resolve_scope):
(JSC::JIT::emit_op_get_from_scope):
(JSC::JIT::emitPutClosureVar):
(JSC::JIT::emit_op_put_to_scope):
(JSC::JIT::emitSlow_op_put_to_scope):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emit_op_resolve_scope):
(JSC::JIT::emit_op_get_from_scope):
(JSC::JIT::emitPutClosureVar):
(JSC::JIT::emit_op_put_to_scope):
(JSC::JIT::emitSlow_op_put_to_scope):
* llint/LLIntData.cpp:
(JSC::LLInt::Data::performAssertions):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* llint/LLIntSlowPaths.h:
* llint/LowLevelInterpreter.asm:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/Arguments.cpp:
(JSC::Arguments::tearOff):
* runtime/Arguments.h:
(JSC::Arguments::argument):
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL): Deleted.
* runtime/CommonSlowPaths.h:
* runtime/JSLexicalEnvironment.cpp:
(JSC::JSLexicalEnvironment::visitChildren):
(JSC::JSLexicalEnvironment::symbolTableGet):
(JSC::JSLexicalEnvironment::symbolTablePut):
(JSC::JSLexicalEnvironment::getOwnNonIndexPropertyNames):
(JSC::JSLexicalEnvironment::getOwnPropertySlot):
(JSC::JSLexicalEnvironment::argumentsGetter):
* runtime/JSLexicalEnvironment.h:
(JSC::JSLexicalEnvironment::create):
(JSC::JSLexicalEnvironment::JSLexicalEnvironment):
(JSC::JSLexicalEnvironment::tearOff): Deleted.
(JSC::JSLexicalEnvironment::isTornOff): Deleted.
* runtime/JSScope.cpp:
(JSC::resolveTypeName):
* runtime/JSScope.h:
(JSC::makeType):
(JSC::needsVarInjectionChecks):
* runtime/WriteBarrier.h:
(JSC::WriteBarrier<Unknown>::WriteBarrier):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@174226 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index 8187e98..4b4e5a7 100644
--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -168,11 +168,12 @@
JSTextPosition divot = m_start + m_ident.length();
generator.emitExpressionInfo(divot, m_start, divot);
- RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident);
+ ResolveScopeInfo resolveScopeInfo;
+ RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident, resolveScopeInfo);
RegisterID* finalDest = generator.finalDestination(dst);
- RegisterID* result = generator.emitGetFromScope(finalDest, scope.get(), m_ident, ThrowIfNotFound);
+ RegisterID* result = generator.emitGetFromScope(finalDest, scope.get(), m_ident, ThrowIfNotFound, resolveScopeInfo);
if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(finalDest, ProfileTypeBytecodeGetFromScope, &m_ident);
+ generator.emitProfileType(finalDest, resolveScopeInfo.isLocal() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &m_ident);
generator.emitTypeProfilerExpressionInfo(m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
}
return result;
@@ -489,8 +490,9 @@
CallArguments callArguments(generator, m_args);
JSTextPosition newDivot = divotStart() + 4;
generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
- generator.emitResolveScope(callArguments.thisRegister(), generator.propertyNames().eval);
- generator.emitGetFromScope(func.get(), callArguments.thisRegister(), generator.propertyNames().eval, ThrowIfNotFound);
+ ResolveScopeInfo resolveScopeInfo;
+ generator.emitResolveScope(callArguments.thisRegister(), generator.propertyNames().eval, resolveScopeInfo);
+ generator.emitGetFromScope(func.get(), callArguments.thisRegister(), generator.propertyNames().eval, ThrowIfNotFound, resolveScopeInfo);
return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd());
}
@@ -537,8 +539,9 @@
JSTextPosition newDivot = divotStart() + m_ident.length();
generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
- generator.emitResolveScope(callArguments.thisRegister(), m_ident);
- generator.emitGetFromScope(func.get(), callArguments.thisRegister(), m_ident, ThrowIfNotFound);
+ ResolveScopeInfo resolveScopeInfo;
+ generator.emitResolveScope(callArguments.thisRegister(), m_ident, resolveScopeInfo);
+ generator.emitGetFromScope(func.get(), callArguments.thisRegister(), m_ident, ThrowIfNotFound, resolveScopeInfo);
RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
if (generator.vm()->typeProfiler()) {
generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
@@ -802,7 +805,7 @@
if (local.isReadOnly()) {
generator.emitReadOnlyExceptionIfNeeded();
localReg = generator.emitMove(generator.tempDestination(dst), localReg);
- } else if (local.isCaptured() || generator.vm()->typeProfiler()) {
+ } else if (generator.vm()->typeProfiler()) {
RefPtr<RegisterID> tempDst = generator.finalDestination(dst);
ASSERT(dst != localReg);
RefPtr<RegisterID> tempDstSrc = generator.newTemporary();
@@ -818,12 +821,13 @@
}
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
- RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), ident);
- RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound);
+ ResolveScopeInfo resolveScopeInfo;
+ RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), ident, resolveScopeInfo);
+ RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound, resolveScopeInfo);
RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
- generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound);
+ generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound, resolveScopeInfo);
if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(value.get(), ProfileTypeBytecodePutToScope, &ident);
+ generator.emitProfileType(value.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);
generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
}
@@ -903,7 +907,8 @@
return generator.emitLoad(generator.finalDestination(dst), false);
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
- RefPtr<RegisterID> base = generator.emitResolveScope(generator.tempDestination(dst), m_ident);
+ ResolveScopeInfo resolveScopeInfo;
+ RefPtr<RegisterID> base = generator.emitResolveScope(generator.tempDestination(dst), m_ident, resolveScopeInfo);
return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident);
}
@@ -960,8 +965,9 @@
return generator.emitTypeOf(generator.finalDestination(dst), local.get());
}
- RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident);
- RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound);
+ ResolveScopeInfo resolveScopeInfo;
+ RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident, resolveScopeInfo);
+ RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound, resolveScopeInfo);
if (dst == generator.ignoredResult())
return 0;
return generator.emitTypeOf(generator.finalDestination(dst, scope.get()), value.get());
@@ -992,7 +998,7 @@
if (local.isReadOnly()) {
generator.emitReadOnlyExceptionIfNeeded();
localReg = generator.emitMove(generator.tempDestination(dst), localReg);
- } else if (local.isCaptured() || generator.vm()->typeProfiler()) {
+ } else if (generator.vm()->typeProfiler()) {
RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
generator.emitMove(tempDst.get(), localReg);
emitIncOrDec(generator, tempDst.get(), m_operator);
@@ -1006,12 +1012,13 @@
}
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
- RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), ident);
- RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound);
+ ResolveScopeInfo resolveScopeInfo;
+ RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), ident, resolveScopeInfo);
+ RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound, resolveScopeInfo);
emitIncOrDec(generator, value.get(), m_operator);
- generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound);
+ generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound, resolveScopeInfo);
if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(value.get(), ProfileTypeBytecodePutToScope, &ident);
+ generator.emitProfileType(value.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);
generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
}
return generator.moveToDestinationIfNeeded(dst, value.get());
@@ -1505,8 +1512,7 @@
return emitReadModifyAssignment(generator, generator.finalDestination(dst), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
}
- if (local.isCaptured()
- || generator.vm()->typeProfiler()
+ if (generator.vm()->typeProfiler()
|| generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
RefPtr<RegisterID> result = generator.newTemporary();
generator.emitMove(result.get(), local.get());
@@ -1524,12 +1530,13 @@
}
generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
- RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
- RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, ThrowIfNotFound);
+ ResolveScopeInfo resolveScopeInfo;
+ RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident, resolveScopeInfo);
+ RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, ThrowIfNotFound, resolveScopeInfo);
RefPtr<RegisterID> result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
- RegisterID* returnResult = generator.emitPutToScope(scope.get(), m_ident, result.get(), ThrowIfNotFound);
+ RegisterID* returnResult = generator.emitPutToScope(scope.get(), m_ident, result.get(), ThrowIfNotFound, resolveScopeInfo);
if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(result.get(), ProfileTypeBytecodePutToScope, &m_ident);
+ generator.emitProfileType(result.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_ident);
generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
}
return returnResult;
@@ -1544,7 +1551,7 @@
generator.emitReadOnlyExceptionIfNeeded();
return generator.emitNode(dst, m_right);
}
- if (local.isCaptured() || generator.vm()->typeProfiler()) {
+ if (local.isSpecial() || generator.vm()->typeProfiler()) {
RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
generator.emitNode(tempDst.get(), m_right);
generator.emitMove(local.get(), tempDst.get());
@@ -1560,14 +1567,15 @@
if (generator.isStrictMode())
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
- RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
+ ResolveScopeInfo resolveScopeInfo;
+ RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident, resolveScopeInfo);
if (dst == generator.ignoredResult())
dst = 0;
RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
- RegisterID* returnResult = generator.emitPutToScope(scope.get(), m_ident, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
+ RegisterID* returnResult = generator.emitPutToScope(scope.get(), m_ident, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, resolveScopeInfo);
if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(result.get(), ProfileTypeBytecodePutToScope, &m_ident);
+ generator.emitProfileType(result.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_ident);
generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
}
return returnResult;
@@ -1676,7 +1684,7 @@
return local.get();
// FIXME: Maybe call emitExpressionInfo here.
- if (local.isCaptured() || generator.vm()->typeProfiler()) {
+ if (local.isSpecial() || generator.vm()->typeProfiler()) {
RefPtr<RegisterID> tempDst = generator.newTemporary();
generator.emitNode(tempDst.get(), m_init);
return generator.emitMove(local.get(), tempDst.get());
@@ -1690,12 +1698,19 @@
if (generator.codeType() == GlobalCode)
return generator.emitInitGlobalConst(m_ident, value.get());
- if (generator.codeType() != EvalCode)
+ if (generator.codeType() != EvalCode) {
+
+ ResolveScopeInfo resolveScopeInfo;
+ if (RefPtr<RegisterID> scope = generator.emitResolveConstantLocal(generator.newTemporary(), m_ident, resolveScopeInfo))
+ return generator.emitPutToScope(scope.get(), m_ident, value.get(), DoNotThrowIfNotFound, resolveScopeInfo);
+
return value.get();
+ }
// FIXME: This will result in incorrect assignment if m_ident exists in an intervening with scope.
- RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
- return generator.emitPutToScope(scope.get(), m_ident, value.get(), DoNotThrowIfNotFound);
+ ResolveScopeInfo resolveScopeInfo;
+ RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident, resolveScopeInfo);
+ return generator.emitPutToScope(scope.get(), m_ident, value.get(), DoNotThrowIfNotFound, resolveScopeInfo);
}
RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
@@ -1792,9 +1807,10 @@
if (Local local = generator.local(m_ident))
generator.emitProfileType(local.get(), ProfileTypeBytecodeHasGlobalID, nullptr);
else {
- RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
- RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound);
- generator.emitProfileType(value.get(), ProfileTypeBytecodeGetFromScope, &m_ident);
+ ResolveScopeInfo resolveScopeInfo;
+ RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident, resolveScopeInfo);
+ RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound, resolveScopeInfo);
+ generator.emitProfileType(value.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &m_ident);
}
generator.emitTypeProfilerExpressionInfo(position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
@@ -1955,8 +1971,6 @@
if (m_lexpr->isResolveNode()) {
const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
Local local = generator.local(ident);
- if (local.isCaptured())
- return nullptr;
return local.get();
}
@@ -1969,7 +1983,7 @@
auto simpleBinding = static_cast<BindingNode*>(binding);
const Identifier& ident = simpleBinding->boundProperty();
Local local = generator.local(ident);
- if (local.isCaptured())
+ if (local.isSpecial())
return nullptr;
return local.get();
}
@@ -1987,9 +2001,10 @@
else {
if (generator.isStrictMode())
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
- RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident);
+ ResolveScopeInfo resolveScopeInfo;
+ RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident, resolveScopeInfo);
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
- generator.emitPutToScope(scope, ident, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
+ generator.emitPutToScope(scope, ident, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, resolveScopeInfo);
}
return;
}
@@ -2021,7 +2036,7 @@
auto simpleBinding = static_cast<BindingNode*>(binding);
const Identifier& ident = simpleBinding->boundProperty();
Local local = generator.local(ident);
- if (!local.get() || local.isCaptured()) {
+ if (!local.get() || local.isSpecial()) {
assignNode->bindings()->bindValue(generator, propertyName);
return;
}
@@ -2183,9 +2198,10 @@
else {
if (generator.isStrictMode())
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
- RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident);
+ ResolveScopeInfo resolveScopeInfo;
+ RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident, resolveScopeInfo);
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
- generator.emitPutToScope(scope, ident, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
+ generator.emitPutToScope(scope, ident, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, resolveScopeInfo);
}
} else if (m_lexpr->isDotAccessorNode()) {
DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
@@ -2822,11 +2838,12 @@
}
if (generator.isStrictMode())
generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
- RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), m_boundProperty);
+ ResolveScopeInfo resolveScopeInfo;
+ RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), m_boundProperty, resolveScopeInfo);
generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
- generator.emitPutToScope(scope, m_boundProperty, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
+ generator.emitPutToScope(scope, m_boundProperty, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, resolveScopeInfo);
if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(value, ProfileTypeBytecodePutToScope, &m_boundProperty);
+ generator.emitProfileType(value, resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_boundProperty);
generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
}
return;