[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

oliver at apple.com oliver at apple.com
Wed Dec 22 13:46:13 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 74e00b03a94ab15256ee8c39764f4a6c7e766176
Author: oliver at apple.com <oliver at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Sat Sep 25 21:42:00 2010 +0000

    2010-09-25  Oliver Hunt  <oliver at apple.com>
    
            Reviewed by Cameron Zwarich.
    
            Avoid constructing arguments object when accessing length and index properties
            https://bugs.webkit.org/show_bug.cgi?id=46572
    
            Add opcodes to read argument length and properties, and then implement them.
            Much like other lazy opcodes these opcodes take a fast path when the arguments
            object has not been instantiated, and fall back on generic access mechanisms
            if they are acting on an instantiated object.
    
            3% win on v8-earleyboyer, no change elsewhere.
    
            * bytecode/CodeBlock.cpp:
            (JSC::CodeBlock::dump):
            * bytecode/Opcode.h:
            * bytecompiler/BytecodeGenerator.cpp:
            (JSC::BytecodeGenerator::emitGetArgumentsLength):
            (JSC::BytecodeGenerator::emitGetArgumentByVal):
            * bytecompiler/BytecodeGenerator.h:
            * bytecompiler/NodesCodegen.cpp:
            (JSC::BracketAccessorNode::emitBytecode):
            (JSC::DotAccessorNode::emitBytecode):
            * interpreter/Interpreter.cpp:
            (JSC::Interpreter::privateExecute):
            * jit/JIT.cpp:
            (JSC::JIT::privateCompileMainPass):
            (JSC::JIT::privateCompileSlowCases):
            * jit/JIT.h:
            * jit/JITOpcodes.cpp:
            (JSC::JIT::emit_op_get_arguments_length):
            (JSC::JIT::emitSlow_op_get_arguments_length):
            (JSC::JIT::emit_op_get_argument_by_val):
            (JSC::JIT::emitSlow_op_get_argument_by_val):
            * jit/JITOpcodes32_64.cpp:
            (JSC::JIT::emit_op_get_arguments_length):
            (JSC::JIT::emitSlow_op_get_arguments_length):
            (JSC::JIT::emit_op_get_argument_by_val):
            (JSC::JIT::emitSlow_op_get_argument_by_val):
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@68338 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index 891ac10..5bdbd34 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,44 @@
+2010-09-25  Oliver Hunt  <oliver at apple.com>
+
+        Reviewed by Cameron Zwarich.
+
+        Avoid constructing arguments object when accessing length and index properties
+        https://bugs.webkit.org/show_bug.cgi?id=46572
+
+        Add opcodes to read argument length and properties, and then implement them.
+        Much like other lazy opcodes these opcodes take a fast path when the arguments
+        object has not been instantiated, and fall back on generic access mechanisms
+        if they are acting on an instantiated object.
+
+        3% win on v8-earleyboyer, no change elsewhere.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dump):
+        * bytecode/Opcode.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitGetArgumentsLength):
+        (JSC::BytecodeGenerator::emitGetArgumentByVal):
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::BracketAccessorNode::emitBytecode):
+        (JSC::DotAccessorNode::emitBytecode):
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::privateExecute):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        (JSC::JIT::privateCompileSlowCases):
+        * jit/JIT.h:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_get_arguments_length):
+        (JSC::JIT::emitSlow_op_get_arguments_length):
+        (JSC::JIT::emit_op_get_argument_by_val):
+        (JSC::JIT::emitSlow_op_get_argument_by_val):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_get_arguments_length):
+        (JSC::JIT::emitSlow_op_get_arguments_length):
+        (JSC::JIT::emit_op_get_argument_by_val):
+        (JSC::JIT::emitSlow_op_get_argument_by_val):
+
 2010-09-25  Patrick Gansterer  <paroga at webkit.org>
 
         Unreviewed.
diff --git a/JavaScriptCore/bytecode/CodeBlock.cpp b/JavaScriptCore/bytecode/CodeBlock.cpp
index 849f2ba..b8dc3eb 100644
--- a/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -842,6 +842,10 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printGetByIdOp(exec, location, it, "get_string_length");
             break;
         }
+        case op_get_arguments_length: {
+            printUnaryOp(exec, location, it, "get_arguments_length");
+            break;
+        }
         case op_put_by_id: {
             printPutByIdOp(exec, location, it, "put_by_id");
             break;
@@ -890,6 +894,13 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
             break;
         }
