Title: [118112] trunk/Source/_javascript_Core
Revision
118112
Author
fpi...@apple.com
Date
2012-05-22 20:48:52 -0700 (Tue, 22 May 2012)

Log Message

DFG should support op_get_argument_by_val and op_get_arguments_length
https://bugs.webkit.org/show_bug.cgi?id=85911

Reviewed by Oliver Hunt.
        
Merged r116467 from dfgopt.
        
This adds a simple and relatively conservative implementation of op_get_argument_by_val
and op_get_arguments_length. We can optimize these later. For now it's great to have
the additional coverage.
        
This patch appears to be perf-neutral.

* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::execute):
* dfg/DFGAssemblyHelpers.h:
(JSC::DFG::AssemblyHelpers::addressFor):
(JSC::DFG::AssemblyHelpers::tagFor):
(JSC::DFG::AssemblyHelpers::payloadFor):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.h:
(JSC::DFG::canCompileOpcode):
(JSC::DFG::canInlineOpcode):
* dfg/DFGNode.h:
(JSC::DFG::Node::hasHeapPrediction):
* dfg/DFGNodeType.h:
(DFG):
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
(SpeculativeJIT):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_get_argument_by_val):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_get_argument_by_val):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (118111 => 118112)


--- trunk/Source/_javascript_Core/ChangeLog	2012-05-23 03:36:39 UTC (rev 118111)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-05-23 03:48:52 UTC (rev 118112)
@@ -1,3 +1,51 @@
+2012-05-08  Filip Pizlo  <fpi...@apple.com>
+
+        DFG should support op_get_argument_by_val and op_get_arguments_length
+        https://bugs.webkit.org/show_bug.cgi?id=85911
+
+        Reviewed by Oliver Hunt.
+        
+        Merged r116467 from dfgopt.
+        
+        This adds a simple and relatively conservative implementation of op_get_argument_by_val
+        and op_get_arguments_length. We can optimize these later. For now it's great to have
+        the additional coverage.
+        
+        This patch appears to be perf-neutral.
+
+        * dfg/DFGAbstractState.cpp:
+        (JSC::DFG::AbstractState::execute):
+        * dfg/DFGAssemblyHelpers.h:
+        (JSC::DFG::AssemblyHelpers::addressFor):
+        (JSC::DFG::AssemblyHelpers::tagFor):
+        (JSC::DFG::AssemblyHelpers::payloadFor):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.h:
+        (JSC::DFG::canCompileOpcode):
+        (JSC::DFG::canInlineOpcode):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::hasHeapPrediction):
+        * dfg/DFGNodeType.h:
+        (DFG):
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        (SpeculativeJIT):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_get_argument_by_val):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_get_argument_by_val):
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+
 2012-05-07  Filip Pizlo  <fpi...@apple.com>
 
         DFG should support op_tear_off_arguments

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp (118111 => 118112)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2012-05-23 03:36:39 UTC (rev 118111)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2012-05-23 03:48:52 UTC (rev 118112)
@@ -1068,6 +1068,25 @@
         // Does nothing that is user-visible.
         break;
         
+    case GetMyArgumentsLength:
+        // This potentially clobbers all structures if the arguments object had a getter
+        // installed on the length property.
+        clobberStructures(indexInBlock);
+        // We currently make no guarantee about what this returns because it does not
+        // speculate that the length property is actually a length.
+        forNode(nodeIndex).makeTop();
+        break;
+        
+    case GetMyArgumentByVal:
+        // This potentially clobbers all structures if the property we're accessing has
+        // a getter. We don't speculate against this.
+        clobberStructures(indexInBlock);
+        // But we do speculate that the index is an integer.
+        forNode(node.child1()).filter(PredictInt32);
+        // And the result is unknown.
+        forNode(nodeIndex).makeTop();
+        break;
+        
     case NewFunction:
     case NewFunctionExpression:
     case NewFunctionNoCheck:

Modified: trunk/Source/_javascript_Core/dfg/DFGAssemblyHelpers.h (118111 => 118112)


--- trunk/Source/_javascript_Core/dfg/DFGAssemblyHelpers.h	2012-05-23 03:36:39 UTC (rev 118111)
+++ trunk/Source/_javascript_Core/dfg/DFGAssemblyHelpers.h	2012-05-23 03:48:52 UTC (rev 118112)
@@ -134,16 +134,28 @@
     {
         return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register));
     }
