Ignore:
Timestamp:
Apr 18, 2016, 6:38:30 PM (9 years ago)
Author:
[email protected]
Message:

implement dynamic scope accesses in the DFG/FTL
https://bugs.webkit.org/show_bug.cgi?id=156567

Reviewed by Geoffrey Garen.

This patch adds dynamic scope operations to the DFG/FTL.
This patch adds three new DFG nodes: ResolveScope, PutDynamicVar and GetDynamicVar.
When we encounter a Dynamic/UnresolvedProperty/UnresolvedPropertyWithVarInjectionChecks
resolve type, we will compile dynamic scope resolution nodes. When we encounter
a resolve type that needs var injection checks and the var injection
watchpoint has already been fired, we will compile dynamic scope resolution
nodes.

This patch also adds a new value to the InitializationMode enum: ConstInitialization.
There was a subtle bug where we used to never compile the var injection variant of the
resolve type for an eval that injected a var where there was also a global lexical variable with the same name.
For example, the store compiled in this eval("var foo = 20;") wouldn't be compiled
with var injection checks if there was global let/const variable named "foo".
So there was the potential for the injected var to store to the GlobalLexicalObject.
I found this bug because my initial implementation in the DFG/FTL ran into it.
The reason this bug existed is because when we compile a const initialization,
we never need a var injections check. The const initialization always
knows where to store its value. This same logic leaked into the above eval's
"var foo = 20" store. This new enum value allows us to distinguish const
initialization stores from non-const initialization stores.

(I also changed InitializationMode to be an enum class instead of an enum).

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::finishCreation):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack):
(JSC::BytecodeGenerator::initializeBlockScopedFunctions):
(JSC::BytecodeGenerator::hoistSloppyModeFunctionIfNecessary):
(JSC::BytecodeGenerator::prepareLexicalScopeForNextForLoopIteration):
(JSC::BytecodeGenerator::emitGetFromScope):
(JSC::BytecodeGenerator::initializeVariable):
(JSC::BytecodeGenerator::emitInstanceOf):
(JSC::BytecodeGenerator::emitPushFunctionNameScope):
(JSC::BytecodeGenerator::pushScopedControlFlowContext):
(JSC::BytecodeGenerator::emitPutNewTargetToArrowFunctionContextScope):
(JSC::BytecodeGenerator::emitPutDerivedConstructorToArrowFunctionContextScope):
(JSC::BytecodeGenerator::emitPutThisToArrowFunctionContextScope):

  • bytecompiler/NodesCodegen.cpp:

(JSC::PostfixNode::emitResolve):
(JSC::PrefixNode::emitResolve):
(JSC::ReadModifyResolveNode::emitBytecode):
(JSC::initializationModeForAssignmentContext):
(JSC::AssignResolveNode::emitBytecode):
(JSC::EmptyLetExpression::emitBytecode):
(JSC::ForInNode::emitLoopHeader):
(JSC::ForOfNode::emitBytecode):
(JSC::ClassExprNode::emitBytecode):
(JSC::BindingNode::bindValue):
(JSC::AssignmentElementNode::bindValue):
(JSC::RestParameterNode::emit):

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::noticeArgumentsUse):
(JSC::DFG::ByteCodeParser::promoteToConstant):
(JSC::DFG::ByteCodeParser::needsDynamicLookup):
(JSC::DFG::ByteCodeParser::planLoad):
(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/DFGNode.h:

(JSC::DFG::Node::hasIdentifier):
(JSC::DFG::Node::identifierNumber):
(JSC::DFG::Node::hasGetPutInfo):
(JSC::DFG::Node::getPutInfo):
(JSC::DFG::Node::hasAccessorAttributes):

  • dfg/DFGNodeType.h:
  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGPredictionPropagationPhase.cpp:

(JSC::DFG::PredictionPropagationPhase::propagate):

  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compilePutGetterSetterById):
(JSC::DFG::SpeculativeJIT::compileResolveScope):
(JSC::DFG::SpeculativeJIT::compileGetDynamicVar):
(JSC::DFG::SpeculativeJIT::compilePutDynamicVar):
(JSC::DFG::SpeculativeJIT::compilePutAccessorByVal):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::callOperation):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compare):
(JSC::FTL::DFG::LowerDFGToB3::compileResolveScope):
(JSC::FTL::DFG::LowerDFGToB3::compileGetDynamicVar):
(JSC::FTL::DFG::LowerDFGToB3::compilePutDynamicVar):
(JSC::FTL::DFG::LowerDFGToB3::compareEqObjectOrOtherToObject):

  • jit/CCallHelpers.h:

(JSC::CCallHelpers::setupArgumentsWithExecState):

  • jit/JITOperations.cpp:
  • jit/JITOperations.h:
  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emit_op_put_to_scope):
