Ignore:
Timestamp:
Oct 2, 2014, 1:35:58 PM (11 years ago)
Author:
[email protected]
Message:

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):

Location:
trunk/Source/JavaScriptCore/bytecompiler
Files:
3 edited

Legend:

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

    r174216 r174226  
    247247    if (m_codeBlock->needsFullScopeChain() || m_shouldEmitDebugHooks) {
    248248        m_lexicalEnvironmentRegister = addVar();
    249         emitInitLazyRegister(m_lexicalEnvironmentRegister);
    250249        m_codeBlock->setActivationRegister(m_lexicalEnvironmentRegister->virtualRegister());
    251250        emitOpcode(op_create_lexical_environment);
     
    268267        emitInitLazyRegister(unmodifiedArgumentsRegister);
    269268       
    270         if (shouldTearOffArgumentsEagerly()) {
     269        if (shouldCreateArgumentsEagerly() || shouldTearOffArgumentsEagerly()) {
    271270            emitOpcode(op_create_arguments);
    272271            instructions().append(argumentsRegister->index());
     272            if (m_codeBlock->hasActivationRegister()) {
     273                RegisterID* argumentsRegister = &registerFor(m_codeBlock->argumentsRegister().offset());
     274                initializeCapturedVariable(argumentsRegister, propertyNames().arguments, argumentsRegister);
     275                RegisterID* uncheckedArgumentsRegister = &registerFor(JSC::unmodifiedArgumentsRegister(m_codeBlock->argumentsRegister()).offset());
     276                initializeCapturedVariable(uncheckedArgumentsRegister, propertyNames().arguments, uncheckedArgumentsRegister);
     277            }
    273278        }
    274279    }
     
    317322    // Captured variables and functions go first so that activations don't have
    318323    // to step over the non-captured locals to mark them.
    319     if (functionBody->hasCapturedVariables()) {
     324    if (functionBody->hasCapturedVariables() || shouldCaptureAllTheThings) {
    320325        for (size_t i = 0; i < boundParameterProperties.size(); i++) {
    321326            const Identifier& ident = boundParameterProperties[i];
    322             if (functionBody->captures(ident))
     327            if (functionBody->captures(ident) || shouldCaptureAllTheThings)
    323328                addVar(ident, IsVariable, IsWatchable);
    324329        }
     
    326331            FunctionBodyNode* function = functionStack[i];
    327332            const Identifier& ident = function->ident();
    328             if (functionBody->captures(ident)) {
     333            if (functionBody->captures(ident) || shouldCaptureAllTheThings) {
    329334                m_functions.add(ident.impl());
    330                 emitNewFunction(addVar(ident, IsVariable, IsWatchable), IsCaptured, function);
     335                // We rely on still allocating stack space for captured variables
     336                // here.
     337                RegisterID* newFunction = emitNewFunction(addVar(ident, IsVariable, IsWatchable), IsCaptured, function);
     338                initializeCapturedVariable(newFunction, ident, newFunction);
    331339            }
    332340        }
    333341        for (size_t i = 0; i < varStack.size(); ++i) {
    334342            const Identifier& ident = varStack[i].first;
    335             if (functionBody->captures(ident))
     343            if (functionBody->captures(ident) || shouldCaptureAllTheThings)
    336344                addVar(ident, (varStack[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable, IsWatchable);
    337345        }
     
    342350    bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks && !m_vm->typeProfiler();
    343351    m_firstLazyFunction = codeBlock->m_numVars;
    344     for (size_t i = 0; i < functionStack.size(); ++i) {
    345         FunctionBodyNode* function = functionStack[i];
    346         const Identifier& ident = function->ident();
    347         if (!functionBody->captures(ident)) {
    348             m_functions.add(ident.impl());
    349             RefPtr<RegisterID> reg = addVar(ident, IsVariable, NotWatchable);
    350             // Don't lazily create functions that override the name 'arguments'
    351             // as this would complicate lazy instantiation of actual arguments.
    352             if (!canLazilyCreateFunctions || ident == propertyNames().arguments)
    353                 emitNewFunction(reg.get(), NotCaptured, function);
    354             else {
    355                 emitInitLazyRegister(reg.get());
    356                 m_lazyFunctions.set(reg->virtualRegister().toLocal(), function);
     352    if (!shouldCaptureAllTheThings) {
     353        for (size_t i = 0; i < functionStack.size(); ++i) {
     354            FunctionBodyNode* function = functionStack[i];
     355            const Identifier& ident = function->ident();
     356            if (!functionBody->captures(ident)) {
     357                m_functions.add(ident.impl());
     358                RefPtr<RegisterID> reg = addVar(ident, IsVariable, NotWatchable);
     359                // Don't lazily create functions that override the name 'arguments'
     360                // as this would complicate lazy instantiation of actual arguments.
     361                if (!canLazilyCreateFunctions || ident == propertyNames().arguments)
     362                    emitNewFunction(reg.get(), NotCaptured, function);
     363                else {
     364                    emitInitLazyRegister(reg.get());
     365                    m_lazyFunctions.set(reg->virtualRegister().toLocal(), function);
     366                }
    357367            }
    358368        }
    359     }
    360     m_lastLazyFunction = canLazilyCreateFunctions ? codeBlock->m_numVars : m_firstLazyFunction;
    361     for (size_t i = 0; i < boundParameterProperties.size(); i++) {
    362         const Identifier& ident = boundParameterProperties[i];
    363         if (!functionBody->captures(ident))
    364             addVar(ident, IsVariable, IsWatchable);
    365     }
    366     for (size_t i = 0; i < varStack.size(); ++i) {
    367         const Identifier& ident = varStack[i].first;
    368         if (!functionBody->captures(ident))
    369             addVar(ident, (varStack[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable, NotWatchable);
    370     }
    371 
    372     if (shouldCaptureAllTheThings)
    373         m_symbolTable->setCaptureEnd(virtualRegisterForLocal(codeBlock->m_numVars).offset());
     369        m_lastLazyFunction = canLazilyCreateFunctions ? codeBlock->m_numVars : m_firstLazyFunction;
     370        for (size_t i = 0; i < boundParameterProperties.size(); i++) {
     371            const Identifier& ident = boundParameterProperties[i];
     372            if (!functionBody->captures(ident))
     373                addVar(ident, IsVariable, IsWatchable);
     374        }
     375        for (size_t i = 0; i < varStack.size(); ++i) {
     376            const Identifier& ident = varStack[i].first;
     377            if (!functionBody->captures(ident))
     378                addVar(ident, (varStack[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable, NotWatchable);
     379        }
     380    }
    374381
    375382    if (m_symbolTable->captureCount())
     
    397404            index = capturedArguments[i]->index();
    398405            RegisterID original(nextParameterIndex);
    399             emitMove(capturedArguments[i], &original);
     406            initializeCapturedVariable(capturedArguments[i], simpleParameter->boundProperty(), &original);
    400407        }
    401408        addParameter(simpleParameter->boundProperty(), index);
     
    477484}
    478485
     486RegisterID* BytecodeGenerator::initializeCapturedVariable(RegisterID* dst, const Identifier& propertyName, RegisterID* value)
     487{
     488
     489    m_codeBlock->addPropertyAccessInstruction(instructions().size());
     490    emitOpcode(op_put_to_scope);
     491    instructions().append(m_lexicalEnvironmentRegister->index());
     492    instructions().append(addConstant(propertyName));
     493    instructions().append(value->index());
     494    instructions().append(ResolveModeAndType(ThrowIfNotFound, LocalClosureVar).operand());
     495    instructions().append(0);
     496    instructions().append(dst->index());
     497    return dst;
     498}
     499
    479500RegisterID* BytecodeGenerator::resolveCallee(FunctionBodyNode* functionBodyNode)
    480501{
     
    487508    m_calleeRegister.setIndex(JSStack::Callee);
    488509    if (functionBodyNode->captures(functionBodyNode->ident()))
    489         return emitMove(addVar(), IsCaptured, &m_calleeRegister);
     510        return initializeCapturedVariable(addVar(), functionBodyNode->ident(), &m_calleeRegister);
    490511
    491512    return &m_calleeRegister;
     
    9971018}
    9981019
    999 RegisterID* BytecodeGenerator::emitMove(RegisterID* dst, CaptureMode captureMode, RegisterID* src)
     1020RegisterID* BytecodeGenerator::emitMove(RegisterID* dst, RegisterID* src)
    10001021{
    10011022    m_staticPropertyAnalyzer.mov(dst->index(), src->index());
    1002 
    1003     emitOpcode(captureMode == IsCaptured ? op_captured_mov : op_mov);
     1023    ASSERT(dst->virtualRegister() == m_codeBlock->argumentsRegister() || !isCaptured(dst->index()));
     1024    emitOpcode(op_mov);
    10041025    instructions().append(dst->index());
    10051026    instructions().append(src->index());
    1006     if (captureMode == IsCaptured)
    1007         instructions().append(watchableVariable(dst->index()));
    10081027
    10091028    if (!dst->isTemporary() && vm()->typeProfiler())
     
    10111030
    10121031    return dst;
    1013 }
    1014 
    1015 RegisterID* BytecodeGenerator::emitMove(RegisterID* dst, RegisterID* src)
    1016 {
    1017     return emitMove(dst, captureMode(dst->index()), src);
    10181032}
    10191033
     
    11981212{
    11991213    if (property == propertyNames().thisIdentifier)
    1200         return Local(thisRegister(), ReadOnly, NotCaptured);
    1201    
    1202     if (property == propertyNames().arguments)
     1214        return Local(thisRegister(), ReadOnly, Local::SpecialLocal);
     1215    bool isArguments = property == propertyNames().arguments;
     1216    if (isArguments)
    12031217        createArgumentsIfNecessary();
    12041218
     
    12101224        return Local();
    12111225
     1226
    12121227    RegisterID* local = createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
    1213     return Local(local, entry.getAttributes(), captureMode(local->index()));
     1228
     1229    if (isCaptured(local->index()) && m_lexicalEnvironmentRegister)
     1230        return Local();
     1231
     1232    return Local(local, entry.getAttributes(), isArguments ? Local::SpecialLocal : Local::NormalLocal);
    12141233}
    12151234
     
    12241243
    12251244    RegisterID* local = createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
    1226     return Local(local, entry.getAttributes(), captureMode(local->index()));
     1245
     1246    bool isArguments = property == propertyNames().arguments;
     1247    if (isCaptured(local->index()) && m_lexicalEnvironmentRegister)
     1248        return Local();
     1249
     1250    return Local(local, entry.getAttributes(), isArguments ? Local::SpecialLocal : Local::NormalLocal);
    12271251}
    12281252
     
    12481272}
    12491273
    1250 RegisterID* BytecodeGenerator::emitResolveScope(RegisterID* dst, const Identifier& identifier)
     1274RegisterID* BytecodeGenerator::emitResolveScope(RegisterID* dst, const Identifier& identifier, ResolveScopeInfo& info)
    12511275{
    12521276    m_codeBlock->addPropertyAccessInstruction(instructions().size());
     1277
     1278    if (m_symbolTable && m_codeType == FunctionCode && !m_localScopeDepth) {
     1279        SymbolTableEntry entry = m_symbolTable->get(identifier.impl());
     1280        if (!entry.isNull()) {
     1281            emitOpcode(op_resolve_scope);
     1282            instructions().append(kill(dst));
     1283            instructions().append(addConstant(identifier));
     1284            instructions().append(LocalClosureVar);
     1285            instructions().append(0);
     1286            instructions().append(0);
     1287            info = ResolveScopeInfo(entry.getIndex());
     1288            return dst;
     1289        }
     1290    }
    12531291
    12541292    ASSERT(!m_symbolTable || !m_symbolTable->contains(identifier.impl()) || resolveType() == Dynamic);
     
    12641302}
    12651303
    1266 RegisterID* BytecodeGenerator::emitGetFromScope(RegisterID* dst, RegisterID* scope, const Identifier& identifier, ResolveMode resolveMode)
     1304RegisterID* BytecodeGenerator::emitResolveConstantLocal(RegisterID* dst, const Identifier& identifier, ResolveScopeInfo& info)
     1305{
     1306    if (!m_symbolTable || m_codeType != FunctionCode)
     1307        return nullptr;
     1308
     1309    SymbolTableEntry entry = m_symbolTable->get(identifier.impl());
     1310    if (entry.isNull())
     1311        return nullptr;
     1312    info = ResolveScopeInfo(entry.getIndex());
     1313    return emitMove(dst, m_lexicalEnvironmentRegister);
     1314
     1315}
     1316
     1317RegisterID* BytecodeGenerator::emitGetFromScope(RegisterID* dst, RegisterID* scope, const Identifier& identifier, ResolveMode resolveMode, const ResolveScopeInfo& info)
    12671318{
    12681319    m_codeBlock->addPropertyAccessInstruction(instructions().size());
     
    12731324    instructions().append(scope->index());
    12741325    instructions().append(addConstant(identifier));
    1275     instructions().append(ResolveModeAndType(resolveMode, resolveType()).operand());
     1326    instructions().append(ResolveModeAndType(resolveMode, info.isLocal() ? LocalClosureVar : resolveType()).operand());
    12761327    instructions().append(0);
    1277     instructions().append(0);
     1328    instructions().append(info.localIndex());
    12781329    instructions().append(profile);
    12791330    return dst;
    12801331}
    12811332
    1282 RegisterID* BytecodeGenerator::emitPutToScope(RegisterID* scope, const Identifier& identifier, RegisterID* value, ResolveMode resolveMode)
     1333RegisterID* BytecodeGenerator::emitPutToScope(RegisterID* scope, const Identifier& identifier, RegisterID* value, ResolveMode resolveMode, const ResolveScopeInfo& info)
    12831334{
    12841335    m_codeBlock->addPropertyAccessInstruction(instructions().size());
     
    12891340    instructions().append(addConstant(identifier));
    12901341    instructions().append(value->index());
    1291     instructions().append(ResolveModeAndType(resolveMode, resolveType()).operand());
    1292     instructions().append(0);
    1293     instructions().append(0);
     1342    if (info.isLocal()) {
     1343        instructions().append(ResolveModeAndType(resolveMode, LocalClosureVar).operand());
     1344        instructions().append(watchableVariable(registerFor(info.localIndex()).index()));
     1345    } else {
     1346        instructions().append(ResolveModeAndType(resolveMode, resolveType()).operand());
     1347        instructions().append(0);
     1348    }
     1349    instructions().append(info.localIndex());
    12941350    return value;
    12951351}
     
    16601716        return;
    16611717
    1662     if (shouldTearOffArgumentsEagerly())
     1718    if (shouldTearOffArgumentsEagerly() || shouldCreateArgumentsEagerly())
    16631719        return;
    16641720
     
    18561912RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
    18571913{
    1858     if (m_lexicalEnvironmentRegister) {
    1859         emitOpcode(op_tear_off_lexical_environment);
    1860         instructions().append(m_lexicalEnvironmentRegister->index());
    1861     }
    1862 
    18631914    if (m_codeBlock->usesArguments() && m_codeBlock->numParameters() != 1 && !isStrictMode()) {
    18641915        emitOpcode(op_tear_off_arguments);
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r173517 r174226  
    190190            : m_local(0)
    191191            , m_attributes(0)
    192         {
    193         }
    194 
    195         Local(RegisterID* local, unsigned attributes, CaptureMode captureMode)
     192            , m_kind(NormalLocal)
     193        {
     194        }
     195
     196        enum LocalKind { NormalLocal, SpecialLocal };
     197
     198        Local(RegisterID* local, unsigned attributes, LocalKind kind)
    196199            : m_local(local)
    197200            , m_attributes(attributes)
    198             , m_isCaptured(captureMode == IsCaptured)
    199         {
    200         }
    201 
    202         operator bool() { return m_local; }
    203 
    204         RegisterID* get() { return m_local; }
    205 
    206         bool isReadOnly() { return m_attributes & ReadOnly; }
    207        
    208         bool isCaptured() { return m_isCaptured; }
    209         CaptureMode captureMode() { return isCaptured() ? IsCaptured : NotCaptured; }
     201            , m_kind(kind)
     202        {
     203        }
     204
     205        operator bool() const { return m_local; }
     206
     207        RegisterID* get() const { return m_local; }
     208
     209        bool isReadOnly() const { return m_attributes & ReadOnly; }
     210        bool isSpecial() const { return m_kind != NormalLocal; }
    210211
    211212    private:
    212213        RegisterID* m_local;
    213214        unsigned m_attributes;
    214         bool m_isCaptured;
     215        LocalKind m_kind;
     216    };
     217
     218    struct ResolveScopeInfo {
     219        ResolveScopeInfo()
     220            : m_localIndex(0)
     221            , m_resolveScopeKind(NonLocalScope)
     222        {
     223        }
     224
     225        ResolveScopeInfo(int index)
     226            : m_localIndex(index)
     227            , m_resolveScopeKind(LocalScope)
     228        {
     229        }
     230
     231        bool isLocal() const { return m_resolveScopeKind == LocalScope; }
     232        int localIndex() const { return m_localIndex; }
     233
     234    private:
     235        int m_localIndex;
     236        enum { LocalScope, NonLocalScope } m_resolveScopeKind;
    215237    };
    216238
     
    224246        ProfileTypeBytecodePutToScope,
    225247        ProfileTypeBytecodeGetFromScope,
     248        ProfileTypeBytecodePutToLocalScope,
     249        ProfileTypeBytecodeGetFromLocalScope,
    226250        ProfileTypeBytecodeHasGlobalID,
    227251        ProfileTypeBytecodeDoesNotHaveGlobalID,
     
    432456        RegisterID* emitNewRegExp(RegisterID* dst, RegExp*);
    433457
    434         RegisterID* emitMove(RegisterID* dst, CaptureMode, RegisterID* src);
    435458        RegisterID* emitMove(RegisterID* dst, RegisterID* src);
    436459
     
    474497
    475498        ResolveType resolveType();
    476         RegisterID* emitResolveScope(RegisterID* dst, const Identifier&);
    477         RegisterID* emitGetFromScope(RegisterID* dst, RegisterID* scope, const Identifier&, ResolveMode);
    478         RegisterID* emitPutToScope(RegisterID* scope, const Identifier&, RegisterID* value, ResolveMode);
     499        RegisterID* emitResolveConstantLocal(RegisterID* dst, const Identifier&, ResolveScopeInfo&);
     500        RegisterID* emitResolveScope(RegisterID* dst, const Identifier&, ResolveScopeInfo&);
     501        RegisterID* emitGetFromScope(RegisterID* dst, RegisterID* scope, const Identifier&, ResolveMode, const ResolveScopeInfo&);
     502        RegisterID* emitPutToScope(RegisterID* scope, const Identifier&, RegisterID* value, ResolveMode, const ResolveScopeInfo&);
    479503
    480504        PassRefPtr<Label> emitLabel(Label*);
     
    634658        RegisterID* emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
    635659        RegisterID* emitCallVarargs(OpcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
    636        
     660        RegisterID* initializeCapturedVariable(RegisterID* dst, const Identifier&, RegisterID*);
     661
    637662    public:
    638663        JSString* addStringConstant(const Identifier&);
     
    670695        {
    671696            return m_codeType == FunctionCode && isStrictMode() && m_scopeNode->modifiesParameter();
     697        }
     698
     699        bool shouldCreateArgumentsEagerly()
     700        {
     701            if (m_codeType != FunctionCode)
     702                return false;
     703            return m_lexicalEnvironmentRegister && m_codeBlock->usesArguments();
    672704        }
    673705
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r173125 r174226  
    169169    JSTextPosition divot = m_start + m_ident.length();
    170170    generator.emitExpressionInfo(divot, m_start, divot);
    171     RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident);
     171    ResolveScopeInfo resolveScopeInfo;
     172    RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident, resolveScopeInfo);
    172173    RegisterID* finalDest = generator.finalDestination(dst);
    173     RegisterID* result = generator.emitGetFromScope(finalDest, scope.get(), m_ident, ThrowIfNotFound);
     174    RegisterID* result = generator.emitGetFromScope(finalDest, scope.get(), m_ident, ThrowIfNotFound, resolveScopeInfo);
    174175    if (generator.vm()->typeProfiler()) {
    175         generator.emitProfileType(finalDest, ProfileTypeBytecodeGetFromScope, &m_ident);
     176        generator.emitProfileType(finalDest, resolveScopeInfo.isLocal() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &m_ident);
    176177        generator.emitTypeProfilerExpressionInfo(m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
    177178    }
     
    490491    JSTextPosition newDivot = divotStart() + 4;
    491492    generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
    492     generator.emitResolveScope(callArguments.thisRegister(), generator.propertyNames().eval);
    493     generator.emitGetFromScope(func.get(), callArguments.thisRegister(), generator.propertyNames().eval, ThrowIfNotFound);
     493    ResolveScopeInfo resolveScopeInfo;
     494    generator.emitResolveScope(callArguments.thisRegister(), generator.propertyNames().eval, resolveScopeInfo);
     495    generator.emitGetFromScope(func.get(), callArguments.thisRegister(), generator.propertyNames().eval, ThrowIfNotFound, resolveScopeInfo);
    494496    return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd());
    495497}
     
    538540    JSTextPosition newDivot = divotStart() + m_ident.length();
    539541    generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
    540     generator.emitResolveScope(callArguments.thisRegister(), m_ident);
    541     generator.emitGetFromScope(func.get(), callArguments.thisRegister(), m_ident, ThrowIfNotFound);
     542    ResolveScopeInfo resolveScopeInfo;
     543    generator.emitResolveScope(callArguments.thisRegister(), m_ident, resolveScopeInfo);
     544    generator.emitGetFromScope(func.get(), callArguments.thisRegister(), m_ident, ThrowIfNotFound, resolveScopeInfo);
    542545    RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
    543546    if (generator.vm()->typeProfiler()) {
     
    803806            generator.emitReadOnlyExceptionIfNeeded();
    804807            localReg = generator.emitMove(generator.tempDestination(dst), localReg);
    805         } else if (local.isCaptured() || generator.vm()->typeProfiler()) {
     808        } else if (generator.vm()->typeProfiler()) {
    806809            RefPtr<RegisterID> tempDst = generator.finalDestination(dst);
    807810            ASSERT(dst != localReg);
     
    819822
    820823    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    821     RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), ident);
    822     RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound);
     824    ResolveScopeInfo resolveScopeInfo;
     825    RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), ident, resolveScopeInfo);
     826    RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound, resolveScopeInfo);
    823827    RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
    824     generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound);
     828    generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound, resolveScopeInfo);
    825829    if (generator.vm()->typeProfiler()) {
    826         generator.emitProfileType(value.get(), ProfileTypeBytecodePutToScope, &ident);
     830        generator.emitProfileType(value.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);
    827831        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
    828832    }
     
    904908
    905909    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    906     RefPtr<RegisterID> base = generator.emitResolveScope(generator.tempDestination(dst), m_ident);
     910    ResolveScopeInfo resolveScopeInfo;
     911    RefPtr<RegisterID> base = generator.emitResolveScope(generator.tempDestination(dst), m_ident, resolveScopeInfo);
    907912    return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident);
    908913}
     
    961966    }
    962967
    963     RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident);
    964     RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound);
     968    ResolveScopeInfo resolveScopeInfo;
     969    RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident, resolveScopeInfo);
     970    RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound, resolveScopeInfo);
    965971    if (dst == generator.ignoredResult())
    966972        return 0;
     
    993999            generator.emitReadOnlyExceptionIfNeeded();
    9941000            localReg = generator.emitMove(generator.tempDestination(dst), localReg);
    995         } else if (local.isCaptured() || generator.vm()->typeProfiler()) {
     1001        } else if (generator.vm()->typeProfiler()) {
    9961002            RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
    9971003            generator.emitMove(tempDst.get(), localReg);
     
    10071013
    10081014    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    1009     RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), ident);
    1010     RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound);
     1015    ResolveScopeInfo resolveScopeInfo;
     1016    RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), ident, resolveScopeInfo);
     1017    RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound, resolveScopeInfo);
    10111018    emitIncOrDec(generator, value.get(), m_operator);
    1012     generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound);
     1019    generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound, resolveScopeInfo);
    10131020    if (generator.vm()->typeProfiler()) {
    1014         generator.emitProfileType(value.get(), ProfileTypeBytecodePutToScope, &ident);
     1021        generator.emitProfileType(value.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);
    10151022        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
    10161023    }
     
    15061513        }
    15071514       
    1508         if (local.isCaptured()
    1509             || generator.vm()->typeProfiler()
     1515        if (generator.vm()->typeProfiler()
    15101516            || generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
    15111517            RefPtr<RegisterID> result = generator.newTemporary();
     
    15251531
    15261532    generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
    1527     RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
    1528     RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, ThrowIfNotFound);
     1533    ResolveScopeInfo resolveScopeInfo;
     1534    RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident, resolveScopeInfo);
     1535    RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, ThrowIfNotFound, resolveScopeInfo);
    15291536    RefPtr<RegisterID> result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
    1530     RegisterID* returnResult = generator.emitPutToScope(scope.get(), m_ident, result.get(), ThrowIfNotFound);
     1537    RegisterID* returnResult = generator.emitPutToScope(scope.get(), m_ident, result.get(), ThrowIfNotFound, resolveScopeInfo);
    15311538    if (generator.vm()->typeProfiler()) {
    1532         generator.emitProfileType(result.get(), ProfileTypeBytecodePutToScope, &m_ident);
     1539        generator.emitProfileType(result.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_ident);
    15331540        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
    15341541    }
     
    15451552            return generator.emitNode(dst, m_right);
    15461553        }
    1547         if (local.isCaptured() || generator.vm()->typeProfiler()) {
     1554        if (local.isSpecial() || generator.vm()->typeProfiler()) {
    15481555            RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
    15491556            generator.emitNode(tempDst.get(), m_right);
     
    15611568    if (generator.isStrictMode())
    15621569        generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    1563     RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
     1570    ResolveScopeInfo resolveScopeInfo;
     1571    RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident, resolveScopeInfo);
    15641572    if (dst == generator.ignoredResult())
    15651573        dst = 0;
    15661574    RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
    15671575    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    1568     RegisterID* returnResult = generator.emitPutToScope(scope.get(), m_ident, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
     1576    RegisterID* returnResult = generator.emitPutToScope(scope.get(), m_ident, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, resolveScopeInfo);
    15691577    if (generator.vm()->typeProfiler()) {
    1570         generator.emitProfileType(result.get(), ProfileTypeBytecodePutToScope, &m_ident);
     1578        generator.emitProfileType(result.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_ident);
    15711579        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
    15721580    }
     
    16771685
    16781686        // FIXME: Maybe call emitExpressionInfo here.
    1679         if (local.isCaptured() || generator.vm()->typeProfiler()) {
     1687        if (local.isSpecial() || generator.vm()->typeProfiler()) {
    16801688            RefPtr<RegisterID> tempDst = generator.newTemporary();
    16811689            generator.emitNode(tempDst.get(), m_init);
     
    16911699        return generator.emitInitGlobalConst(m_ident, value.get());
    16921700
    1693     if (generator.codeType() != EvalCode)
     1701    if (generator.codeType() != EvalCode) {
     1702
     1703        ResolveScopeInfo resolveScopeInfo;
     1704        if (RefPtr<RegisterID> scope = generator.emitResolveConstantLocal(generator.newTemporary(), m_ident, resolveScopeInfo))
     1705            return generator.emitPutToScope(scope.get(), m_ident, value.get(), DoNotThrowIfNotFound, resolveScopeInfo);
     1706
    16941707        return value.get();
     1708    }
    16951709
    16961710    // FIXME: This will result in incorrect assignment if m_ident exists in an intervening with scope.
    1697     RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
    1698     return generator.emitPutToScope(scope.get(), m_ident, value.get(), DoNotThrowIfNotFound);
     1711    ResolveScopeInfo resolveScopeInfo;
     1712    RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident, resolveScopeInfo);
     1713    return generator.emitPutToScope(scope.get(), m_ident, value.get(), DoNotThrowIfNotFound, resolveScopeInfo);
    16991714}
    17001715
     
    17931808        generator.emitProfileType(local.get(), ProfileTypeBytecodeHasGlobalID, nullptr);
    17941809    else {
    1795         RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
    1796         RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound);
    1797         generator.emitProfileType(value.get(), ProfileTypeBytecodeGetFromScope, &m_ident);
     1810        ResolveScopeInfo resolveScopeInfo;
     1811        RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident, resolveScopeInfo);
     1812        RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound, resolveScopeInfo);
     1813        generator.emitProfileType(value.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &m_ident);
    17981814    }
    17991815
     
    19561972        const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
    19571973        Local local = generator.local(ident);
    1958         if (local.isCaptured())
    1959             return nullptr;
    19601974        return local.get();
    19611975    }
     
    19701984        const Identifier& ident = simpleBinding->boundProperty();
    19711985        Local local = generator.local(ident);
    1972         if (local.isCaptured())
     1986        if (local.isSpecial())
    19731987            return nullptr;
    19741988        return local.get();
     
    19882002            if (generator.isStrictMode())
    19892003                generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    1990             RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident);
     2004            ResolveScopeInfo resolveScopeInfo;
     2005            RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident, resolveScopeInfo);
    19912006            generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    1992             generator.emitPutToScope(scope, ident, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
     2007            generator.emitPutToScope(scope, ident, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, resolveScopeInfo);
    19932008        }
    19942009        return;
     
    20222037        const Identifier& ident = simpleBinding->boundProperty();
    20232038        Local local = generator.local(ident);
    2024         if (!local.get() || local.isCaptured()) {
     2039        if (!local.get() || local.isSpecial()) {
    20252040            assignNode->bindings()->bindValue(generator, propertyName);
    20262041            return;
     
    21842199                if (generator.isStrictMode())
    21852200                    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    2186                 RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident);
     2201                ResolveScopeInfo resolveScopeInfo;
     2202                RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident, resolveScopeInfo);
    21872203                generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    2188                 generator.emitPutToScope(scope, ident, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
     2204                generator.emitPutToScope(scope, ident, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, resolveScopeInfo);
    21892205            }
    21902206        } else if (m_lexpr->isDotAccessorNode()) {
     
    28232839    if (generator.isStrictMode())
    28242840        generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
    2825     RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), m_boundProperty);
     2841    ResolveScopeInfo resolveScopeInfo;
     2842    RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), m_boundProperty, resolveScopeInfo);
    28262843    generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
    2827     generator.emitPutToScope(scope, m_boundProperty, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
     2844    generator.emitPutToScope(scope, m_boundProperty, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, resolveScopeInfo);
    28282845    if (generator.vm()->typeProfiler()) {
    2829         generator.emitProfileType(value, ProfileTypeBytecodePutToScope, &m_boundProperty);
     2846        generator.emitProfileType(value, resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_boundProperty);
    28302847        generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
    28312848    }
Note: See TracChangeset for help on using the changeset viewer.