Changeset 128096 in webkit


Ignore:
Timestamp:
Sep 10, 2012 1:23:50 PM (12 years ago)
Author:
ggaren@apple.com
Message:

Refactored op_tear_off* to support activations that don't allocate space for 'arguments'
https://bugs.webkit.org/show_bug.cgi?id=96231

Reviewed by Gavin Barraclough.

This is a step toward smaller activations.

As a side-effect, this patch eliminates a load and branch from the hot path
of activation tear-off by moving it to the cold path of arguments tear-off. Our
optimizing assumptions are that activations are common and that reifying the
arguments object is less common.

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dump):

  • bytecode/Opcode.h:

(JSC::padOpcodeName): Updated for new opcode lengths.

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::addConstantValue): Added support for JSValue()
in the bytecode, which we use when we have 'arguments' but no activation.

(JSC::BytecodeGenerator::emitReturn): Always emit tear_off_arguments
if we've allocated the arguments registers. This allows tear_off_activation
not to worry about the arguments object anymore.

Also, pass the activation and arguments values directly to these opcodes
instead of requiring the opcodes to infer the values through special
registers. This gives us more flexibility to move or eliminate registers.

  • dfg/DFGArgumentsSimplificationPhase.cpp:

(JSC::DFG::ArgumentsSimplificationPhase::run):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGNode.h:

(Node): Updated for new opcode lengths.

  • dfg/DFGOperations.cpp: Activation tear-off doesn't worry about the

arguments object anymore. If 'arguments' is in use and reified, it's
responsible for aliasing back to the activation object in tear_off_arguments.

  • dfg/DFGOperations.h:
  • dfg/DFGSpeculativeJIT.h:

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

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile): Don't pass the arguments object to
activation tear-off; do pass the activation object to arguments tear-off.

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::privateExecute): Ditto.

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_tear_off_activation):
(JSC::JIT::emit_op_tear_off_arguments):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_tear_off_activation):
(JSC::JIT::emit_op_tear_off_arguments):

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):

  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::LLINT_SLOW_PATH_DECL):

  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm: Same change in a few more execution engines.
