Changeset 174226 in webkit


Ignore:
Timestamp:
Oct 2, 2014, 1:35:58 PM (11 years ago)
Author:
oliver@apple.com
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
Files:
44 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r174224 r174226  
     12014-10-01  Oliver Hunt  <oliver@apple.com>
     2
     3        Do all closed variable access through the local lexical object
     4        https://bugs.webkit.org/show_bug.cgi?id=136869
     5
     6        Reviewed by Filip Pizlo.
     7
     8        This patch makes all reads and writes from captured registers
     9        go through the lexical record, and by doing so removes the
     10        need for record tearoff.
     11
     12        To keep the patch simple we still number variables as though
     13        they are local stack allocated registers, but ::local() will
     14        fail. When local fails we perform a generic resolve, and in
     15        that resolve we now use a ResolveScopeInfo struct to pass
     16        around information about whether a lookup is a statically
     17        known captured variable, and its location in the activation.
     18        To ensure correct behaviour during codeblock linking we also
     19        add a LocalClosureVariable resolution type.
     20
     21        To ensure correct semantics for the Arguments object, we now
     22        have to eagerly create the Arguments object for any function
     23        that uses both the Arguments object and requires a lexical
     24        record.
     25
     26        * bytecode/BytecodeList.json:
     27        * bytecode/BytecodeUseDef.h:
     28        (JSC::computeUsesForBytecodeOffset):
     29        (JSC::computeDefsForBytecodeOffset):
     30        * bytecode/CodeBlock.cpp:
     31        (JSC::CodeBlock::dumpBytecode):
     32        (JSC::CodeBlock::CodeBlock):
     33        (JSC::CodeBlock::finalizeUnconditionally):
     34        * bytecompiler/BytecodeGenerator.cpp:
     35        (JSC::BytecodeGenerator::BytecodeGenerator):
     36        (JSC::BytecodeGenerator::initializeCapturedVariable):
     37          During the entry to a function we are not yet in a position
     38          to allocate temporaries so we directly use the lexical
     39          environment register.
     40        (JSC::BytecodeGenerator::resolveCallee):
     41        (JSC::BytecodeGenerator::emitMove):
     42        (JSC::BytecodeGenerator::local):
     43        (JSC::BytecodeGenerator::constLocal):
     44        (JSC::BytecodeGenerator::emitResolveScope):
     45        (JSC::BytecodeGenerator::emitResolveConstantLocal):
     46          The two resolve scope operations could technically skip
     47          the op_resolve_scope, and simply perform
     48              op_mov dst, recordRegister
     49          but for now it seemed best to maintain the same basic
     50          behaviour.
     51        (JSC::BytecodeGenerator::emitGetFromScope):
     52        (JSC::BytecodeGenerator::emitPutToScope):
     53        (JSC::BytecodeGenerator::createArgumentsIfNecessary):
     54          If we have an environment we've already created Arguments
     55          so no need to check again.
     56        (JSC::BytecodeGenerator::emitReturn):
     57          Don't need to emit tearoff_environment
     58        * bytecompiler/BytecodeGenerator.h:
     59        (JSC::Local::Local):
     60        (JSC::Local::operator bool):
     61        (JSC::Local::get):
     62        (JSC::Local::isReadOnly):
     63        (JSC::Local::isSpecial):
     64        (JSC::ResolveScopeInfo::ResolveScopeInfo):
     65        (JSC::ResolveScopeInfo::isLocal):
     66        (JSC::ResolveScopeInfo::localIndex):
     67        (JSC::BytecodeGenerator::shouldCreateArgumentsEagerly):
     68        (JSC::Local::isCaptured): Deleted.
     69        (JSC::Local::captureMode): Deleted.
     70        * bytecompiler/NodesCodegen.cpp:
     71        (JSC::ResolveNode::emitBytecode):
     72        (JSC::EvalFunctionCallNode::emitBytecode):
     73        (JSC::FunctionCallResolveNode::emitBytecode):
     74        (JSC::PostfixNode::emitResolve):
     75        (JSC::DeleteResolveNode::emitBytecode):
     76        (JSC::TypeOfResolveNode::emitBytecode):
     77        (JSC::PrefixNode::emitResolve):
     78        (JSC::ReadModifyResolveNode::emitBytecode):
     79        (JSC::AssignResolveNode::emitBytecode):
     80        (JSC::ConstDeclNode::emitCodeSingle):
     81        (JSC::EmptyVarExpression::emitBytecode):
     82        (JSC::ForInNode::tryGetBoundLocal):
     83        (JSC::ForInNode::emitLoopHeader):
     84        (JSC::ForOfNode::emitBytecode):
     85        (JSC::BindingNode::bindValue):
     86        * dfg/DFGAbstractInterpreterInlines.h:
     87        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     88        * dfg/DFGByteCodeParser.cpp:
     89        (JSC::DFG::ByteCodeParser::parseBlock):
     90        * dfg/DFGCapabilities.cpp:
     91        (JSC::DFG::capabilityLevel):
     92        * dfg/DFGClobberize.h:
     93        (JSC::DFG::clobberize):
     94        * dfg/DFGDoesGC.cpp:
     95        (JSC::DFG::doesGC):
     96        * dfg/DFGFixupPhase.cpp:
     97        (JSC::DFG::FixupPhase::fixupNode):
     98        * dfg/DFGGraph.cpp:
     99        (JSC::DFG::Graph::tryGetRegisters):
     100        * dfg/DFGNodeType.h:
     101        * dfg/DFGPredictionPropagationPhase.cpp:
     102        (JSC::DFG::PredictionPropagationPhase::propagate):
     103        * dfg/DFGSafeToExecute.h:
     104        (JSC::DFG::safeToExecute):
     105        * dfg/DFGSpeculativeJIT32_64.cpp:
     106        (JSC::DFG::SpeculativeJIT::compile):
     107        * dfg/DFGSpeculativeJIT64.cpp:
     108        (JSC::DFG::SpeculativeJIT::compile):
     109        * ftl/FTLCapabilities.cpp:
     110        (JSC::FTL::canCompile):
     111        * interpreter/Interpreter.cpp:
     112        (JSC::unwindCallFrame):
     113        * jit/JIT.cpp:
     114        (JSC::JIT::privateCompileMainPass):
     115        (JSC::JIT::privateCompileSlowCases):
     116        * jit/JIT.h:
     117        * jit/JITOpcodes.cpp:
     118        (JSC::JIT::emit_op_captured_mov): Deleted.
     119        (JSC::JIT::emit_op_tear_off_lexical_environment): Deleted.
     120        (JSC::JIT::emitSlow_op_captured_mov): Deleted.
     121        * jit/JITOpcodes32_64.cpp:
     122        (JSC::JIT::emit_op_captured_mov): Deleted.
     123        (JSC::JIT::emit_op_tear_off_lexical_environment): Deleted.
     124        * jit/JITOperations.cpp:
     125        * jit/JITOperations.h:
     126        * jit/JITPropertyAccess.cpp:
     127        (JSC::JIT::emit_op_resolve_scope):
     128        (JSC::JIT::emit_op_get_from_scope):
     129        (JSC::JIT::emitPutClosureVar):
     130        (JSC::JIT::emit_op_put_to_scope):
     131        (JSC::JIT::emitSlow_op_put_to_scope):
     132        * jit/JITPropertyAccess32_64.cpp:
     133        (JSC::JIT::emit_op_resolve_scope):
     134        (JSC::JIT::emit_op_get_from_scope):
     135        (JSC::JIT::emitPutClosureVar):
     136        (JSC::JIT::emit_op_put_to_scope):
     137        (JSC::JIT::emitSlow_op_put_to_scope):
     138        * llint/LLIntData.cpp:
     139        (JSC::LLInt::Data::performAssertions):
     140        * llint/LLIntSlowPaths.cpp:
     141        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     142        * llint/LLIntSlowPaths.h:
     143        * llint/LowLevelInterpreter.asm:
     144        * llint/LowLevelInterpreter32_64.asm:
     145        * llint/LowLevelInterpreter64.asm:
     146        * runtime/Arguments.cpp:
     147        (JSC::Arguments::tearOff):
     148        * runtime/Arguments.h:
     149        (JSC::Arguments::argument):
     150        * runtime/CommonSlowPaths.cpp:
     151        (JSC::SLOW_PATH_DECL): Deleted.
     152        * runtime/CommonSlowPaths.h:
     153        * runtime/JSLexicalEnvironment.cpp:
     154        (JSC::JSLexicalEnvironment::visitChildren):
     155        (JSC::JSLexicalEnvironment::symbolTableGet):
     156        (JSC::JSLexicalEnvironment::symbolTablePut):
     157        (JSC::JSLexicalEnvironment::getOwnNonIndexPropertyNames):
     158        (JSC::JSLexicalEnvironment::getOwnPropertySlot):
     159        (JSC::JSLexicalEnvironment::argumentsGetter):
     160        * runtime/JSLexicalEnvironment.h:
     161        (JSC::JSLexicalEnvironment::create):
     162        (JSC::JSLexicalEnvironment::JSLexicalEnvironment):
     163        (JSC::JSLexicalEnvironment::tearOff): Deleted.
     164        (JSC::JSLexicalEnvironment::isTornOff): Deleted.
     165        * runtime/JSScope.cpp:
     166        (JSC::resolveTypeName):
     167        * runtime/JSScope.h:
     168        (JSC::makeType):
     169        (JSC::needsVarInjectionChecks):
     170        * runtime/WriteBarrier.h:
     171        (JSC::WriteBarrier<Unknown>::WriteBarrier):
     172
    11732014-10-02  Filip Pizlo  <fpizlo@apple.com>
    2174
  • trunk/Source/JavaScriptCore/bytecode/BytecodeList.json

    r174216 r174226  
    1818            { "name" : "op_new_regexp", "length" : 3 },
    1919            { "name" : "op_mov", "length" : 3 },
    20             { "name" : "op_captured_mov", "length" : 4 },
    2120            { "name" : "op_not", "length" : 3 },
    2221            { "name" : "op_eq", "length" : 4 },
     
    10099            { "name" : "op_call_eval", "length" : 9 },
    101100            { "name" : "op_call_varargs", "length" : 9 },
    102             { "name" : "op_tear_off_lexical_environment", "length" : 2 },
    103101            { "name" : "op_tear_off_arguments", "length" : 3 },
    104102            { "name" : "op_ret", "length" : 2 },
  • trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h

    r173517 r174226  
    6363    case op_create_arguments:
    6464    case op_to_this:
    65     case op_tear_off_lexical_environment:
    6665    case op_profile_will_call:
    6766    case op_profile_did_call:
     
    142141    case op_not:
    143142    case op_mov:
    144     case op_captured_mov:
    145143    case op_new_array_with_size:
    146144    case op_create_this:
     
    306304    case op_resolve_scope:
    307305    case op_strcat:
    308     case op_tear_off_lexical_environment:
    309306    case op_to_primitive:
    310307    case op_catch:
     
    366363    case op_not:
    367364    case op_mov:
    368     case op_captured_mov:
    369365    case op_new_object:
    370366    case op_to_this:
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r173797 r174226  
    834834            break;
    835835        }
    836         case op_captured_mov: {
    837             int r0 = (++it)->u.operand;
    838             int r1 = (++it)->u.operand;
    839             printLocationAndOp(out, exec, location, it, "captured_mov");
    840             out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
    841             ++it;
    842             break;
    843         }
    844836        case op_profile_type: {
    845837            int r0 = (++it)->u.operand;
     
    13171309            break;
    13181310        }
    1319            
    1320         case op_tear_off_lexical_environment: {
    1321             int r0 = (++it)->u.operand;
    1322             printLocationOpAndRegisterOperand(out, exec, location, it, "tear_off_lexical_environment", r0);
    1323             break;
    1324         }
     1311
    13251312        case op_tear_off_arguments: {
    13261313            int r0 = (++it)->u.operand;
     
    19471934            const Identifier& ident = identifier(pc[2].u.operand);
    19481935            ResolveType type = static_cast<ResolveType>(pc[3].u.operand);
     1936            if (type == LocalClosureVar) {
     1937                instructions[i + 3].u.operand = ClosureVar;
     1938                break;
     1939            }
    19491940
    19501941            ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), needsActivation(), scope, ident, Get, type);
     
    19631954
    19641955            // get_from_scope dst, scope, id, ResolveModeAndType, Structure, Operand
     1956
    19651957            const Identifier& ident = identifier(pc[3].u.operand);
    19661958            ResolveModeAndType modeAndType = ResolveModeAndType(pc[4].u.operand);
     1959            if (modeAndType.type() == LocalClosureVar) {
     1960                instructions[i + 4] = ResolveModeAndType(modeAndType.mode(), ClosureVar).operand();
     1961                break;
     1962            }
     1963
    19671964            ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), needsActivation(), scope, ident, Get, modeAndType.type());
    19681965
     
    19801977            // put_to_scope scope, id, value, ResolveModeAndType, Structure, Operand
    19811978            const Identifier& ident = identifier(pc[2].u.operand);
     1979
    19821980            ResolveModeAndType modeAndType = ResolveModeAndType(pc[4].u.operand);
     1981            if (modeAndType.type() == LocalClosureVar) {
     1982                if (pc[5].u.index == UINT_MAX) {
     1983                    instructions[i + 5].u.watchpointSet = 0;
     1984                    break;
     1985                }
     1986                StringImpl* uid = identifier(pc[5].u.index).impl();
     1987                RELEASE_ASSERT(didCloneSymbolTable);
     1988                if (ident != m_vm->propertyNames->arguments) {
     1989                    ConcurrentJITLocker locker(m_symbolTable->m_lock);
     1990                    SymbolTable::Map::iterator iter = m_symbolTable->find(locker, uid);
     1991                    ASSERT(iter != m_symbolTable->end(locker));
     1992                    iter->value.prepareToWatch(symbolTable());
     1993                    instructions[i + 5].u.watchpointSet = iter->value.watchpointSet();
     1994                } else
     1995                    instructions[i + 5].u.watchpointSet = nullptr;
     1996                break;
     1997            }
     1998
    19831999            ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), needsActivation(), scope, ident, Put, modeAndType.type());
    19842000
     
    20322048                break;
    20332049            }
     2050            case ProfileTypeBytecodePutToLocalScope:
     2051            case ProfileTypeBytecodeGetFromLocalScope: {
     2052                const Identifier& ident = identifier(pc[4].u.operand);
     2053                symbolTable = m_symbolTable.get();
     2054                ConcurrentJITLocker locker(symbolTable->m_lock);
     2055                // If our parent scope was created while profiling was disabled, it will not have prepared for profiling yet.
     2056                symbolTable->prepareForTypeProfiling(locker);
     2057                globalVariableID = symbolTable->uniqueIDForVariable(locker, ident.impl(), *vm());
     2058                globalTypeSet = symbolTable->globalTypeSetForVariable(locker, ident.impl(), *vm());
     2059
     2060                break;
     2061            }
     2062
    20342063            case ProfileTypeBytecodeHasGlobalID: {
    20352064                symbolTable = m_symbolTable.get();
     
    20762105        }
    20772106
    2078         case op_captured_mov:
    20792107        case op_new_captured_func: {
    20802108            if (pc[3].u.index == UINT_MAX) {
     
    25472575                ResolveModeAndType modeAndType =
    25482576                    ResolveModeAndType(curInstruction[4].u.operand);
    2549                 if (modeAndType.type() == GlobalVar || modeAndType.type() == GlobalVarWithVarInjectionChecks)
     2577                if (modeAndType.type() == GlobalVar || modeAndType.type() == GlobalVarWithVarInjectionChecks || modeAndType.type() == LocalClosureVar)
    25502578                    continue;
    25512579                WriteBarrierBase<Structure>& structure = curInstruction[5].u.structure;
     
    38693897        switch (opcodeID) {
    38703898        case op_enter:
    3871         case op_captured_mov:
    38723899        case op_init_lazy_reg:
    38733900        case op_create_arguments:
     
    38773904            break;
    38783905        }
    3879        
     3906
    38803907        VirtualRegister virtualReg(operand);
    38813908        if (!virtualReg.isLocal())
    38823909            return;
    3883        
     3910
     3911        if (codeBlock->usesArguments() && virtualReg == codeBlock->argumentsRegister())
     3912            return;
     3913
    38843914        if (codeBlock->captureCount() && codeBlock->symbolTable()->isCaptured(operand)) {
    38853915            codeBlock->beginValidationDidFail();
  • 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    }
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r174167 r174226  
    13001300        break;
    13011301       
    1302     case TearOffActivation:
    13031302    case TearOffArguments:
    13041303        // Does nothing that is user-visible.
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r174167 r174226  
    26312631            NEXT_OPCODE(op_mov);
    26322632        }
    2633            
    2634         case op_captured_mov: {
    2635             Node* op = get(VirtualRegister(currentInstruction[2].u.operand));
    2636             if (VariableWatchpointSet* set = currentInstruction[3].u.watchpointSet) {
    2637                 if (set->state() != IsInvalidated)
    2638                     addToGraph(NotifyWrite, OpInfo(set), op);
    2639             }
    2640             set(VirtualRegister(currentInstruction[1].u.operand), op);
    2641             NEXT_OPCODE(op_captured_mov);
    2642         }
    26432633
    26442634        case op_check_has_instance:
     
    31973187                set(VirtualRegister(dst), weakJSConstant(m_inlineStackTop->m_codeBlock->globalObject()));
    31983188                break;
     3189            case LocalClosureVar:
    31993190            case ClosureVar:
    32003191            case ClosureVarWithVarInjectionChecks: {
     
    32723263                break;
    32733264            }
     3265            case LocalClosureVar:
    32743266            case ClosureVar:
    32753267            case ClosureVarWithVarInjectionChecks: {
     
    33153307            {
    33163308                ConcurrentJITLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
    3317                 if (resolveType == GlobalVar || resolveType == GlobalVarWithVarInjectionChecks)
     3309                if (resolveType == GlobalVar || resolveType == GlobalVarWithVarInjectionChecks || resolveType == LocalClosureVar)
    33183310                    watchpoints = currentInstruction[5].u.watchpointSet;
    33193311                else
     
    33543346                break;
    33553347            }
     3348            case LocalClosureVar:
    33563349            case ClosureVar:
    33573350            case ClosureVarWithVarInjectionChecks: {
    33583351                Node* scopeNode = get(VirtualRegister(scope));
    33593352                Node* scopeRegisters = addToGraph(GetClosureRegisters, scopeNode);
    3360                 addToGraph(PutClosureVar, OpInfo(operand), scopeNode, scopeRegisters, get(VirtualRegister(value)));
     3353                Node* valueNode = get(VirtualRegister(value));
     3354
     3355                if (watchpoints && watchpoints->state() != IsInvalidated)
     3356                    addToGraph(NotifyWrite, OpInfo(watchpoints), valueNode);
     3357
     3358                addToGraph(PutClosureVar, OpInfo(operand), scopeNode, scopeRegisters, valueNode);
    33613359                break;
    33623360            }
     
    34063404            set(unmodifiedArgumentsRegister(VirtualRegister(currentInstruction[1].u.operand)), createArguments);
    34073405            NEXT_OPCODE(op_create_arguments);
    3408         }
    3409            
    3410         case op_tear_off_lexical_environment: {
    3411             addToGraph(TearOffActivation, get(VirtualRegister(currentInstruction[1].u.operand)));
    3412             NEXT_OPCODE(op_tear_off_lexical_environment);
    34133406        }
    34143407
  • trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp

    r174167 r174226  
    123123    case op_profile_type:
    124124    case op_mov:
    125     case op_captured_mov:
    126125    case op_check_has_instance:
    127126    case op_instanceof:
     
    233232    case op_new_regexp:
    234233    case op_create_lexical_environment:
    235     case op_tear_off_lexical_environment:
    236234    case op_new_func:
    237235    case op_new_captured_func:
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r174167 r174226  
    849849            return;
    850850        }
    851 
    852     case TearOffActivation:
    853         read(Variables);
    854         write(JSEnvironmentRecord_registers);
    855         return;
    856851       
    857852    case TearOffArguments:
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r174167 r174226  
    139139    case ToString:
    140140    case In:
    141     case TearOffActivation:
    142141    case PhantomArguments:
    143142    case TearOffArguments:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r174167 r174226  
    10371037                SpecNone, StoreBarrier, m_currentNode->origin,
    10381038                Edge(globalObjectNode, KnownCellUse));
    1039             m_insertionSet.insert(m_indexInBlock, barrierNode);
    1040             break;
    1041         }
    1042 
    1043         case TearOffActivation: {
    1044             Node* barrierNode = m_graph.addNode(
    1045                 SpecNone, StoreBarrierWithNullCheck, m_currentNode->origin,
    1046                 Edge(node->child1().node(), UntypedUse));
    10471039            m_insertionSet.insert(m_indexInBlock, barrierNode);
    10481040            break;
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r174224 r174226  
    10141014    if (!lexicalEnvironment)
    10151015        return 0;
    1016     if (!lexicalEnvironment->isTornOff())
    1017         return 0;
    10181016    return lexicalEnvironment->registers();
    10191017}
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r174167 r174226  
    264264    /* being threaded with each other. */\
    265265    macro(CreateActivation, NodeResultJS) \
    266     macro(TearOffActivation, NodeMustGenerate) \
    267266    \
    268267    /* Nodes used for arguments. Similar to lexical environment support, only it makes even less */\
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r174167 r174226  
    657657        case CheckBadCell:
    658658        case PutStructure:
    659         case TearOffActivation:
    660659        case TearOffArguments:
    661660        case CheckArgumentsNotCreated:
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r174167 r174226  
    218218    case In:
    219219    case CreateActivation:
    220     case TearOffActivation:
    221220    case CreateArguments:
    222221    case PhantomArguments:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r174167 r174226  
    41714171
    41724172    case CreateActivation: {
    4173         JSValueOperand value(this, node->child1());
    4174         GPRTemporary result(this, Reuse, value, PayloadWord);
    4175        
    4176         GPRReg valueTagGPR = value.tagGPR();
    4177         GPRReg valuePayloadGPR = value.payloadGPR();
     4173        GPRTemporary result(this);
    41784174        GPRReg resultGPR = result.gpr();
    4179        
    4180         m_jit.move(valuePayloadGPR, resultGPR);
    4181        
    4182         JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
    4183        
    4184         addSlowPathGenerator(
    4185             slowPathCall(
    4186                 notCreated, this, operationCreateActivation, resultGPR,
    4187                 framePointerOffsetToGetActivationRegisters()));
     4175
     4176        flushRegisters();
     4177        callOperation(operationCreateActivation, resultGPR, framePointerOffsetToGetActivationRegisters());
    41884178       
    41894179        cellResult(resultGPR, node);
     
    42404230        alreadyCreated.link(&m_jit);
    42414231        cellResult(resultGPR, node);
    4242         break;
    4243     }
    4244        
    4245     case TearOffActivation: {
    4246         JSValueOperand activationValue(this, node->child1());
    4247         GPRTemporary scratch(this);
    4248        
    4249         GPRReg activationValueTagGPR = activationValue.tagGPR();
    4250         GPRReg activationValuePayloadGPR = activationValue.payloadGPR();
    4251         GPRReg scratchGPR = scratch.gpr();
    4252 
    4253         JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, activationValueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
    4254 
    4255         SymbolTable* symbolTable = m_jit.symbolTableFor(node->origin.semantic);
    4256         int registersOffset = JSLexicalEnvironment::registersOffset(symbolTable);
    4257 
    4258         int bytecodeCaptureStart = symbolTable->captureStart();
    4259         int machineCaptureStart = m_jit.graph().m_machineCaptureStart;
    4260         for (int i = symbolTable->captureCount(); i--;) {
    4261             m_jit.loadPtr(
    4262                 JITCompiler::Address(
    4263                     GPRInfo::callFrameRegister, (machineCaptureStart - i) * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)),
    4264                 scratchGPR);
    4265             m_jit.storePtr(
    4266                 scratchGPR, JITCompiler::Address(
    4267                     activationValuePayloadGPR, registersOffset + (bytecodeCaptureStart - i) * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
    4268             m_jit.loadPtr(
    4269                 JITCompiler::Address(
    4270                     GPRInfo::callFrameRegister, (machineCaptureStart - i) * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)),
    4271                 scratchGPR);
    4272             m_jit.storePtr(
    4273                 scratchGPR, JITCompiler::Address(
    4274                     activationValuePayloadGPR, registersOffset + (bytecodeCaptureStart - i) * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
    4275         }
    4276         m_jit.addPtr(TrustedImm32(registersOffset), activationValuePayloadGPR, scratchGPR);
    4277         m_jit.storePtr(scratchGPR, JITCompiler::Address(activationValuePayloadGPR, JSLexicalEnvironment::offsetOfRegisters()));
    4278        
    4279         notCreated.link(&m_jit);
    4280         noResult(node);
    42814232        break;
    42824233    }
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r174167 r174226  
    42374237        DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame);
    42384238       
    4239         JSValueOperand value(this, node->child1());
    4240         GPRTemporary result(this, Reuse, value);
    4241        
    4242         GPRReg valueGPR = value.gpr();
     4239        GPRTemporary result(this);
    42434240        GPRReg resultGPR = result.gpr();
    4244        
    4245         m_jit.move(valueGPR, resultGPR);
    4246        
    4247         JITCompiler::Jump notCreated = m_jit.branchTest64(JITCompiler::Zero, resultGPR);
    4248        
    4249         addSlowPathGenerator(
    4250             slowPathCall(
    4251                 notCreated, this, operationCreateActivation, resultGPR,
    4252                 framePointerOffsetToGetActivationRegisters()));
    4253        
     4241   
     4242        flushRegisters();
     4243        callOperation(operationCreateActivation, resultGPR, framePointerOffsetToGetActivationRegisters());
     4244
    42544245        cellResult(resultGPR, node);
    42554246        break;
     
    43044295        alreadyCreated.link(&m_jit);
    43054296        cellResult(resultGPR, node);
    4306         break;
    4307     }
    4308 
    4309     case TearOffActivation: {
    4310         DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame);
    4311 
    4312         JSValueOperand activationValue(this, node->child1());
    4313         GPRTemporary scratch(this);
    4314         GPRReg activationValueGPR = activationValue.gpr();
    4315         GPRReg scratchGPR = scratch.gpr();
    4316 
    4317         JITCompiler::Jump notCreated = m_jit.branchTest64(JITCompiler::Zero, activationValueGPR);
    4318 
    4319         SymbolTable* symbolTable = m_jit.symbolTableFor(node->origin.semantic);
    4320         int registersOffset = JSLexicalEnvironment::registersOffset(symbolTable);
    4321 
    4322         int bytecodeCaptureStart = symbolTable->captureStart();
    4323         int machineCaptureStart = m_jit.graph().m_machineCaptureStart;
    4324         for (int i = symbolTable->captureCount(); i--;) {
    4325             m_jit.load64(
    4326                 JITCompiler::Address(
    4327                     GPRInfo::callFrameRegister,
    4328                     (machineCaptureStart - i) * sizeof(Register)),
    4329                 scratchGPR);
    4330             m_jit.store64(
    4331                 scratchGPR,
    4332                 JITCompiler::Address(
    4333                     activationValueGPR,
    4334                     registersOffset + (bytecodeCaptureStart - i) * sizeof(Register)));
    4335         }
    4336         m_jit.addPtr(TrustedImm32(registersOffset), activationValueGPR, scratchGPR);
    4337         m_jit.storePtr(scratchGPR, JITCompiler::Address(activationValueGPR, JSLexicalEnvironment::offsetOfRegisters()));
    4338 
    4339         notCreated.link(&m_jit);
    4340         noResult(node);
    43414297        break;
    43424298    }
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r174165 r174226  
    370370    if (graph.m_codeBlock->needsActivation()) {
    371371        // Need this because although we also don't support
    372         // CreateActivation/TearOffActivation, we might not see those nodes in case of
     372        // CreateActivation, we might not see those nodes in case of
    373373        // OSR entry.
    374374        // FIXME: Support activations.
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r173600 r174226  
    440440    CallFrame* callFrame = visitor->callFrame();
    441441    CodeBlock* codeBlock = visitor->codeBlock();
    442     JSScope* scope = callFrame->scope();
    443 
    444442    if (Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger()) {
    445443        ClearExceptionScope scope(&callFrame->vm());
     
    456454        RELEASE_ASSERT(!visitor->isInlinedFrame());
    457455#endif
    458         lexicalEnvironment = callFrame->uncheckedActivation();
    459         // Protect against the lexical environment not being created, or the variable still being
    460         // initialized to Undefined inside op_enter.
    461         if (lexicalEnvironment && lexicalEnvironment.isCell()) {
    462             JSLexicalEnvironment* activationObject = jsCast<JSLexicalEnvironment*>(lexicalEnvironment);
    463             // Protect against throwing exceptions after tear-off.
    464             if (!activationObject->isTornOff())
    465                 activationObject->tearOff(*scope->vm());
    466         }
    467456    }
    468457
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r173517 r174226  
    248248        DEFINE_OP(op_lshift)
    249249        DEFINE_OP(op_mod)
    250         DEFINE_OP(op_captured_mov)
    251250        DEFINE_OP(op_mov)
    252251        DEFINE_OP(op_mul)
     
    297296        DEFINE_OP(op_switch_imm)
    298297        DEFINE_OP(op_switch_string)
    299         DEFINE_OP(op_tear_off_lexical_environment)
    300298        DEFINE_OP(op_tear_off_arguments)
    301299        DEFINE_OP(op_throw)
     
    385383        DEFINE_SLOWCASE_OP(op_to_this)
    386384        DEFINE_SLOWCASE_OP(op_create_this)
    387         DEFINE_SLOWCASE_OP(op_captured_mov)
    388385        DEFINE_SLOWCASE_OP(op_div)
    389386        DEFINE_SLOWCASE_OP(op_eq)
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r174216 r174226  
    464464        void emit_op_call_varargs(Instruction*);
    465465        void emit_op_construct_varargs(Instruction*);
    466         void emit_op_captured_mov(Instruction*);
    467466        void emit_op_catch(Instruction*);
    468467        void emit_op_construct(Instruction*);
     
    544543        void emit_op_switch_imm(Instruction*);
    545544        void emit_op_switch_string(Instruction*);
    546         void emit_op_tear_off_lexical_environment(Instruction*);
    547545        void emit_op_tear_off_arguments(Instruction*);
    548546        void emit_op_throw(Instruction*);
     
    571569        void emitSlow_op_call_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&);
    572570        void emitSlow_op_construct_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&);
    573         void emitSlow_op_captured_mov(Instruction*, Vector<SlowCaseEntry>::iterator&);
    574571        void emitSlow_op_construct(Instruction*, Vector<SlowCaseEntry>::iterator&);
    575572        void emitSlow_op_to_this(Instruction*, Vector<SlowCaseEntry>::iterator&);
     
    641638#endif
    642639        void emitPutGlobalVar(uintptr_t operand, int value, VariableWatchpointSet*);
    643         void emitPutClosureVar(int scope, uintptr_t operand, int value);
     640        void emitPutClosureVar(int scope, uintptr_t operand, int value, VariableWatchpointSet*);
    644641
    645642        void emitInitRegister(int dst);
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r174216 r174226  
    6464}
    6565
    66 void JIT::emit_op_captured_mov(Instruction* currentInstruction)
    67 {
    68     int dst = currentInstruction[1].u.operand;
    69     int src = currentInstruction[2].u.operand;
    70 
    71     emitGetVirtualRegister(src, regT0);
    72     emitNotifyWrite(regT0, regT1, currentInstruction[3].u.watchpointSet);
    73     emitPutVirtualRegister(dst);
    74 }
    7566
    7667void JIT::emit_op_end(Instruction* currentInstruction)
     
    232223    done.link(this);
    233224    emitPutVirtualRegister(dst);
    234 }
    235 
    236 void JIT::emit_op_tear_off_lexical_environment(Instruction* currentInstruction)
    237 {
    238     int lexicalEnvironment = currentInstruction[1].u.operand;
    239     Jump activationNotCreated = branchTest64(Zero, addressFor(lexicalEnvironment));
    240     emitGetVirtualRegister(lexicalEnvironment, regT0);
    241     callOperation(operationTearOffActivation, regT0);
    242     activationNotCreated.link(this);
    243225}
    244226
     
    10991081    const JSValue* values = codeBlock()->constantBuffer(valuesIndex);
    11001082    callOperation(operationNewArrayBufferWithProfile, dst, currentInstruction[4].u.arrayAllocationProfile, values, size);
    1101 }
    1102 
    1103 void JIT::emitSlow_op_captured_mov(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    1104 {
    1105     VariableWatchpointSet* set = currentInstruction[3].u.watchpointSet;
    1106     if (!set || set->state() == IsInvalidated)
    1107         return;
    1108 #if USE(JSVALUE32_64)
    1109     linkSlowCase(iter);
    1110 #endif
    1111     linkSlowCase(iter);
    1112     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_captured_mov);
    1113     slowPathCall.call();
    11141083}
    11151084
  • trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r174216 r174226  
    154154}
    155155
    156 void JIT::emit_op_captured_mov(Instruction* currentInstruction)
    157 {
    158     int dst = currentInstruction[1].u.operand;
    159     int src = currentInstruction[2].u.operand;
    160 
    161     emitLoad(src, regT1, regT0);
    162     emitNotifyWrite(regT1, regT0, regT2, currentInstruction[3].u.watchpointSet);
    163     emitStore(dst, regT1, regT0);
    164 }
    165 
    166156void JIT::emit_op_end(Instruction* currentInstruction)
    167157{
     
    349339    done.link(this);
    350340    emitStoreBool(dst, regT0);
    351 }
    352 
    353 void JIT::emit_op_tear_off_lexical_environment(Instruction* currentInstruction)
    354 {
    355     int lexicalEnvironment = currentInstruction[1].u.operand;
    356     Jump activationNotCreated = branch32(Equal, tagFor(lexicalEnvironment), TrustedImm32(JSValue::EmptyValueTag));
    357     emitLoadPayload(lexicalEnvironment, regT0);
    358     callOperation(operationTearOffActivation, regT0);
    359     activationNotCreated.link(this);
    360341}
    361342
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r174216 r174226  
    15901590    return JSValue::encode(result);
    15911591}
    1592    
    1593 void JIT_OPERATION operationTearOffActivation(ExecState* exec, JSCell* activationCell)
    1594 {
    1595     VM& vm = exec->vm();
    1596     NativeCallFrameTracer tracer(&vm, exec);
    1597 
    1598     ASSERT(exec->codeBlock()->needsActivation());
    1599     jsCast<JSLexicalEnvironment*>(activationCell)->tearOff(vm);
    1600 }
    16011592
    16021593void JIT_OPERATION operationTearOffArguments(ExecState* exec, JSCell* argumentsCell, JSCell* activationCell)
     
    17721763    JSValue value = exec->r(pc[3].u.operand).jsValue();
    17731764    ResolveModeAndType modeAndType = ResolveModeAndType(pc[4].u.operand);
    1774 
     1765    if (modeAndType.type() == LocalClosureVar) {
     1766        JSLexicalEnvironment* environment = jsCast<JSLexicalEnvironment*>(scope);
     1767        environment->registerAt(pc[6].u.operand).set(vm, environment, value);
     1768        if (VariableWatchpointSet* set = pc[5].u.watchpointSet)
     1769            set->notifyWrite(vm, value, "Executed op_put_scope<LocalClosureVar>");
     1770        return;
     1771    }
    17751772    if (modeAndType.mode() == ThrowIfNotFound && !scope->hasProperty(exec, ident)) {
    17761773        exec->vm().throwException(exec, createUndefinedVariableError(exec, ident));
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r174216 r174226  
    293293EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript) WTF_INTERNAL;
    294294EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript) WTF_INTERNAL;
    295 void JIT_OPERATION operationTearOffActivation(ExecState*, JSCell*) WTF_INTERNAL;
    296295void JIT_OPERATION operationTearOffArguments(ExecState*, JSCell*, JSCell*) WTF_INTERNAL;
    297296EncodedJSValue JIT_OPERATION operationDeleteById(ExecState*, EncodedJSValue base, const Identifier*) WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r173490 r174226  
    622622        addSlowCase(jump());
    623623        break;
     624    case LocalClosureVar:
     625        RELEASE_ASSERT_NOT_REACHED();
    624626    }
    625627}
     
    692694        addSlowCase(jump());
    693695        break;
     696    case LocalClosureVar:
     697        RELEASE_ASSERT_NOT_REACHED();
    694698    }
    695699    emitPutVirtualRegister(dst);
     
    739743}
    740744
    741 void JIT::emitPutClosureVar(int scope, uintptr_t operand, int value)
     745void JIT::emitPutClosureVar(int scope, uintptr_t operand, int value, VariableWatchpointSet* set)
    742746{
    743747    emitGetVirtualRegister(value, regT1);
    744748    emitGetVirtualRegister(scope, regT0);
    745749    loadPtr(Address(regT0, JSEnvironmentRecord::offsetOfRegisters()), regT0);
     750    emitNotifyWrite(regT1, regT2, set);
    746751    storePtr(regT1, Address(regT0, operand * sizeof(Register)));
    747752}
     
    768773        emitPutGlobalVar(*operandSlot, value, currentInstruction[5].u.watchpointSet);
    769774        break;
     775    case LocalClosureVar:
    770776    case ClosureVar:
    771777    case ClosureVarWithVarInjectionChecks:
    772778        emitWriteBarrier(scope, value, ShouldFilterValue);
    773779        emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
    774         emitPutClosureVar(scope, *operandSlot, value);
     780        emitPutClosureVar(scope, *operandSlot, value, currentInstruction[5].u.watchpointSet);
    775781        break;
    776782    case Dynamic:
     
    784790    ResolveType resolveType = ResolveModeAndType(currentInstruction[4].u.operand).type();
    785791    unsigned linkCount = 0;
    786     if (resolveType != GlobalVar && resolveType != ClosureVar)
     792    if (resolveType != GlobalVar && resolveType != ClosureVar && resolveType != LocalClosureVar)
    787793        linkCount++;
    788     if ((resolveType == GlobalVar || resolveType == GlobalVarWithVarInjectionChecks)
     794    if ((resolveType == GlobalVar || resolveType == GlobalVarWithVarInjectionChecks || resolveType == LocalClosureVar)
    789795        && currentInstruction[5].u.watchpointSet->state() != IsInvalidated)
    790796        linkCount++;
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r173490 r174226  
    646646        addSlowCase(jump());
    647647        break;
     648    case LocalClosureVar:
     649        RELEASE_ASSERT_NOT_REACHED();
    648650    }
    649651}
     
    717719        addSlowCase(jump());
    718720        break;
     721    case LocalClosureVar:
     722        RELEASE_ASSERT_NOT_REACHED();
    719723    }
    720724    emitValueProfilingSite();
     
    770774}
    771775
    772 void JIT::emitPutClosureVar(int scope, uintptr_t operand, int value)
     776void JIT::emitPutClosureVar(int scope, uintptr_t operand, int value, VariableWatchpointSet* set)
    773777{
    774778    emitLoad(value, regT3, regT2);
    775779    emitLoad(scope, regT1, regT0);
     780    emitNotifyWrite(regT3, regT2, regT4, set);
    776781    loadPtr(Address(regT0, JSEnvironmentRecord::offsetOfRegisters()), regT0);
    777782    store32(regT3, Address(regT0, operand * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
     
    800805        emitPutGlobalVar(*operandSlot, value, currentInstruction[5].u.watchpointSet);
    801806        break;
     807    case LocalClosureVar:
    802808    case ClosureVar:
    803809    case ClosureVarWithVarInjectionChecks:
    804810        emitWriteBarrier(scope, value, ShouldFilterValue);
    805811        emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
    806         emitPutClosureVar(scope, *operandSlot, value);
     812        emitPutClosureVar(scope, *operandSlot, value, currentInstruction[5].u.watchpointSet);
    807813        break;
    808814    case Dynamic:
     
    816822    ResolveType resolveType = ResolveModeAndType(currentInstruction[4].u.operand).type();
    817823    unsigned linkCount = 0;
    818     if (resolveType != GlobalVar && resolveType != ClosureVar)
     824    if (resolveType != GlobalVar && resolveType != ClosureVar && resolveType != LocalClosureVar)
    819825        linkCount++;
    820     if ((resolveType == GlobalVar || resolveType == GlobalVarWithVarInjectionChecks)
     826    if ((resolveType == GlobalVar || resolveType == GlobalVarWithVarInjectionChecks || resolveType == LocalClosureVar)
    821827        && currentInstruction[5].u.watchpointSet->state() != IsInvalidated)
    822828        linkCount += 2;
  • trunk/Source/JavaScriptCore/llint/LLIntData.cpp

    r171660 r174226  
    144144    ASSERT(FunctionCode == 2);
    145145
    146     ASSERT(GlobalProperty == 0);
    147     ASSERT(GlobalVar == 1);
    148     ASSERT(ClosureVar == 2);
    149     ASSERT(GlobalPropertyWithVarInjectionChecks == 3);
    150     ASSERT(GlobalVarWithVarInjectionChecks == 4);
    151     ASSERT(ClosureVarWithVarInjectionChecks == 5);
    152     ASSERT(Dynamic == 6);
     146    static_assert(GlobalProperty == 0, "LLInt assumes GlobalProperty ResultType is == 0");
     147    static_assert(GlobalVar == 1, "LLInt assumes GlobalVar ResultType is == 1");
     148    static_assert(ClosureVar == 2, "LLInt assumes ClosureVar ResultType is == 2");
     149    static_assert(LocalClosureVar == 3, "LLInt assumes LocalClosureVar ResultType is == 3");
     150    static_assert(GlobalPropertyWithVarInjectionChecks == 4, "LLInt assumes GlobalPropertyWithVarInjectionChecks ResultType is == 4");
     151    static_assert(GlobalVarWithVarInjectionChecks == 5, "LLInt assumes GlobalVarWithVarInjectionChecks ResultType is == 5");
     152    static_assert(ClosureVarWithVarInjectionChecks == 6, "LLInt assumes ClosureVarWithVarInjectionChecks ResultType is == 6");
     153    static_assert(Dynamic == 7, "LLInt assumes Dynamic ResultType is == 7");
    153154   
    154155    ASSERT(ResolveModeAndType::mask == 0xffff);
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r174216 r174226  
    12461246}
    12471247
    1248 LLINT_SLOW_PATH_DECL(slow_path_tear_off_lexical_environment)
    1249 {
    1250     LLINT_BEGIN();
    1251     ASSERT(exec->codeBlock()->needsActivation());
    1252     jsCast<JSLexicalEnvironment*>(LLINT_OP(1).jsValue())->tearOff(vm);
    1253     LLINT_END();
    1254 }
    1255 
    12561248LLINT_SLOW_PATH_DECL(slow_path_tear_off_arguments)
    12571249{
     
    14121404    JSValue value = LLINT_OP_C(3).jsValue();
    14131405    ResolveModeAndType modeAndType = ResolveModeAndType(pc[4].u.operand);
     1406    if (modeAndType.type() == LocalClosureVar) {
     1407        JSLexicalEnvironment* environment = jsCast<JSLexicalEnvironment*>(scope);
     1408        environment->registerAt(pc[6].u.operand).set(vm, environment, value);
     1409        if (VariableWatchpointSet* set = pc[5].u.watchpointSet)
     1410            set->notifyWrite(vm, value, "Executed op_put_scope<LocalClosureVar>");
     1411        LLINT_END();
     1412    }
    14141413
    14151414    if (modeAndType.mode() == ThrowIfNotFound && !scope->hasProperty(exec, ident))
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h

    r173517 r174226  
    103103LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_construct_varargs);
    104104LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_call_eval);
    105 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_tear_off_lexical_environment);
    106105LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_tear_off_arguments);
    107106LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_strcat);
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r174216 r174226  
    184184const GlobalVar = 1
    185185const ClosureVar = 2
    186 const GlobalPropertyWithVarInjectionChecks = 3
    187 const GlobalVarWithVarInjectionChecks = 4
    188 const ClosureVarWithVarInjectionChecks = 5
    189 const Dynamic = 6
     186const LocalClosureVar = 3
     187const GlobalPropertyWithVarInjectionChecks = 4
     188const GlobalVarWithVarInjectionChecks = 5
     189const ClosureVarWithVarInjectionChecks = 6
     190const Dynamic = 7
    190191
    191192const ResolveModeMask = 0xffff
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r173886 r174226  
    825825end
    826826
    827 _llint_op_captured_mov:
    828     traceExecution()
    829     loadi 8[PC], t1
    830     loadConstantOrVariable(t1, t2, t3)
    831     loadpFromInstruction(3, t0)
    832     btpz t0, .opCapturedMovReady
    833     notifyWrite(t0, t2, t3, t1, .opCapturedMovSlow)
    834 .opCapturedMovReady:
    835     loadi 4[PC], t0
    836     storei t2, TagOffset[cfr, t0, 8]
    837     storei t3, PayloadOffset[cfr, t0, 8]
    838     dispatch(4)
    839 
    840 .opCapturedMovSlow:
    841     callSlowPath(_slow_path_captured_mov)
    842     dispatch(4)
    843 
    844 
    845827_llint_op_not:
    846828    traceExecution()
     
    19701952    slowPathForCall(slowPath)
    19711953end
    1972 
    1973 
    1974 _llint_op_tear_off_lexical_environment:
    1975     traceExecution()
    1976     loadi 4[PC], t0
    1977     bieq TagOffset[cfr, t0, 8], EmptyValueTag, .opTearOffActivationNotCreated
    1978     callSlowPath(_llint_slow_path_tear_off_lexical_environment)
    1979 .opTearOffActivationNotCreated:
    1980     dispatch(2)
    1981 
    19821954
    19831955_llint_op_tear_off_arguments:
     
    23712343    andi ResolveModeMask, t0
    23722344
    2373 #pGlobalProperty:
     2345#pLocalClosureVar:
     2346    bineq t0, LocalClosureVar, .pGlobalProperty
     2347    writeBarrierOnOperands(1, 3)
     2348    loadVariable(1, t2, t1, t0)
     2349    putClosureVar()
     2350    dispatch(7)
     2351
     2352.pGlobalProperty:
    23742353    bineq t0, GlobalProperty, .pGlobalVar
    23752354    writeBarrierOnOperands(1, 3)
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r173706 r174226  
    708708end
    709709
    710 _llint_op_captured_mov:
    711     traceExecution()
    712     loadisFromInstruction(2, t1)
    713     loadConstantOrVariable(t1, t2)
    714     loadpFromInstruction(3, t0)
    715     btpz t0, .opCapturedMovReady
    716     notifyWrite(t0, t2, t1, .opCapturedMovSlow)
    717 .opCapturedMovReady:
    718     loadisFromInstruction(1, t0)
    719     storeq t2, [cfr, t0, 8]
    720     dispatch(4)
    721 
    722 .opCapturedMovSlow:
    723     callSlowPath(_slow_path_captured_mov)
    724     dispatch(4)
    725 
    726 
    727710_llint_op_not:
    728711    traceExecution()
     
    18271810    slowPathForCall(slowPath)
    18281811end
    1829 
    1830 
    1831 _llint_op_tear_off_lexical_environment:
    1832     traceExecution()
    1833     loadisFromInstruction(1, t0)
    1834     btqz [cfr, t0, 8], .opTearOffActivationNotCreated
    1835     callSlowPath(_llint_slow_path_tear_off_lexical_environment)
    1836 .opTearOffActivationNotCreated:
    1837     dispatch(2)
    1838 
    18391812
    18401813_llint_op_tear_off_arguments:
     
    21902163end
    21912164
     2165macro putLocalClosureVar()
     2166    loadisFromInstruction(3, t1)
     2167    loadConstantOrVariable(t1, t2)
     2168    notifyWrite(t0, t2, t1, .pDynamic)
     2169    loadp JSEnvironmentRecord::m_registers[t0], t0
     2170    loadisFromInstruction(6, t1)
     2171    storeq t2, [t0, t1, 8]
     2172end
     2173
    21922174
    21932175_llint_op_put_to_scope:
     
    21962178    andi ResolveModeMask, t0
    21972179
    2198 #pGlobalProperty:
     2180#pLocalClosureVar:
     2181    bineq t0, LocalClosureVar, .pGlobalProperty
     2182    writeBarrierOnOperands(1, 3)
     2183    loadVariable(1, t0)
     2184    putLocalClosureVar()
     2185    dispatch(7)
     2186
     2187.pGlobalProperty:
    21992188    bineq t0, GlobalProperty, .pGlobalVar
    22002189    writeBarrierOnOperands(1, 3)
  • trunk/Source/JavaScriptCore/runtime/Arguments.cpp

    r173517 r174226  
    385385    m_registers = m_registerArray.get() - CallFrame::offsetFor(1) - 1;
    386386
    387     // If we have a captured argument that logically aliases lexical environment storage,
    388     // but we optimize away the lexicalEnvironment, the argument needs to tear off into
    389     // our storage. The simplest way to do this is to revert it to Normal status.
    390     if (m_slowArgumentData && !m_lexicalEnvironment) {
    391         for (size_t i = 0; i < m_numArguments; ++i) {
    392             if (m_slowArgumentData->slowArguments()[i].status != SlowArgument::Captured)
    393                 continue;
    394             m_slowArgumentData->slowArguments()[i].status = SlowArgument::Normal;
    395             m_slowArgumentData->slowArguments()[i].index = CallFrame::argumentOffset(i);
    396         }
    397     }
    398 
    399     for (size_t i = 0; i < m_numArguments; ++i)
     387    for (size_t i = 0; i < m_numArguments; ++i) {
     388        if (m_slowArgumentData && m_slowArgumentData->slowArguments()[i].status == SlowArgument::Captured)
     389            continue;
    400390        trySetArgument(callFrame->vm(), i, callFrame->argumentAfterCapture(i));
     391    }
    401392}
    402393
  • trunk/Source/JavaScriptCore/runtime/Arguments.h

    r174036 r174226  
    271271
    272272    int index = m_slowArgumentData->slowArguments()[argument].index;
    273     if (!m_lexicalEnvironment || m_slowArgumentData->slowArguments()[argument].status != SlowArgument::Captured)
     273    if (m_slowArgumentData->slowArguments()[argument].status != SlowArgument::Captured)
    274274        return m_registers[index];
    275275
    276     return m_lexicalEnvironment->registerAt(index - m_slowArgumentData->bytecodeToMachineCaptureOffset());
     276    JSLexicalEnvironment* lexicalEnvironment = m_lexicalEnvironment.get();
     277    if (!lexicalEnvironment)
     278        lexicalEnvironment = CallFrame::create(reinterpret_cast<Register*>(m_registers))->lexicalEnvironment();
     279    return lexicalEnvironment->registerAt(index - m_slowArgumentData->bytecodeToMachineCaptureOffset());
    277280}
    278281
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

    r173517 r174226  
    263263}
    264264
    265 SLOW_PATH_DECL(slow_path_captured_mov)
    266 {
    267     BEGIN();
    268     JSValue value = OP_C(2).jsValue();
    269     if (VariableWatchpointSet* set = pc[3].u.watchpointSet)
    270         set->notifyWrite(vm, value, "Executed op_captured_mov");
    271     RETURN(value);
    272 }
    273 
    274265SLOW_PATH_DECL(slow_path_new_captured_func)
    275266{
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h

    r173082 r174226  
    191191SLOW_PATH_HIDDEN_DECL(slow_path_get_callee);
    192192SLOW_PATH_HIDDEN_DECL(slow_path_to_this);
    193 SLOW_PATH_HIDDEN_DECL(slow_path_captured_mov);
    194193SLOW_PATH_HIDDEN_DECL(slow_path_new_captured_func);
    195194SLOW_PATH_HIDDEN_DECL(slow_path_not);
  • trunk/Source/JavaScriptCore/runtime/JSLexicalEnvironment.cpp

    r173517 r174226  
    4747    Base::visitChildren(thisObject, visitor);
    4848
    49     // No need to mark our registers if they're still in the JSStack.
    50     if (!thisObject->isTornOff())
    51         return;
    52 
    5349    for (int i = 0; i < thisObject->symbolTable()->captureCount(); ++i)
    5450        visitor.append(&thisObject->storage()[i]);
     
    6258
    6359    // Defend against the inspector asking for a var after it has been optimized out.
    64     if (isTornOff() && !isValid(entry))
     60    if (!isValid(entry))
    6561        return false;
    6662
     
    7672
    7773    // Defend against the inspector asking for a var after it has been optimized out.
    78     if (isTornOff() && !isValid(entry))
     74    if (!isValid(entry))
    7975        return false;
    8076
     
    10197        }
    10298        // Defend against the inspector asking for a var after it has been optimized out.
    103         if (isTornOff() && !isValid(iter->value))
     99        if (!isValid(iter->value))
    104100            return false;
    105101        if (VariableWatchpointSet* set = iter->value.watchpointSet())
     
    114110{
    115111    JSLexicalEnvironment* thisObject = jsCast<JSLexicalEnvironment*>(object);
    116 
    117     CallFrame* callFrame = CallFrame::create(reinterpret_cast<Register*>(thisObject->m_registers));
    118     if (shouldIncludeDontEnumProperties(mode) && !thisObject->isTornOff() && (callFrame->codeBlock()->usesArguments() || callFrame->codeBlock()->usesEval()))
    119         propertyNames.add(exec->propertyNames().arguments);
    120112
    121113    {
     
    160152    JSLexicalEnvironment* thisObject = jsCast<JSLexicalEnvironment*>(object);
    161153
    162     if (propertyName == exec->propertyNames().arguments) {
    163         // Defend against the inspector asking for the arguments object after it has been optimized out.
    164         CallFrame* callFrame = CallFrame::create(reinterpret_cast<Register*>(thisObject->m_registers));
    165         if (!thisObject->isTornOff() && (callFrame->codeBlock()->usesArguments() || callFrame->codeBlock()->usesEval())) {
    166             slot.setCustom(thisObject, DontEnum, argumentsGetter);
    167             return true;
    168         }
    169     }
    170 
    171154    if (thisObject->symbolTableGet(propertyName, slot))
    172155        return true;
     
    219202    JSLexicalEnvironment* lexicalEnvironment = jsCast<JSLexicalEnvironment*>(slotBase);
    220203    CallFrame* callFrame = CallFrame::create(reinterpret_cast<Register*>(lexicalEnvironment->m_registers));
    221     ASSERT(!lexicalEnvironment->isTornOff() && (callFrame->codeBlock()->usesArguments() || callFrame->codeBlock()->usesEval()));
    222     if (lexicalEnvironment->isTornOff() || !(callFrame->codeBlock()->usesArguments() || callFrame->codeBlock()->usesEval()))
    223         return JSValue::encode(jsUndefined());
     204    return JSValue::encode(jsUndefined());
    224205
    225206    VirtualRegister argumentsRegister = callFrame->codeBlock()->argumentsRegister();
  • trunk/Source/JavaScriptCore/runtime/JSLexicalEnvironment.h

    r173517 r174226  
    4242class JSLexicalEnvironment : public JSEnvironmentRecord {
    4343private:
    44     JSLexicalEnvironment(VM&, CallFrame*, Register*, SymbolTable*);
     44    JSLexicalEnvironment(VM&, CallFrame*, Register*, CodeBlock*);
    4545   
    4646public:
     
    5757                allocationSize(symbolTable)
    5858            )
    59         ) JSLexicalEnvironment(vm, callFrame, registers, symbolTable);
     59        ) JSLexicalEnvironment(vm, callFrame, registers, codeBlock);
    6060        lexicalEnvironment->finishCreation(vm);
    6161        return lexicalEnvironment;
     
    7878    static JSValue toThis(JSCell*, ExecState*, ECMAMode);
    7979
    80     void tearOff(VM&);
    81        
    8280    DECLARE_INFO;
    8381
     
    8785    bool isValidIndex(int) const;
    8886    bool isValid(const SymbolTableEntry&) const;
    89     bool isTornOff();
    9087    int registersOffset();
    9188    static int registersOffset(SymbolTable*);
     
    112109extern int allTheThingsCount;
    113110
    114 inline JSLexicalEnvironment::JSLexicalEnvironment(VM& vm, CallFrame* callFrame, Register* registers, SymbolTable* symbolTable)
     111inline JSLexicalEnvironment::JSLexicalEnvironment(VM& vm, CallFrame* callFrame, Register* registers, CodeBlock* codeBlock)
    115112    : Base(
    116113        vm,
     
    118115        registers,
    119116        callFrame->scope(),
    120         symbolTable)
     117        codeBlock->symbolTable())
    121118{
     119    SymbolTable* symbolTable = codeBlock->symbolTable();
    122120    WriteBarrier<Unknown>* storage = this->storage();
    123121    size_t captureCount = symbolTable->captureCount();
    124122    for (size_t i = 0; i < captureCount; ++i)
    125         new (NotNull, &storage[i]) WriteBarrier<Unknown>;
     123        new (NotNull, &storage[i]) WriteBarrier<Unknown>(UndefinedWriteBarrierTag);
     124    m_registers = reinterpret_cast_ptr<WriteBarrierBase<Unknown>*>(
     125        reinterpret_cast<char*>(this) + registersOffset(symbolTable));
    126126}
    127127
     
    142142{
    143143    return storageOffset() + ((symbolTable->captureCount() - symbolTable->captureStart()  - 1) * sizeof(WriteBarrier<Unknown>));
    144 }
    145 
    146 inline void JSLexicalEnvironment::tearOff(VM& vm)
    147 {
    148     ASSERT(!isTornOff());
    149 
    150     WriteBarrierBase<Unknown>* dst = reinterpret_cast_ptr<WriteBarrierBase<Unknown>*>(
    151         reinterpret_cast<char*>(this) + registersOffset(symbolTable()));
    152     WriteBarrierBase<Unknown>* src = m_registers;
    153 
    154     int captureEnd = symbolTable()->captureEnd();
    155     for (int i = symbolTable()->captureStart(); i > captureEnd; --i)
    156         dst[i].set(vm, this, src[i].get());
    157 
    158     m_registers = dst;
    159     ASSERT(isTornOff());
    160 }
    161 
    162 inline bool JSLexicalEnvironment::isTornOff()
    163 {
    164     return m_registers == reinterpret_cast_ptr<WriteBarrierBase<Unknown>*>(
    165         reinterpret_cast<char*>(this) + registersOffset(symbolTable()));
    166144}
    167145
  • trunk/Source/JavaScriptCore/runtime/JSScope.cpp

    r173517 r174226  
    181181        "GlobalVar",
    182182        "ClosureVar",
     183        "LocalClosureVar",
    183184        "GlobalPropertyWithVarInjectionChecks",
    184185        "GlobalVarWithVarInjectionChecks",
     
    186187        "Dynamic"
    187188    };
    188     ASSERT(type < sizeof(names) / sizeof(names[0]));
    189189    return names[type];
    190190}
  • trunk/Source/JavaScriptCore/runtime/JSScope.h

    r173706 r174226  
    4444    GlobalVar,
    4545    ClosureVar,
     46    LocalClosureVar,
    4647
    4748    // Ditto, but at least one intervening scope used non-strict eval, which
     
    6970        return GlobalVarWithVarInjectionChecks;
    7071    case ClosureVar:
     72    case LocalClosureVar:
    7173        return ClosureVarWithVarInjectionChecks;
    7274    case GlobalPropertyWithVarInjectionChecks:
     
    8789    case GlobalVar:
    8890    case ClosureVar:
     91    case LocalClosureVar:
    8992        return false;
    9093    case GlobalPropertyWithVarInjectionChecks:
  • trunk/Source/JavaScriptCore/runtime/WriteBarrier.h

    r169703 r174226  
    202202};
    203203
     204enum UndefinedWriteBarrierTagType { UndefinedWriteBarrierTag };
    204205template <> class WriteBarrier<Unknown> : public WriteBarrierBase<Unknown> {
    205206    WTF_MAKE_FAST_ALLOCATED;
     
    209210        this->setWithoutWriteBarrier(JSValue());
    210211    }
     212    WriteBarrier(UndefinedWriteBarrierTagType)
     213    {
     214        this->setWithoutWriteBarrier(jsUndefined());
     215    }
    211216
    212217    WriteBarrier(VM& vm, const JSCell* owner, JSValue value)
Note: See TracChangeset for help on using the changeset viewer.