2010-09-25 Oliver Hunt <oliver@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@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@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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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* 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* 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 @@
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 @@
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 @@
#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 @@
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 @@
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 @@
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 @@
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)