(JSC::JIT::emitSlow_op_put_to_scope):

  • jit/JITPropertyAccess32_64.cpp:

(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/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/GetPutInfo.h:

(JSC::resolveModeName):
(JSC::initializationModeName):
(JSC::isInitialization):
(JSC::makeType):
(JSC::GetPutInfo::GetPutInfo):

  • runtime/JSScope.cpp:

(JSC::abstractAccess):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r199179 r199699  
    11591159    RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
    11601160    if (!var.isReadOnly()) {
    1161         generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, NotInitialization);
     1161        generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
    11621162        generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
    11631163    }
     
    13591359    emitIncOrDec(generator, value.get(), m_operator);
    13601360    if (!var.isReadOnly()) {
    1361         generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, NotInitialization);
     1361        generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
    13621362        generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
    13631363    }
     
    19101910    RegisterID* returnResult = result.get();
    19111911    if (!var.isReadOnly()) {
    1912         returnResult = generator.emitPutToScope(scope.get(), var, result.get(), ThrowIfNotFound, NotInitialization);
     1912        returnResult = generator.emitPutToScope(scope.get(), var, result.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
    19131913        generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
    19141914    }
    19151915    return returnResult;
     1916}
     1917
     1918static InitializationMode initializationModeForAssignmentContext(AssignmentContext assignmentContext)
     1919{
     1920    switch (assignmentContext) {
     1921    case AssignmentContext::DeclarationStatement:
     1922        return InitializationMode::Initialization;
     1923    case AssignmentContext::ConstDeclarationStatement:
     1924        return InitializationMode::ConstInitialization;
     1925    case AssignmentContext::AssignmentExpression:
     1926        return InitializationMode::NotInitialization;
     1927    }
     1928
     1929    ASSERT_NOT_REACHED();
     1930    return InitializationMode::NotInitialization;
    19161931}
    19171932
     
    19671982    RegisterID* returnResult = result.get();
    19681983    if (!isReadOnly) {
    1969         returnResult = generator.emitPutToScope(scope.get(), var, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound,
    1970             m_assignmentContext == AssignmentContext::ConstDeclarationStatement || m_assignmentContext == AssignmentContext::DeclarationStatement  ? Initialization : NotInitialization);
     1984        returnResult = generator.emitPutToScope(scope.get(), var, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, initializationModeForAssignmentContext(m_assignmentContext));
    19711985        generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
    19721986    }
     
    21632177        RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
    21642178        RefPtr<RegisterID> value = generator.emitLoad(nullptr, jsUndefined());
    2165         generator.emitPutToScope(scope.get(), var, value.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, Initialization);
     2179        generator.emitPutToScope(scope.get(), var, value.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::Initialization);
    21662180        generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
    21672181    }
     
    23712385            RegisterID* scope = generator.emitResolveScope(nullptr, var);
    23722386            generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    2373             generator.emitPutToScope(scope, var, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, NotInitialization);
     2387            generator.emitPutToScope(scope, var, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
    23742388        }
    23752389        generator.emitProfileType(propertyName, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
     
    25922606                RegisterID* scope = generator.emitResolveScope(nullptr, var);
    25932607                generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    2594                 generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, NotInitialization);
     2608                generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
    25952609            }
    25962610            generator.emitProfileType(value, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
     
    33123326        RELEASE_ASSERT(classNameVar.isResolved());
    33133327        RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, classNameVar);
    3314         generator.emitPutToScope(scope.get(), classNameVar, constructor.get(), ThrowIfNotFound, Initialization);
     3328        generator.emitPutToScope(scope.get(), classNameVar, constructor.get(), ThrowIfNotFound, InitializationMode::Initialization);
    33153329        generator.popLexicalScope(this);
    33163330    }
     
    36093623        return;
    36103624    }
    3611     generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound,
    3612         m_bindingContext == AssignmentContext::ConstDeclarationStatement || m_bindingContext == AssignmentContext::DeclarationStatement ? Initialization : NotInitialization);
     3625    generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, initializationModeForAssignmentContext(m_bindingContext));
    36133626    generator.emitProfileType(value, var, divotStart(), divotEnd());
    36143627    if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
     
    36603673        generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
    36613674        if (!isReadOnly) {
    3662             generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, NotInitialization);
     3675            generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
    36633676            generator.emitProfileType(value, var, divotStart(), divotEnd());
    36643677        }
     
    37113724    RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
    37123725    generator.emitExpressionInfo(m_divotEnd, m_divotStart, m_divotEnd);
    3713     generator.emitPutToScope(scope.get(), var, restParameterArray.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, Initialization);
     3726    generator.emitPutToScope(scope.get(), var, restParameterArray.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::Initialization);
    37143727}
    37153728
Note: See TracChangeset for help on using the changeset viewer.