+        case op_get_argument_by_val: {
+            int r0 = (++it)->u.operand;
+            int r1 = (++it)->u.operand;
+            int r2 = (++it)->u.operand;
+            printf("[%4d] get_argument_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
+            break;
+        }
         case op_get_by_pname: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
diff --git a/JavaScriptCore/bytecode/Opcode.h b/JavaScriptCore/bytecode/Opcode.h
index 68e52e7..03f6573 100644
--- a/JavaScriptCore/bytecode/Opcode.h
+++ b/JavaScriptCore/bytecode/Opcode.h
@@ -120,12 +120,14 @@ namespace JSC {
         macro(op_get_by_id_generic, 8) \
         macro(op_get_array_length, 8) \
         macro(op_get_string_length, 8) \
+        macro(op_get_arguments_length, 4) \
         macro(op_put_by_id, 9) \
         macro(op_put_by_id_transition, 9) \
         macro(op_put_by_id_replace, 9) \
         macro(op_put_by_id_generic, 9) \
         macro(op_del_by_id, 4) \
         macro(op_get_by_val, 4) \
+        macro(op_get_argument_by_val, 4) \
         macro(op_get_by_pname, 7) \
         macro(op_put_by_val, 4) \
         macro(op_del_by_val, 4) \
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index f2bbb77..3b2c2ca 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -1328,6 +1328,16 @@ RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, co
     return dst;
 }
 
+RegisterID* BytecodeGenerator::emitGetArgumentsLength(RegisterID* dst, RegisterID* base)
+{
+    emitOpcode(op_get_arguments_length);
+    instructions().append(dst->index());
+    ASSERT(base->index() == m_codeBlock->argumentsRegister());
+    instructions().append(base->index());
+    instructions().append(addConstant(propertyNames().arguments));
+    return dst;
+}
+
 RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
 {
 #if ENABLE(JIT)
@@ -1395,6 +1405,16 @@ RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base,
     return dst;
 }
 
+RegisterID* BytecodeGenerator::emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
+{
+    emitOpcode(op_get_argument_by_val);
+    instructions().append(dst->index());
+    ASSERT(base->index() == m_codeBlock->argumentsRegister());
+    instructions().append(base->index());
+    instructions().append(property->index());
+    return dst;
+}
+
 RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
 {
     for (size_t i = m_forInContextStack.size(); i > 0; i--) {
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index 5fbe864..2afa0c4 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -334,10 +334,12 @@ namespace JSC {
         void emitMethodCheck();
 
         RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
+        RegisterID* emitGetArgumentsLength(RegisterID* dst, RegisterID* base);
         RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value);
         RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value);
         RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&);
         RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
+        RegisterID* emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
         RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
         RegisterID* emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
         RegisterID* emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value);
diff --git a/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index f098ba6..2cc1a3f 100644
--- a/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -290,6 +290,12 @@ RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, Registe
 
 RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
+    if (m_base->isResolveNode() && generator.willResolveToArguments(static_cast<ResolveNode*>(m_base)->identifier())) {
+        RegisterID* property = generator.emitNode(m_subscript);
+        generator.emitExpressionInfo(divot(), startOffset(), endOffset());    
+        return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedRegisterForArguments(), property);
+    }
+
     RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
     RegisterID* property = generator.emitNode(m_subscript);
     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
@@ -300,6 +306,17 @@ RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, Regi
 
 RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
+    if (m_ident == generator.propertyNames().length) {
+        if (!m_base->isResolveNode())
+            goto nonArgumentsPath;
+        ResolveNode* resolveNode = static_cast<ResolveNode*>(m_base);
+        if (!generator.willResolveToArguments(resolveNode->identifier()))
+            goto nonArgumentsPath;
+        generator.emitExpressionInfo(divot(), startOffset(), endOffset());    
+        return generator.emitGetArgumentsLength(generator.finalDestination(dst), generator.uncheckedRegisterForArguments());
+    }
+
+nonArgumentsPath:
     RegisterID* base = generator.emitNode(m_base);
     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
     return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp
index f8abc6a..abacc29 100644
--- a/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/JavaScriptCore/interpreter/Interpreter.cpp
@@ -3091,6 +3091,46 @@ skip_id_custom_self:
         vPC += OPCODE_LENGTH(op_get_by_pname);
         NEXT_INSTRUCTION();
     }