Location:
trunk/Source/JavaScriptCore
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r128091 r128096  
     12012-09-09  Geoffrey Garen  <ggaren@apple.com>
     2
     3        Refactored op_tear_off* to support activations that don't allocate space for 'arguments'
     4        https://bugs.webkit.org/show_bug.cgi?id=96231
     5
     6        Reviewed by Gavin Barraclough.
     7
     8        This is a step toward smaller activations.
     9
     10        As a side-effect, this patch eliminates a load and branch from the hot path
     11        of activation tear-off by moving it to the cold path of arguments tear-off. Our
     12        optimizing assumptions are that activations are common and that reifying the
     13        arguments object is less common.
     14
     15        * bytecode/CodeBlock.cpp:
     16        (JSC::CodeBlock::dump):
     17        * bytecode/Opcode.h:
     18        (JSC::padOpcodeName): Updated for new opcode lengths.
     19
     20        * bytecompiler/BytecodeGenerator.cpp:
     21        (JSC::BytecodeGenerator::BytecodeGenerator):
     22        (JSC::BytecodeGenerator::addConstantValue): Added support for JSValue()
     23        in the bytecode, which we use when we have 'arguments' but no activation.
     24
     25        (JSC::BytecodeGenerator::emitReturn): Always emit tear_off_arguments
     26        if we've allocated the arguments registers. This allows tear_off_activation
     27        not to worry about the arguments object anymore.
     28
     29        Also, pass the activation and arguments values directly to these opcodes
     30        instead of requiring the opcodes to infer the values through special
     31        registers. This gives us more flexibility to move or eliminate registers.
     32
     33        * dfg/DFGArgumentsSimplificationPhase.cpp:
     34        (JSC::DFG::ArgumentsSimplificationPhase::run):
     35        * dfg/DFGByteCodeParser.cpp:
     36        (JSC::DFG::ByteCodeParser::parseBlock):
     37        * dfg/DFGNode.h:
     38        (Node): Updated for new opcode lengths.
     39
     40        * dfg/DFGOperations.cpp: Activation tear-off doesn't worry about the
     41        arguments object anymore. If 'arguments' is in use and reified, it's
     42        responsible for aliasing back to the activation object in tear_off_arguments.
     43
     44        * dfg/DFGOperations.h:
     45        * dfg/DFGSpeculativeJIT.h:
     46        (JSC::DFG::SpeculativeJIT::callOperation):
     47        (SpeculativeJIT):
     48        * dfg/DFGSpeculativeJIT32_64.cpp:
     49        (JSC::DFG::SpeculativeJIT::compile):
     50        * dfg/DFGSpeculativeJIT64.cpp:
     51        (JSC::DFG::SpeculativeJIT::compile): Don't pass the arguments object to
     52        activation tear-off; do pass the activation object to arguments tear-off.
     53
     54        * interpreter/Interpreter.cpp:
     55        (JSC::Interpreter::privateExecute): Ditto.
     56
     57        * jit/JITOpcodes.cpp:
     58        (JSC::JIT::emit_op_tear_off_activation):
     59        (JSC::JIT::emit_op_tear_off_arguments):
     60        * jit/JITOpcodes32_64.cpp:
     61        (JSC::JIT::emit_op_tear_off_activation):
     62        (JSC::JIT::emit_op_tear_off_arguments):
     63        * jit/JITStubs.cpp:
     64        (JSC::DEFINE_STUB_FUNCTION):
     65        * llint/LLIntSlowPaths.cpp:
     66        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     67        * llint/LowLevelInterpreter32_64.asm:
     68        * llint/LowLevelInterpreter64.asm: Same change in a few more execution engines.
     69
    1702012-09-10  Patrick Gansterer  <paroga@webkit.org>
    271
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r128084 r128096  
    14081408        case op_tear_off_activation: {
    14091409            int r0 = (++it)->u.operand;
     1410            dataLog("[%4d] tear_off_activation\t %s", location, registerName(exec, r0).data());
     1411            dumpBytecodeCommentAndNewLine(location);
     1412            break;
     1413        }
     1414        case op_tear_off_arguments: {
     1415            int r0 = (++it)->u.operand;
    14101416            int r1 = (++it)->u.operand;
    1411             dataLog("[%4d] tear_off_activation\t %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data());
    1412             dumpBytecodeCommentAndNewLine(location);
    1413             break;
    1414         }
    1415         case op_tear_off_arguments: {
    1416             int r0 = (++it)->u.operand;
    1417             dataLog("[%4d] tear_off_arguments %s", location, registerName(exec, r0).data());
     1417            dataLog("[%4d] tear_off_arguments %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data());
    14181418            dumpBytecodeCommentAndNewLine(location);
    14191419            break;
  • trunk/Source/JavaScriptCore/bytecode/Opcode.h

    r127393 r128096  
    175175        macro(op_call_eval, 6) \
    176176        macro(op_call_varargs, 5) \
    177         macro(op_tear_off_activation, 3) \
    178         macro(op_tear_off_arguments, 2) \
     177        macro(op_tear_off_activation, 2) \
     178        macro(op_tear_off_arguments, 3) \
    179179        macro(op_ret, 2) \
    180180        macro(op_call_put_result, 3) /* has value profiling */ \
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r127987 r128096  
    273273    , m_codeBlock(codeBlock)
    274274    , m_thisRegister(CallFrame::thisArgumentOffset())
     275    , m_emptyValueRegister(0)
    275276    , m_finallyDepth(0)
    276277    , m_dynamicScopeDepth(0)
     
    354355    , m_codeBlock(codeBlock)
    355356    , m_activationRegister(0)
     357    , m_emptyValueRegister(0)
    356358    , m_finallyDepth(0)
    357359    , m_dynamicScopeDepth(0)
     
    387389    }
    388390
    389     // Both op_tear_off_activation and op_tear_off_arguments tear off the 'arguments'
    390     // object, if created.
    391391    if (m_codeBlock->needsFullScopeChain() || functionBody->usesArguments()) {
    392392        RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code.
     
    527527    , m_codeBlock(codeBlock)
    528528    , m_thisRegister(CallFrame::thisArgumentOffset())
     529    , m_emptyValueRegister(0)
    529530    , m_finallyDepth(0)
    530531    , m_dynamicScopeDepth(0)
     
    11121113}
    11131114
     1115// We can't hash JSValue(), so we use a dedicated data member to cache it.
     1116RegisterID* BytecodeGenerator::addConstantEmptyValue()
     1117{
     1118    if (!m_emptyValueRegister) {
     1119        int index = m_nextConstantOffset;
     1120        m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
     1121        ++m_nextConstantOffset;
     1122        m_codeBlock->addConstant(JSValue());
     1123        m_emptyValueRegister = &m_constantPoolRegisters[index];
     1124    }
     1125
     1126    return m_emptyValueRegister;
     1127}
     1128
    11141129RegisterID* BytecodeGenerator::addConstantValue(JSValue v)
    11151130{
     1131    if (!v)
     1132        return addConstantEmptyValue();
     1133
    11161134    int index = m_nextConstantOffset;
    1117 
    11181135    JSValueMap::AddResult result = m_jsValueMap.add(JSValue::encode(v), m_nextConstantOffset);
    11191136    if (result.isNewEntry) {
    11201137        m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
    11211138        ++m_nextConstantOffset;
    1122         m_codeBlock->addConstant(JSValue(v));
     1139        m_codeBlock->addConstant(v);
    11231140    } else
    11241141        index = result.iterator->second;
    1125 
    11261142    return &m_constantPoolRegisters[index];
    11271143}
     
    20472063        emitOpcode(op_tear_off_activation);
    20482064        instructions().append(m_activationRegister->index());
    2049         instructions().append(m_codeBlock->argumentsRegister());
    2050     } else if (m_codeBlock->usesArguments() && m_codeBlock->numParameters() != 1 && !m_codeBlock->isStrictMode()) {
     2065    }
     2066
     2067    if (m_codeBlock->usesArguments() && m_codeBlock->numParameters() != 1 && !m_codeBlock->isStrictMode()) {
    20512068        emitOpcode(op_tear_off_arguments);
    20522069        instructions().append(m_codeBlock->argumentsRegister());
     2070        instructions().append(m_activationRegister ? m_activationRegister->index() : emitLoad(0, JSValue())->index());
    20532071    }
    20542072
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r127987 r128096  
    638638        unsigned addConstant(const Identifier&);
    639639        RegisterID* addConstantValue(JSValue);
     640        RegisterID* addConstantEmptyValue();
    640641        unsigned addRegExp(RegExp*);
    641642
     
    714715        RegisterID m_calleeRegister;
    715716        RegisterID* m_activationRegister;
     717        RegisterID* m_emptyValueRegister;
    716718        SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
    717719        SegmentedVector<RegisterID, 32> m_calleeRegisters;
  • trunk/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp

    r126926 r128096  
    617617                    node.setOpAndDefaultFlags(Nop);
    618618                    m_graph.clearAndDerefChild1(node);
     619                    m_graph.clearAndDerefChild2(node);
    619620                    node.setRefCount(0);
    620621                    break;
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r127643 r128096  
    28562856           
    28572857        case op_tear_off_activation: {
    2858             addToGraph(TearOffActivation, OpInfo(unmodifiedArgumentsRegister(currentInstruction[2].u.operand)), get(currentInstruction[1].u.operand), get(currentInstruction[2].u.operand));
     2858            addToGraph(TearOffActivation, get(currentInstruction[1].u.operand));
    28592859            NEXT_OPCODE(op_tear_off_activation);
    28602860        }
    2861            
     2861
    28622862        case op_tear_off_arguments: {
    28632863            m_graph.m_hasArguments = true;
    2864             addToGraph(TearOffArguments, get(unmodifiedArgumentsRegister(currentInstruction[1].u.operand)));
     2864            addToGraph(TearOffArguments, get(unmodifiedArgumentsRegister(currentInstruction[1].u.operand)), get(currentInstruction[2].u.operand));
    28652865            NEXT_OPCODE(op_tear_off_arguments);
    28662866        }
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r127189 r128096  
    338338    }
    339339   
    340     VirtualRegister unmodifiedArgumentsRegister()
    341     {
    342         ASSERT(op() == TearOffActivation);
    343         return static_cast<VirtualRegister>(m_opInfo);
    344     }
    345    
    346340    VirtualRegister unlinkedLocal()
    347341    {
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r127810 r128096  
    11661166}
    11671167
    1168 void DFG_OPERATION operationTearOffActivation(ExecState* exec, JSCell* activationCell, int32_t unmodifiedArgumentsRegister)
     1168void DFG_OPERATION operationTearOffActivation(ExecState* exec, JSCell* activationCell)
    11691169{
    11701170    JSGlobalData& globalData = exec->globalData();
    11711171    NativeCallFrameTracer tracer(&globalData, exec);
    1172     if (!activationCell) {
    1173         if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister).jsValue()) {
    1174             if (!exec->codeBlock()->isStrictMode())
    1175                 asArguments(v)->tearOff(exec);
    1176         }
     1172    jsCast<JSActivation*>(activationCell)->tearOff(exec->globalData());
     1173}
     1174
     1175void DFG_OPERATION operationTearOffArguments(ExecState* exec, JSCell* argumentsCell, JSCell* activationCell)
     1176{
     1177    ASSERT(exec->codeBlock()->usesArguments());
     1178    if (activationCell) {
     1179        jsCast<Arguments*>(argumentsCell)->didTearOffActivation(exec->globalData(), jsCast<JSActivation*>(activationCell));
    11771180        return;
    11781181    }
    1179     JSActivation* activation = jsCast<JSActivation*>(activationCell);
    1180     activation->tearOff(exec->globalData());
    1181     if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister).jsValue())
    1182         asArguments(v)->didTearOffActivation(exec->globalData(), activation);
    1183 }
    1184 
    1185 
    1186 void DFG_OPERATION operationTearOffArguments(ExecState* exec, JSCell* argumentsCell)
    1187 {
    1188     ASSERT(exec->codeBlock()->usesArguments());
    1189     ASSERT(!exec->codeBlock()->needsFullScopeChain());
    1190     asArguments(argumentsCell)->tearOff(exec);
     1182    jsCast<Arguments*>(argumentsCell)->tearOff(exec);
    11911183}
    11921184
    11931185void DFG_OPERATION operationTearOffInlinedArguments(
    1194     ExecState* exec, JSCell* argumentsCell, InlineCallFrame* inlineCallFrame)
    1195 {
    1196     // This should only be called when the inline code block uses arguments but does not
    1197     // need a full scope chain. We could assert it, except that the assertion would be
    1198     // rather expensive and may cause side effects that would greatly diverge debug-mode
    1199     // behavior from release-mode behavior, since getting the code block of an inline
    1200     // call frame implies call frame reification.
    1201     asArguments(argumentsCell)->tearOff(exec, inlineCallFrame);
     1186    ExecState* exec, JSCell* argumentsCell, JSCell* activationCell, InlineCallFrame* inlineCallFrame)
     1187{
     1188    ASSERT_UNUSED(activationCell, !activationCell); // Currently, we don't inline functions with activations.
     1189    jsCast<Arguments*>(argumentsCell)->tearOff(exec, inlineCallFrame);
    12021190}
    12031191
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r127536 r128096  
    9999typedef void DFG_OPERATION (*V_DFGOperation_EC)(ExecState*, JSCell*);
    100100typedef void DFG_OPERATION (*V_DFGOperation_ECIcf)(ExecState*, JSCell*, InlineCallFrame*);
     101typedef void DFG_OPERATION (*V_DFGOperation_ECCIcf)(ExecState*, JSCell*, JSCell*, InlineCallFrame*);
    101102typedef void DFG_OPERATION (*V_DFGOperation_ECJJ)(ExecState*, JSCell*, EncodedJSValue, EncodedJSValue);
    102103typedef void DFG_OPERATION (*V_DFGOperation_ECZ)(ExecState*, JSCell*, int32_t);
     104typedef void DFG_OPERATION (*V_DFGOperation_ECC)(ExecState*, JSCell*, JSCell*);
    103105typedef void DFG_OPERATION (*V_DFGOperation_EJCI)(ExecState*, EncodedJSValue, JSCell*, Identifier*);
    104106typedef void DFG_OPERATION (*V_DFGOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue);
     
    174176JSCell* DFG_OPERATION operationCreateArguments(ExecState*) WTF_INTERNAL;
    175177JSCell* DFG_OPERATION operationCreateInlinedArguments(ExecState*, InlineCallFrame*) WTF_INTERNAL;
    176 void DFG_OPERATION operationTearOffActivation(ExecState*, JSCell*, int32_t unmodifiedArgumentsRegister) WTF_INTERNAL;
    177 void DFG_OPERATION operationTearOffArguments(ExecState*, JSCell*) WTF_INTERNAL;
    178 void DFG_OPERATION operationTearOffInlinedArguments(ExecState*, JSCell*, InlineCallFrame*) WTF_INTERNAL;
     178void DFG_OPERATION operationTearOffActivation(ExecState*, JSCell*) WTF_INTERNAL;
     179void DFG_OPERATION operationTearOffArguments(ExecState*, JSCell*, JSCell*) WTF_INTERNAL;
     180void DFG_OPERATION operationTearOffInlinedArguments(ExecState*, JSCell*, JSCell*, InlineCallFrame*) WTF_INTERNAL;
    179181EncodedJSValue DFG_OPERATION operationGetArgumentsLength(ExecState*, int32_t) WTF_INTERNAL;
    180182EncodedJSValue DFG_OPERATION operationGetInlinedArgumentByVal(ExecState*, int32_t, InlineCallFrame*, int32_t) WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r127561 r128096  
    13541354        return appendCallWithExceptionCheck(operation);
    13551355    }
     1356    JITCompiler::Call callOperation(V_DFGOperation_ECCIcf operation, GPRReg arg1, GPRReg arg2, InlineCallFrame* arg3)
     1357    {
     1358        m_jit.setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(arg3));
     1359        return appendCallWithExceptionCheck(operation);
     1360    }
    13561361    JITCompiler::Call callOperation(V_DFGOperation_EJPP operation, GPRReg arg1, GPRReg arg2, void* pointer)
    13571362    {
     
    13871392    {
    13881393        m_jit.setupArgumentsWithExecState(arg1, TrustedImm32(arg2));
     1394        return appendCallWithExceptionCheck(operation);
     1395    }
     1396    JITCompiler::Call callOperation(V_DFGOperation_ECC operation, GPRReg arg1, GPRReg arg2)
     1397    {
     1398        m_jit.setupArgumentsWithExecState(arg1, arg2);
    13891399        return appendCallWithExceptionCheck(operation);
    13901400    }
     
    16521662        return appendCallWithExceptionCheck(operation);
    16531663    }
     1664    JITCompiler::Call callOperation(V_DFGOperation_ECCIcf operation, GPRReg arg1, GPRReg arg2, InlineCallFrame* inlineCallFrame)
     1665    {
     1666        m_jit.setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(inlineCallFrame));
     1667        return appendCallWithExceptionCheck(operation);
     1668    }
    16541669    JITCompiler::Call callOperation(V_DFGOperation_EJPP operation, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2, void* pointer)
    16551670    {
     
    16721687        return appendCallWithExceptionCheck(operation);
    16731688    }
     1689    JITCompiler::Call callOperation(V_DFGOperation_ECC operation, GPRReg arg1, GPRReg arg2)
     1690    {
     1691        m_jit.setupArgumentsWithExecState(arg1, arg2);
     1692        return appendCallWithExceptionCheck(operation);
     1693    }
    16741694    JITCompiler::Call callOperation(V_DFGOperation_EPZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3Tag, GPRReg arg3Payload)
    16751695    {
     
    16961716    {
    16971717        return callOperation(operation, arg1, arg2);
     1718    }
     1719    template<typename FunctionType, typename ArgumentType1, typename ArgumentType2, typename ArgumentType3>
     1720    JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1, ArgumentType2 arg2, ArgumentType3 arg3)
     1721    {
     1722        return callOperation(operation, arg1, arg2, arg3);
    16981723    }
    16991724    template<typename FunctionType, typename ArgumentType1, typename ArgumentType2, typename ArgumentType3, typename ArgumentType4>
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r127536 r128096  
    40244024    case TearOffActivation: {
    40254025        JSValueOperand activationValue(this, node.child1());
    4026         JSValueOperand argumentsValue(this, node.child2());
    40274026       
    40284027        GPRReg activationValueTagGPR = activationValue.tagGPR();
    40294028        GPRReg activationValuePayloadGPR = activationValue.payloadGPR();
    4030         GPRReg argumentsValueTagGPR = argumentsValue.tagGPR();
    4031        
    4032         JITCompiler::JumpList created;
    4033         created.append(m_jit.branch32(JITCompiler::NotEqual, activationValueTagGPR, TrustedImm32(JSValue::EmptyValueTag)));
    4034         created.append(m_jit.branch32(JITCompiler::NotEqual, argumentsValueTagGPR, TrustedImm32(JSValue::EmptyValueTag)));
    4035        
     4029
     4030        JITCompiler::Jump created = m_jit.branch32(JITCompiler::NotEqual, activationValueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
     4031
    40364032        addSlowPathGenerator(
    40374033            slowPathCall(
    4038                 created, this, operationTearOffActivation, NoResult, activationValuePayloadGPR,
    4039                 static_cast<int32_t>(node.unmodifiedArgumentsRegister())));
     4034                created, this, operationTearOffActivation, NoResult, activationValuePayloadGPR));
    40404035       
    40414036        noResult(m_compileIndex);
     
    40444039       
    40454040    case TearOffArguments: {
    4046         JSValueOperand argumentsValue(this, node.child1());
    4047         GPRReg argumentsValueTagGPR = argumentsValue.tagGPR();
    4048         GPRReg argumentsValuePayloadGPR = argumentsValue.payloadGPR();
    4049        
    4050         JITCompiler::Jump created = m_jit.branch32(
    4051             JITCompiler::NotEqual, argumentsValueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
     4041        JSValueOperand unmodifiedArgumentsValue(this, node.child1());
     4042        JSValueOperand activationValue(this, node.child2());
     4043        GPRReg unmodifiedArgumentsValuePayloadGPR = unmodifiedArgumentsValue.payloadGPR();
     4044        GPRReg activationValuePayloadGPR = activationValue.payloadGPR();
     4045       
     4046        JITCompiler::Jump created = m_jit.branchTest32(
     4047            JITCompiler::NonZero, unmodifiedArgumentsValuePayloadGPR);
    40524048       
    40534049        if (node.codeOrigin.inlineCallFrame) {
     
    40554051                slowPathCall(
    40564052                    created, this, operationTearOffInlinedArguments, NoResult,
    4057                     argumentsValuePayloadGPR, node.codeOrigin.inlineCallFrame));
     4053                    unmodifiedArgumentsValuePayloadGPR, activationValuePayloadGPR, node.codeOrigin.inlineCallFrame));
    40584054        } else {
    40594055            addSlowPathGenerator(
    40604056                slowPathCall(
    40614057                    created, this, operationTearOffArguments, NoResult,
    4062                     argumentsValuePayloadGPR));
     4058                    unmodifiedArgumentsValuePayloadGPR, activationValuePayloadGPR));
    40634059        }
    40644060       
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r127536 r128096  
    39733973        break;
    39743974    }
    3975        
     3975
    39763976    case TearOffActivation: {
    39773977        ASSERT(!node.codeOrigin.inlineCallFrame);
    39783978
    39793979        JSValueOperand activationValue(this, node.child1());
    3980         JSValueOperand argumentsValue(this, node.child2());
    39813980        GPRReg activationValueGPR = activationValue.gpr();
    3982         GPRReg argumentsValueGPR = argumentsValue.gpr();
    3983        
    3984         JITCompiler::JumpList created;
    3985         created.append(m_jit.branchTestPtr(JITCompiler::NonZero, activationValueGPR));
    3986         created.append(m_jit.branchTestPtr(JITCompiler::NonZero, argumentsValueGPR));
     3981
     3982        JITCompiler::Jump created = m_jit.branchTestPtr(JITCompiler::NonZero, activationValueGPR);
    39873983       
    39883984        addSlowPathGenerator(
    39893985            slowPathCall(
    3990                 created, this, operationTearOffActivation, NoResult, activationValueGPR,
    3991                 static_cast<int32_t>(node.unmodifiedArgumentsRegister())));
     3986                created, this, operationTearOffActivation, NoResult, activationValueGPR));
    39923987       
    39933988        noResult(m_compileIndex);
    39943989        break;
    39953990    }
    3996        
     3991
    39973992    case TearOffArguments: {
    3998         JSValueOperand argumentsValue(this, node.child1());
    3999         GPRReg argumentsValueGPR = argumentsValue.gpr();
    4000        
    4001         JITCompiler::Jump created = m_jit.branchTestPtr(JITCompiler::NonZero, argumentsValueGPR);
    4002        
     3993        JSValueOperand unmodifiedArgumentsValue(this, node.child1());
     3994        JSValueOperand activationValue(this, node.child2());
     3995        GPRReg unmodifiedArgumentsValueGPR = unmodifiedArgumentsValue.gpr();
     3996        GPRReg activationValueGPR = activationValue.gpr();
     3997
     3998        JITCompiler::Jump created = m_jit.branchTestPtr(JITCompiler::NonZero, unmodifiedArgumentsValueGPR);
     3999
    40034000        if (node.codeOrigin.inlineCallFrame) {
    40044001            addSlowPathGenerator(
    40054002                slowPathCall(
    40064003                    created, this, operationTearOffInlinedArguments, NoResult,
    4007                     argumentsValueGPR, node.codeOrigin.inlineCallFrame));
     4004                    unmodifiedArgumentsValueGPR, activationValueGPR, node.codeOrigin.inlineCallFrame));
    40084005        } else {
    40094006            addSlowPathGenerator(
    40104007                slowPathCall(
    4011                     created, this, operationTearOffArguments, NoResult, argumentsValueGPR));
     4008                    created, this, operationTearOffArguments, NoResult, unmodifiedArgumentsValueGPR, activationValueGPR));
    40124009        }
    40134010       
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r127958 r128096  
    44764476    }
    44774477    DEFINE_OPCODE(op_tear_off_activation) {
    4478         /* tear_off_activation activation(r) arguments(r)
     4478        /* tear_off_activation activation(r)
    44794479
    44804480           Copy locals and named parameters from the register file to the heap.
    4481            Point the bindings in 'activation' and 'arguments' to this new backing
    4482            store. (Note that 'arguments' may not have been created. If created,
    4483            'arguments' already holds a copy of any extra / unnamed parameters.)
     4481           Point the bindings in 'activation' to this new backing store.
    44844482
    44854483           This opcode appears before op_ret in functions that require full scope chains.
     
    44874485
    44884486        int activation = vPC[1].u.operand;
    4489         int arguments = vPC[2].u.operand;
    44904487        ASSERT(codeBlock->needsFullScopeChain());
    44914488        JSValue activationValue = callFrame->r(activation).jsValue();
    4492         if (activationValue) {
     4489        if (activationValue)
    44934490            asActivation(activationValue)->tearOff(*globalData);
    44944491
    4495             if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue())
    4496                 asArguments(argumentsValue)->didTearOffActivation(*globalData, asActivation(activationValue));
    4497         } else if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) {
    4498             if (!codeBlock->isStrictMode())
    4499                 asArguments(argumentsValue)->tearOff(callFrame);
    4500         }
    4501 
    45024492        vPC += OPCODE_LENGTH(op_tear_off_activation);
    45034493        NEXT_INSTRUCTION();
    45044494    }
    45054495    DEFINE_OPCODE(op_tear_off_arguments) {
    4506         /* tear_off_arguments arguments(r)
     4496        /* tear_off_arguments arguments(r) activation(r)
    45074497
    45084498           Copy named parameters from the register file to the heap. Point the
    4509            bindings in 'arguments' to this new backing store. (Note that
    4510            'arguments' may not have been created. If created, 'arguments' already
    4511            holds a copy of any extra / unnamed parameters.)
     4499           bindings in 'arguments' to this new backing store. (If 'activation'
     4500           was also copied to the heap, 'arguments' will point to its storage.)
    45124501
    45134502           This opcode appears before op_ret in functions that don't require full
     
    45154504        */
    45164505
    4517         int src1 = vPC[1].u.operand;
    4518         ASSERT(!codeBlock->needsFullScopeChain() && codeBlock->ownerExecutable()->usesArguments());
    4519 
    4520         if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(src1)).jsValue())
    4521             asArguments(arguments)->tearOff(callFrame);
     4506        int arguments = vPC[1].u.operand;
     4507        int activation = vPC[2].u.operand;
     4508        ASSERT(codeBlock->usesArguments());
     4509        if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) {
     4510            if (JSValue activationValue = callFrame->r(activation).jsValue())
     4511                asArguments(argumentsValue)->didTearOffActivation(callFrame->globalData(), asActivation(activationValue));
     4512            else
     4513                asArguments(argumentsValue)->tearOff(callFrame);
     4514        }
    45224515
    45234516        vPC += OPCODE_LENGTH(op_tear_off_arguments);
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r127394 r128096  
    560560void JIT::emit_op_tear_off_activation(Instruction* currentInstruction)
    561561{
    562     unsigned activation = currentInstruction[1].u.operand;
    563     unsigned arguments = currentInstruction[2].u.operand;
    564     Jump activationCreated = branchTestPtr(NonZero, addressFor(activation));
    565     Jump argumentsNotCreated = branchTestPtr(Zero, addressFor(arguments));
    566     activationCreated.link(this);
     562    int activation = currentInstruction[1].u.operand;
     563    Jump activationNotCreated = branchTestPtr(Zero, addressFor(activation));
    567564    JITStubCall stubCall(this, cti_op_tear_off_activation);
    568565    stubCall.addArgument(activation, regT2);
    569     stubCall.addArgument(unmodifiedArgumentsRegister(arguments), regT2);
    570     stubCall.call();
    571     argumentsNotCreated.link(this);
     566    stubCall.call();
     567    activationNotCreated.link(this);
    572568}
    573569
    574570void JIT::emit_op_tear_off_arguments(Instruction* currentInstruction)
    575571{
    576     unsigned dst = currentInstruction[1].u.operand;
     572    int dst = currentInstruction[1].u.operand;
     573    int activation = currentInstruction[2].u.operand;
    577574
    578575    Jump argsNotCreated = branchTestPtr(Zero, Address(callFrameRegister, sizeof(Register) * (unmodifiedArgumentsRegister(dst))));
    579576    JITStubCall stubCall(this, cti_op_tear_off_arguments);
    580577    stubCall.addArgument(unmodifiedArgumentsRegister(dst), regT2);
     578    stubCall.addArgument(activation, regT2);
    581579    stubCall.call();
    582580    argsNotCreated.link(this);
  • trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r127394 r128096  
    704704{
    705705    unsigned activation = currentInstruction[1].u.operand;
    706     unsigned arguments = currentInstruction[2].u.operand;
    707     Jump activationCreated = branch32(NotEqual, tagFor(activation), TrustedImm32(JSValue::EmptyValueTag));
    708     Jump argumentsNotCreated = branch32(Equal, tagFor(arguments), TrustedImm32(JSValue::EmptyValueTag));
    709     activationCreated.link(this);
     706    Jump activationNotCreated = branch32(Equal, tagFor(activation), TrustedImm32(JSValue::EmptyValueTag));
    710707    JITStubCall stubCall(this, cti_op_tear_off_activation);
    711     stubCall.addArgument(currentInstruction[1].u.operand);
    712     stubCall.addArgument(unmodifiedArgumentsRegister(currentInstruction[2].u.operand));
     708    stubCall.addArgument(activation);
    713709    stubCall.call();
    714     argumentsNotCreated.link(this);
     710    activationNotCreated.link(this);
    715711}
    716712
     
    718714{
    719715    int dst = currentInstruction[1].u.operand;
     716    int activation = currentInstruction[1].u.operand;
    720717
    721718    Jump argsNotCreated = branch32(Equal, tagFor(unmodifiedArgumentsRegister(dst)), TrustedImm32(JSValue::EmptyValueTag));
    722719    JITStubCall stubCall(this, cti_op_tear_off_arguments);
    723720    stubCall.addArgument(unmodifiedArgumentsRegister(dst));
     721    stubCall.addArgument(activation);
    724722    stubCall.call();
    725723    argsNotCreated.link(this);
  • trunk/Source/JavaScriptCore/jit/JITStubs.cpp

    r127958 r128096  
    23122312    STUB_INIT_STACK_FRAME(stackFrame);
    23132313
    2314     CallFrame* callFrame = stackFrame.callFrame;
    2315     ASSERT(callFrame->codeBlock()->needsFullScopeChain());
    2316     JSValue activationValue = stackFrame.args[0].jsValue();
    2317     if (!activationValue) {
    2318         if (JSValue v = stackFrame.args[1].jsValue()) {
    2319             if (!callFrame->codeBlock()->isStrictMode())
    2320                 asArguments(v)->tearOff(callFrame);
    2321         }
     2314    ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
     2315    jsCast<JSActivation*>(stackFrame.args[0].jsValue())->tearOff(*stackFrame.globalData);
     2316}
     2317
     2318DEFINE_STUB_FUNCTION(void, op_tear_off_arguments)
     2319{
     2320    STUB_INIT_STACK_FRAME(stackFrame);
     2321
     2322    CallFrame* callFrame = stackFrame.callFrame;
     2323    ASSERT(callFrame->codeBlock()->usesArguments());
     2324    Arguments* arguments = jsCast<Arguments*>(stackFrame.args[0].jsValue());
     2325    if (JSValue activationValue = stackFrame.args[1].jsValue()) {
     2326        arguments->didTearOffActivation(callFrame->globalData(), jsCast<JSActivation*>(activationValue));
    23222327        return;
    23232328    }
    2324     JSActivation* activation = asActivation(stackFrame.args[0].jsValue());
    2325     activation->tearOff(*stackFrame.globalData);
    2326     if (JSValue v = stackFrame.args[1].jsValue())
    2327         asArguments(v)->didTearOffActivation(*stackFrame.globalData, activation);
    2328 }
    2329 
    2330 DEFINE_STUB_FUNCTION(void, op_tear_off_arguments)
    2331 {
    2332     STUB_INIT_STACK_FRAME(stackFrame);
    2333 
    2334     CallFrame* callFrame = stackFrame.callFrame;
    2335     ASSERT(callFrame->codeBlock()->usesArguments() && !callFrame->codeBlock()->needsFullScopeChain());
    2336     asArguments(stackFrame.args[0].jsValue())->tearOff(callFrame);
     2329    arguments->tearOff(callFrame);
    23372330}
    23382331
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r127958 r128096  
    14551455    LLINT_BEGIN();
    14561456    ASSERT(exec->codeBlock()->needsFullScopeChain());
    1457     JSValue activationValue = LLINT_OP(1).jsValue();
    1458     if (!activationValue) {
    1459         if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)).jsValue()) {
    1460             if (!exec->codeBlock()->isStrictMode())
    1461                 asArguments(v)->tearOff(exec);
    1462         }
    1463         LLINT_END();
    1464     }
    1465     JSActivation* activation = asActivation(activationValue);
    1466     activation->tearOff(globalData);
    1467     if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)).jsValue())
    1468         asArguments(v)->didTearOffActivation(globalData, activation);
     1457    jsCast<JSActivation*>(LLINT_OP(1).jsValue())->tearOff(globalData);
    14691458    LLINT_END();
    14701459}
     
    14731462{
    14741463    LLINT_BEGIN();
    1475     ASSERT(exec->codeBlock()->usesArguments() && !exec->codeBlock()->needsFullScopeChain());
    1476     asArguments(exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)).jsValue())->tearOff(exec);
     1464    ASSERT(exec->codeBlock()->usesArguments());
     1465    Arguments* arguments = jsCast<Arguments*>(exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)).jsValue());
     1466    if (JSValue activationValue = LLINT_OP_C(2).jsValue())
     1467        arguments->didTearOffActivation(globalData, jsCast<JSActivation*>(activationValue));
     1468    else
     1469        arguments->tearOff(exec);
    14771470    LLINT_END();
    14781471}
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r127374 r128096  
    16401640    traceExecution()
    16411641    loadi 4[PC], t0
    1642     loadi 8[PC], t1
    1643     bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opTearOffActivationCreated
    1644     bieq TagOffset[cfr, t1, 8], EmptyValueTag, .opTearOffActivationNotCreated
    1645 .opTearOffActivationCreated:
     1642    bieq TagOffset[cfr, t0, 8], EmptyValueTag, .opTearOffActivationNotCreated
    16461643    callSlowPath(_llint_slow_path_tear_off_activation)
    16471644.opTearOffActivationNotCreated:
    1648     dispatch(3)
     1645    dispatch(2)
    16491646
    16501647
     
    16561653    callSlowPath(_llint_slow_path_tear_off_arguments)
    16571654.opTearOffArgumentsNotCreated:
    1658     dispatch(2)
     1655    dispatch(3)
    16591656
    16601657
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r127374 r128096  
    14841484    traceExecution()
    14851485    loadis 8[PB, PC, 8], t0
    1486     loadis 16[PB, PC, 8], t1
    1487     btpnz [cfr, t0, 8], .opTearOffActivationCreated
    1488     btpz [cfr, t1, 8], .opTearOffActivationNotCreated
    1489 .opTearOffActivationCreated:
     1486    btpz [cfr, t0, 8], .opTearOffActivationNotCreated
    14901487    callSlowPath(_llint_slow_path_tear_off_activation)
    14911488.opTearOffActivationNotCreated:
    1492     dispatch(3)
     1489    dispatch(2)
    14931490
    14941491
     
    15001497    callSlowPath(_llint_slow_path_tear_off_arguments)
    15011498.opTearOffArgumentsNotCreated:
    1502     dispatch(2)
     1499    dispatch(3)
    15031500
    15041501
Note: See TracChangeset for help on using the changeset viewer.