+    static Address addressFor(int operand)
+    {
+        return addressFor(static_cast<VirtualRegister>(operand));
+    }
 
     static Address tagFor(VirtualRegister virtualRegister)
     {
         return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
     }
+    static Address tagFor(int operand)
+    {
+        return tagFor(static_cast<VirtualRegister>(operand));
+    }
 
     static Address payloadFor(VirtualRegister virtualRegister)
     {
         return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
     }
+    static Address payloadFor(int operand)
+    {
+        return payloadFor(static_cast<VirtualRegister>(operand));
+    }
 
     Jump branchIfNotObject(GPRReg structureReg)
     {

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (118111 => 118112)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2012-05-23 03:36:39 UTC (rev 118111)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2012-05-23 03:48:52 UTC (rev 118112)
@@ -2387,6 +2387,19 @@
             NEXT_OPCODE(op_tear_off_arguments);
         }
             
+        case op_get_arguments_length: {
+            set(currentInstruction[1].u.operand, addToGraph(GetMyArgumentsLength));
+            NEXT_OPCODE(op_get_arguments_length);
+        }
+            
+        case op_get_argument_by_val: {
+            set(currentInstruction[1].u.operand,
+                addToGraph(
+                    GetMyArgumentByVal, OpInfo(0), OpInfo(getPrediction()),
+                    get(currentInstruction[3].u.operand)));
+            NEXT_OPCODE(op_get_argument_by_val);
+        }
+            
         case op_new_func: {
             if (!currentInstruction[3].u.operand) {
                 set(currentInstruction[1].u.operand,

Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.h (118111 => 118112)


--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.h	2012-05-23 03:36:39 UTC (rev 118111)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.h	2012-05-23 03:48:52 UTC (rev 118112)
@@ -167,6 +167,8 @@
     case op_tear_off_arguments:
     case op_new_func:
     case op_new_func_exp:
+    case op_get_argument_by_val:
+    case op_get_arguments_length:
         return true;
         
     default:
@@ -202,6 +204,8 @@
     case op_new_func_exp:
     case op_create_arguments:
     case op_tear_off_arguments:
+    case op_get_argument_by_val:
+    case op_get_arguments_length:
         return false;
         
     default:

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (118111 => 118112)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2012-05-23 03:36:39 UTC (rev 118111)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2012-05-23 03:48:52 UTC (rev 118112)
@@ -512,6 +512,7 @@
         case GetById:
         case GetByIdFlush:
         case GetByVal:
+        case GetMyArgumentByVal:
         case Call:
         case Construct:
         case GetByOffset:

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (118111 => 118112)


--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2012-05-23 03:36:39 UTC (rev 118111)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2012-05-23 03:48:52 UTC (rev 118112)
@@ -195,6 +195,8 @@
     /* sense. */\
     macro(CreateArguments, NodeResultJS) \
     macro(TearOffArguments, NodeMustGenerate) \
+    macro(GetMyArgumentsLength, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
+    macro(GetMyArgumentByVal, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
     \
     /* Nodes for creating functions. */\
     macro(NewFunctionNoCheck, NodeResultJS) \

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (118111 => 118112)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2012-05-23 03:36:39 UTC (rev 118111)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2012-05-23 03:48:52 UTC (rev 118112)
@@ -1066,6 +1066,20 @@
     asArguments(argumentsCell)->tearOff(exec);
 }
 
+EncodedJSValue DFG_OPERATION operationGetArgumentsLength(ExecState* exec)
+{
+    Identifier ident(&exec->globalData(), "length");
+    JSValue baseValue = exec->uncheckedR(exec->codeBlock()->argumentsRegister()).jsValue();
+    PropertySlot slot(baseValue);
+    return JSValue::encode(baseValue.get(exec, ident, slot));
+}
+
+EncodedJSValue DFG_OPERATION operationGetArgumentByVal(ExecState* exec, int32_t index)
+{
+    return JSValue::encode(
+        exec->uncheckedR(exec->codeBlock()->argumentsRegister()).jsValue().get(exec, index));
+}
+
 JSCell* DFG_OPERATION operationNewFunction(ExecState* exec, JSCell* functionExecutable)
 {
     ASSERT(functionExecutable->inherits(&FunctionExecutable::s_info));

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (118111 => 118112)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.h	2012-05-23 03:36:39 UTC (rev 118111)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h	2012-05-23 03:48:52 UTC (rev 118112)
@@ -60,6 +60,7 @@
     I: Identifier*
     G: GlobalResolveInfo*
 */
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_E)(ExecState*);
 typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EA)(ExecState*, JSArray*);
 typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECC)(ExecState*, JSCell*, JSCell*);
 typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECI)(ExecState*, JSCell*, Identifier*);
@@ -75,6 +76,7 @@
 typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EPP)(ExecState*, void*, void*);
 typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EPS)(ExecState*, void*, size_t);
 typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ESS)(ExecState*, size_t, size_t);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EZ)(ExecState*, int32_t);
 typedef JSCell* DFG_OPERATION (*C_DFGOperation_E)(ExecState*);
 typedef JSCell* DFG_OPERATION (*C_DFGOperation_EC)(ExecState*, JSCell*);
 typedef JSCell* DFG_OPERATION (*C_DFGOperation_ECC)(ExecState*, JSCell*, JSCell*);