+    DEFINE_OPCODE(op_get_arguments_length) {
+        int dst = vPC[1].u.operand;
+        int argumentsRegister = vPC[2].u.operand;
+        int property = vPC[3].u.operand;
+        JSValue arguments = callFrame->r(argumentsRegister).jsValue();
+        if (arguments) {
+            Identifier& ident = codeBlock->identifier(property);
+            PropertySlot slot(arguments);
+            JSValue result = arguments.get(callFrame, ident, slot);
+            CHECK_FOR_EXCEPTION();
+            callFrame->r(dst) = result;
+        } else
+            callFrame->r(dst) = jsNumber(callFrame, callFrame->argumentCount());
+
+        vPC += OPCODE_LENGTH(op_get_arguments_length);
+        NEXT_INSTRUCTION();
+    }
+    DEFINE_OPCODE(op_get_argument_by_val) {
+        int dst = vPC[1].u.operand;
+        int argumentsRegister = vPC[2].u.operand;
+        int property = vPC[3].u.operand;
+        JSValue arguments = callFrame->r(argumentsRegister).jsValue();
+        JSValue subscript = callFrame->r(property).jsValue();
+        if (!arguments && subscript.isUInt32() && subscript.asUInt32() < callFrame->argumentCount()) {
+            unsigned arg = subscript.asUInt32() + 1;
+            unsigned numParameters = callFrame->codeBlock()->m_numParameters;
+            if (arg < numParameters)
+                callFrame->r(dst) = callFrame->r(arg - RegisterFile::CallFrameHeaderSize - numParameters);
+            else
+                callFrame->r(dst) = callFrame->r(arg - RegisterFile::CallFrameHeaderSize - numParameters - callFrame->argumentCount() - 1);
+            vPC += OPCODE_LENGTH(op_get_argument_by_val);
+            NEXT_INSTRUCTION();
+        }
+        if (!arguments) {
+            Arguments* arguments = new (globalData) Arguments(callFrame);
+            callFrame->r(dst) = JSValue(arguments);
+            callFrame->r(unmodifiedArgumentsRegister(dst)) = JSValue(arguments);
+        }
+        // fallthrough
+    }
     DEFINE_OPCODE(op_get_by_val) {
         /* get_by_val dst(r) base(r) property(r)
 
diff --git a/JavaScriptCore/jit/JIT.cpp b/JavaScriptCore/jit/JIT.cpp
index ac7277a..a508d0c 100644
--- a/JavaScriptCore/jit/JIT.cpp
+++ b/JavaScriptCore/jit/JIT.cpp
@@ -238,7 +238,9 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_eq)
         DEFINE_OP(op_eq_null)
         DEFINE_OP(op_get_by_id)
+        DEFINE_OP(op_get_arguments_length)
         DEFINE_OP(op_get_by_val)
+        DEFINE_OP(op_get_argument_by_val)
         DEFINE_OP(op_get_by_pname)
         DEFINE_OP(op_get_global_var)
         DEFINE_OP(op_get_pnames)
@@ -399,7 +401,9 @@ void JIT::privateCompileSlowCases()
 #endif
         DEFINE_SLOWCASE_OP(op_eq)
         DEFINE_SLOWCASE_OP(op_get_by_id)
+        DEFINE_SLOWCASE_OP(op_get_arguments_length)
         DEFINE_SLOWCASE_OP(op_get_by_val)
+        DEFINE_SLOWCASE_OP(op_get_argument_by_val)
         DEFINE_SLOWCASE_OP(op_get_by_pname)
         DEFINE_SLOWCASE_OP(op_instanceof)
         DEFINE_SLOWCASE_OP(op_jfalse)
diff --git a/JavaScriptCore/jit/JIT.h b/JavaScriptCore/jit/JIT.h
index 676a5c5..6b2e70e 100644
--- a/JavaScriptCore/jit/JIT.h
+++ b/JavaScriptCore/jit/JIT.h
@@ -748,7 +748,9 @@ namespace JSC {
         void emit_op_eq(Instruction*);
         void emit_op_eq_null(Instruction*);
         void emit_op_get_by_id(Instruction*);
+        void emit_op_get_arguments_length(Instruction*);
         void emit_op_get_by_val(Instruction*);
+        void emit_op_get_argument_by_val(Instruction*);
         void emit_op_get_by_pname(Instruction*);
         void emit_op_get_global_var(Instruction*);
         void emit_op_get_scoped_var(Instruction*);
@@ -846,7 +848,9 @@ namespace JSC {
         void emitSlow_op_div(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_eq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_get_arguments_length(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_get_argument_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_by_pname(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_instanceof(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jfalse(Instruction*, Vector<SlowCaseEntry>::iterator&);
diff --git a/JavaScriptCore/jit/JITOpcodes.cpp b/JavaScriptCore/jit/JITOpcodes.cpp
index 7905cd1..35cd678 100644
--- a/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/JavaScriptCore/jit/JITOpcodes.cpp
@@ -1470,6 +1470,88 @@ void JIT::emitSlow_op_to_jsnumber(Instruction* currentInstruction, Vector<SlowCa
     stubCall.call(currentInstruction[1].u.operand);
 }
 
+void JIT::emit_op_get_arguments_length(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int argumentsRegister = currentInstruction[2].u.operand;
+    addSlowCase(branchTestPtr(NonZero, addressFor(argumentsRegister)));
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
+    sub32(Imm32(1), regT0);
+    emitFastArithReTagImmediate(regT0, regT0);
+    emitPutVirtualRegister(dst, regT0);
+}
+
+void JIT::emitSlow_op_get_arguments_length(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    linkSlowCase(iter);
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned base = currentInstruction[2].u.operand;
+    Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
+    
+    emitGetVirtualRegister(base, regT0);
+    JITStubCall stubCall(this, cti_op_get_by_id_generic);
+    stubCall.addArgument(regT0);
+    stubCall.addArgument(ImmPtr(ident));
+    stubCall.call(dst);
+}
+
+void JIT::emit_op_get_argument_by_val(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int argumentsRegister = currentInstruction[2].u.operand;
+    int property = currentInstruction[3].u.operand;
+    addSlowCase(branchTestPtr(NonZero, addressFor(argumentsRegister)));
+    emitGetVirtualRegister(property, regT1);
+    addSlowCase(emitJumpIfNotImmediateInteger(regT1));
+    add32(Imm32(1), regT1);
+    // regT1 now contains the integer index of the argument we want, including this
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT2);
+    addSlowCase(branch32(AboveOrEqual, regT1, regT2));
+    
+    Jump skipOutofLineParams;
+    int numArgs = m_codeBlock->m_numParameters;
+    if (numArgs) {
+        Jump notInInPlaceArgs = branch32(AboveOrEqual, regT1, Imm32(numArgs));
+        addPtr(Imm32(static_cast<unsigned>(-(RegisterFile::CallFrameHeaderSize + numArgs) * sizeof(Register))), callFrameRegister, regT0);
+        loadPtr(BaseIndex(regT0, regT1, TimesEight, 0), regT0);
+        skipOutofLineParams = jump();
+        notInInPlaceArgs.link(this);
+    }
+    
+    addPtr(Imm32(static_cast<unsigned>(-(RegisterFile::CallFrameHeaderSize + numArgs) * sizeof(Register))), callFrameRegister, regT0);
+    mul32(Imm32(sizeof(Register)), regT2, regT2);
+    subPtr(regT2, regT0);
+    loadPtr(BaseIndex(regT0, regT1, TimesEight, 0), regT0);
+    if (numArgs)
+        skipOutofLineParams.link(this);
+    emitPutVirtualRegister(dst, regT0);
+}
+
+void JIT::emitSlow_op_get_argument_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned arguments = currentInstruction[2].u.operand;
+    unsigned property = currentInstruction[3].u.operand;
+    
+    linkSlowCase(iter);
+    Jump skipArgumentsCreation = jump();
+    
+    linkSlowCase(iter);
+    linkSlowCase(iter);
+    if (m_codeBlock->m_numParameters == 1)
+        JITStubCall(this, cti_op_create_arguments_no_params).call();
+    else
+        JITStubCall(this, cti_op_create_arguments).call();
+    emitPutVirtualRegister(dst);
+    emitPutVirtualRegister(unmodifiedArgumentsRegister(dst));
+    
+    skipArgumentsCreation.link(this);
+    JITStubCall stubCall(this, cti_op_get_by_val);
+    stubCall.addArgument(arguments, regT2);
+    stubCall.addArgument(property, regT2);
+    stubCall.call(dst);
+}
+
 #endif // !USE(JSVALUE32_64)
 
 void JIT::emit_op_resolve_global_dynamic(Instruction* currentInstruction)
diff --git a/JavaScriptCore/jit/JITOpcodes32_64.cpp b/JavaScriptCore/jit/JITOpcodes32_64.cpp
index ef710ef..ad3b558 100644
--- a/JavaScriptCore/jit/JITOpcodes32_64.cpp
+++ b/JavaScriptCore/jit/JITOpcodes32_64.cpp
@@ -1562,6 +1562,89 @@ void JIT::emit_op_profile_did_call(Instruction* currentInstruction)
     noProfiler.link(this);
 }
 
+void JIT::emit_op_get_arguments_length(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int argumentsRegister = currentInstruction[2].u.operand;
+    addSlowCase(branch32(NotEqual, tagFor(argumentsRegister), Imm32(JSValue::EmptyValueTag)));
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
+    sub32(Imm32(1), regT0);
+    emitStoreInt32(dst, regT0);
+}
+
+void JIT::emitSlow_op_get_arguments_length(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    linkSlowCase(iter);
+    int dst = currentInstruction[1].u.operand;
+    int base = currentInstruction[2].u.operand;
+    int ident = currentInstruction[3].u.operand;
+    
+    JITStubCall stubCall(this, cti_op_get_by_id_generic);
+    stubCall.addArgument(base);
+    stubCall.addArgument(ImmPtr(&(m_codeBlock->identifier(ident))));
+    stubCall.call(dst);
+}
+
+void JIT::emit_op_get_argument_by_val(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int argumentsRegister = currentInstruction[2].u.operand;
+    int property = currentInstruction[3].u.operand;
+    addSlowCase(branch32(NotEqual, tagFor(argumentsRegister), Imm32(JSValue::EmptyValueTag)));
+    emitLoad(property, regT1, regT2);
+    addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+    add32(Imm32(1), regT2);
+    // regT2 now contains the integer index of the argument we want, including this
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT3);
+    addSlowCase(branch32(AboveOrEqual, regT2, regT3));
+    
+    Jump skipOutofLineParams;
+    int numArgs = m_codeBlock->m_numParameters;
+    if (numArgs) {
+        Jump notInInPlaceArgs = branch32(AboveOrEqual, regT2, Imm32(numArgs));
+        addPtr(Imm32(static_cast<unsigned>(-(RegisterFile::CallFrameHeaderSize + numArgs) * sizeof(Register))), callFrameRegister, regT1);
+        loadPtr(BaseIndex(regT1, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
+        loadPtr(BaseIndex(regT1, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
+        skipOutofLineParams = jump();
+        notInInPlaceArgs.link(this);
+    }
+
+    addPtr(Imm32(static_cast<unsigned>(-(RegisterFile::CallFrameHeaderSize + numArgs) * sizeof(Register))), callFrameRegister, regT1);
+    mul32(Imm32(sizeof(Register)), regT3, regT3);
+    subPtr(regT3, regT1);
+    loadPtr(BaseIndex(regT1, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
+    loadPtr(BaseIndex(regT1, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
+    if (numArgs)
+        skipOutofLineParams.link(this);
+    emitStore(dst, regT1, regT0);
+}
+
+void JIT::emitSlow_op_get_argument_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned arguments = currentInstruction[2].u.operand;
+    unsigned property = currentInstruction[3].u.operand;
+
+    linkSlowCase(iter);
+    Jump skipArgumentsCreation = jump();
+
+    linkSlowCase(iter);
+    linkSlowCase(iter);
+    if (m_codeBlock->m_numParameters == 1)
+        JITStubCall(this, cti_op_create_arguments_no_params).call();
+    else
+        JITStubCall(this, cti_op_create_arguments).call();
+    
+    emitStore(arguments, regT1, regT0);
+    emitStore(unmodifiedArgumentsRegister(arguments), regT1, regT0);
+    
+    skipArgumentsCreation.link(this);
+    JITStubCall stubCall(this, cti_op_get_by_val);
+    stubCall.addArgument(arguments);
+    stubCall.addArgument(property);
+    stubCall.call(dst);
+}
+
 } // namespace JSC
 
 #endif // USE(JSVALUE32_64)

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list