@@ -157,6 +159,8 @@
 JSCell* DFG_OPERATION operationCreateArguments(ExecState*);
 void DFG_OPERATION operationTearOffActivation(ExecState*, JSCell*, int32_t unmodifiedArgumentsRegister);
 void DFG_OPERATION operationTearOffArguments(ExecState*, JSCell*);
+EncodedJSValue DFG_OPERATION operationGetArgumentsLength(ExecState*);
+EncodedJSValue DFG_OPERATION operationGetArgumentByVal(ExecState*, int32_t);
 JSCell* DFG_OPERATION operationNewFunction(ExecState*, JSCell*);
 JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState*, JSCell*);
 double DFG_OPERATION operationFModOnInts(int32_t, int32_t);

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (118111 => 118112)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2012-05-23 03:36:39 UTC (rev 118111)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2012-05-23 03:48:52 UTC (rev 118112)
@@ -437,6 +437,17 @@
             break;
         }
             
+        case GetMyArgumentByVal: {
+            changed |= mergePrediction(node.getHeapPrediction());
+            changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
+            break;
+        }
+            
+        case GetMyArgumentsLength: {
+            changed |= setPrediction(PredictInt32);
+            break;
+        }
+            
         case GetPropertyStorage: 
         case GetIndexedPropertyStorage: {
             changed |= setPrediction(PredictOther);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (118111 => 118112)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2012-05-23 03:36:39 UTC (rev 118111)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2012-05-23 03:48:52 UTC (rev 118112)
@@ -1211,6 +1211,11 @@
     // machine registers, and delegate the calling convention specific
     // decision as to how to fill the regsiters to setupArguments* methods.
 #if USE(JSVALUE64)
+    JITCompiler::Call callOperation(J_DFGOperation_E operation, GPRReg result)
+    {
+        m_jit.setupArgumentsExecState();
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
     JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg result, void* pointer)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer));
@@ -1273,6 +1278,11 @@
         m_jit.setupArgumentsWithExecState(arg1);
         return appendCallWithExceptionCheckSetResult(operation, result);
     }
+    JITCompiler::Call callOperation(J_DFGOperation_EZ operation, GPRReg result, GPRReg arg1)
+    {
+        m_jit.setupArgumentsWithExecState(arg1);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
     JITCompiler::Call callOperation(C_DFGOperation_E operation, GPRReg result)
     {
         m_jit.setupArgumentsExecState();
@@ -1431,6 +1441,11 @@
         m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, result);
         return call;
     }
+    JITCompiler::Call callOperation(J_DFGOperation_E operation, GPRReg resultTag, GPRReg resultPayload)
+    {
+        m_jit.setupArgumentsExecState();
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
     JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg resultTag, GPRReg resultPayload, void* pointer)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer));
@@ -1506,6 +1521,11 @@
         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag);
         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
     }
+    JITCompiler::Call callOperation(J_DFGOperation_EZ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1)
+    {
+        m_jit.setupArgumentsWithExecState(arg1);
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
     JITCompiler::Call callOperation(C_DFGOperation_E operation, GPRReg result)
     {
         m_jit.setupArgumentsExecState();
@@ -1651,6 +1671,12 @@
 
 #undef EABI_32BIT_DUMMY_ARG
     
+    template<typename FunctionType>
+    JITCompiler::Call callOperation(
+        FunctionType operation, JSValueRegs result)
+    {
+        return callOperation(operation, result.tagGPR(), result.payloadGPR());
+    }
     template<typename FunctionType, typename ArgumentType1>
     JITCompiler::Call callOperation(
         FunctionType operation, JSValueRegs result, ArgumentType1 arg1)
@@ -1998,8 +2024,10 @@
     
     void compileGetCharCodeAt(Node&);
     void compileGetByValOnString(Node&);
+
     void compileGetByValOnArguments(Node&);
     void compileGetArgumentsLength(Node&);
+    
     void compileValueToInt32(Node&);
     void compileUInt32ToNumber(Node&);
     void compileDoubleAsInt32(Node&);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (118111 => 118112)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2012-05-23 03:36:39 UTC (rev 118111)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2012-05-23 03:48:52 UTC (rev 118112)
@@ -3808,6 +3808,80 @@
         break;
     }
         
+    case GetMyArgumentsLength: {
+        GPRTemporary resultPayload(this);
+        GPRTemporary resultTag(this);
+        GPRReg resultPayloadGPR = resultPayload.gpr();
+        GPRReg resultTagGPR = resultTag.gpr();
+        
+        JITCompiler::Jump created = m_jit.branch32(
+            JITCompiler::NotEqual,
+            JITCompiler::tagFor(m_jit.codeBlock()->argumentsRegister()),
+            TrustedImm32(JSValue::EmptyValueTag));
+        
+        m_jit.load32(JITCompiler::payloadFor(RegisterFile::ArgumentCount), resultPayloadGPR);
+        m_jit.sub32(TrustedImm32(1), resultPayloadGPR);
+        m_jit.move(TrustedImm32(JSValue::Int32Tag), resultTagGPR);
+        
+        // FIXME: the slow path generator should perform a forward speculation that the
+        // result is an integer. For now we postpone the speculation by having this return
+        // a JSValue.
+        
+        addSlowPathGenerator(
+            slowPathCall(
+                created, this, operationGetArgumentsLength,
+                JSValueRegs(resultTagGPR, resultPayloadGPR)));
+        
+        jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex);
+        break;
+    }
+        
+    case GetMyArgumentByVal: {
+        SpeculateStrictInt32Operand index(this, node.child1());
+        GPRTemporary resultPayload(this);
+        GPRTemporary resultTag(this);
+        GPRReg indexGPR = index.gpr();
+        GPRReg resultPayloadGPR = resultPayload.gpr();
+        GPRReg resultTagGPR = resultTag.gpr();
+        
+        JITCompiler::JumpList slowPath;
+        slowPath.append(
+            m_jit.branch32(
+                JITCompiler::NotEqual,
+                JITCompiler::tagFor(m_jit.codeBlock()->argumentsRegister()),
+                TrustedImm32(JSValue::EmptyValueTag)));
+        
+        m_jit.add32(TrustedImm32(1), indexGPR, resultPayloadGPR);
+        slowPath.append(
+            m_jit.branch32(
+                JITCompiler::AboveOrEqual,
+                resultPayloadGPR,
+                JITCompiler::payloadFor(RegisterFile::ArgumentCount)));
+        
+        m_jit.neg32(resultPayloadGPR);
+        
+        m_jit.load32(
+            JITCompiler::BaseIndex(
+                GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight,
+                CallFrame::argumentOffsetIncludingThis(0) * sizeof(Register) +
+                OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)),
+            resultTagGPR);
+        m_jit.load32(
+            JITCompiler::BaseIndex(
+                GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight,
+                CallFrame::argumentOffsetIncludingThis(0) * sizeof(Register) +
+                OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)),
+            resultPayloadGPR);
+        
+        addSlowPathGenerator(
+            slowPathCall(
+                slowPath, this, operationGetArgumentByVal,
+                JSValueRegs(resultTagGPR, resultPayloadGPR), indexGPR));
+        
+        jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex);
+        break;
+    }
+        
     case NewFunctionNoCheck:
         compileNewFunctionNoCheck(node);
         break;

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (118111 => 118112)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2012-05-23 03:36:39 UTC (rev 118111)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2012-05-23 03:48:52 UTC (rev 118112)
@@ -3821,6 +3821,65 @@
         break;
     }
         
+    case GetMyArgumentsLength: {
+        GPRTemporary result(this);
+        GPRReg resultGPR = result.gpr();
+        
+        JITCompiler::Jump created = m_jit.branchTestPtr(
+            JITCompiler::NonZero, JITCompiler::addressFor(m_jit.codeBlock()->argumentsRegister()));
+        
+        m_jit.load32(JITCompiler::payloadFor(RegisterFile::ArgumentCount), resultGPR);
+        m_jit.sub32(TrustedImm32(1), resultGPR);
+        m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
+        
+        // FIXME: the slow path generator should perform a forward speculation that the
+        // result is an integer. For now we postpone the speculation by having this return
+        // a JSValue.
+        
+        addSlowPathGenerator(
+            slowPathCall(
+                created, this, operationGetArgumentsLength, resultGPR));
+        
+        jsValueResult(resultGPR, m_compileIndex);
+        break;
+    }
+        
+    case GetMyArgumentByVal: {
+        SpeculateStrictInt32Operand index(this, node.child1());
+        GPRTemporary result(this);
+        GPRReg indexGPR = index.gpr();
+        GPRReg resultGPR = result.gpr();
+        
+        JITCompiler::JumpList slowPath;
+        slowPath.append(
+            m_jit.branchTestPtr(
+                JITCompiler::NonZero,
+                JITCompiler::addressFor(m_jit.codeBlock()->argumentsRegister())));
+        
+        m_jit.add32(TrustedImm32(1), indexGPR, resultGPR);
+        slowPath.append(
+            m_jit.branch32(
+                JITCompiler::AboveOrEqual,
+                resultGPR,
+                JITCompiler::payloadFor(RegisterFile::ArgumentCount)));
+        
+        m_jit.neg32(resultGPR);
+        m_jit.signExtend32ToPtr(resultGPR, resultGPR);
+        
+        m_jit.loadPtr(
+            JITCompiler::BaseIndex(
+                GPRInfo::callFrameRegister, resultGPR, JITCompiler::TimesEight,
+                CallFrame::argumentOffsetIncludingThis(0) * sizeof(Register)),
+            resultGPR);
+        
+        addSlowPathGenerator(
+            slowPathCall(
+                slowPath, this, operationGetArgumentByVal, resultGPR, indexGPR));
+        
+        jsValueResult(resultGPR, m_compileIndex);
+        break;
+    }
+        
     case NewFunctionNoCheck:
         compileNewFunctionNoCheck(node);
         break;

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (118111 => 118112)


--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2012-05-23 03:36:39 UTC (rev 118111)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2012-05-23 03:48:52 UTC (rev 118112)
@@ -1526,6 +1526,7 @@
     neg32(regT1);
     signExtend32ToPtr(regT1, regT1);
     loadPtr(BaseIndex(callFrameRegister, regT1, TimesEight, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))), regT0);
+    emitValueProfilingSite();
     emitPutVirtualRegister(dst, regT0);
 }
 

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (118111 => 118112)


--- trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2012-05-23 03:36:39 UTC (rev 118111)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2012-05-23 03:48:52 UTC (rev 118112)
@@ -1636,6 +1636,7 @@
     neg32(regT2);
     loadPtr(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) + CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))), regT0);
     loadPtr(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) + CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))), regT1);
+    emitValueProfilingSite();
     emitStore(dst, regT1, regT0);
 }
 

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (118111 => 118112)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2012-05-23 03:36:39 UTC (rev 118111)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2012-05-23 03:48:52 UTC (rev 118112)
@@ -1214,8 +1214,10 @@
     loadi 4[PC], t3
     loadi ThisArgumentOffset + TagOffset[cfr, t2, 8], t0
     loadi ThisArgumentOffset + PayloadOffset[cfr, t2, 8], t1
+    loadi 16[PC], t2
     storei t0, TagOffset[cfr, t3, 8]
     storei t1, PayloadOffset[cfr, t3, 8]
+    valueProfile(t0, t1, t2)
     dispatch(5)
 
 .opGetArgumentByValSlow:

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (118111 => 118112)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2012-05-23 03:36:39 UTC (rev 118111)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2012-05-23 03:48:52 UTC (rev 118112)
@@ -1058,8 +1058,10 @@
     negi t2
     sxi2p t2, t2
     loadis 8[PB, PC, 8], t3
+    loadp 32[PB, PC, 8], t1
     loadp ThisArgumentOffset[cfr, t2, 8], t0
     storep t0, [cfr, t3, 8]
+    valueProfile(t0, t1)
     dispatch(5)
 
 .opGetArgumentByValSlow:
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to