Revision: 3856
Author: [email protected]
Date: Mon Feb 15 04:26:07 2010
Log: Change CallIC interface on ARM. Remove name from the stack, and pass
it in register r2.
Review URL: http://codereview.chromium.org/598065
http://code.google.com/p/v8/source/detail?r=3856
Modified:
/branches/bleeding_edge/src/arm/builtins-arm.cc
/branches/bleeding_edge/src/arm/codegen-arm.cc
/branches/bleeding_edge/src/arm/full-codegen-arm.cc
/branches/bleeding_edge/src/arm/ic-arm.cc
/branches/bleeding_edge/src/arm/stub-cache-arm.cc
=======================================
--- /branches/bleeding_edge/src/arm/builtins-arm.cc Fri Jan 15 04:25:24 2010
+++ /branches/bleeding_edge/src/arm/builtins-arm.cc Mon Feb 15 04:26:07 2010
@@ -915,7 +915,7 @@
}
// 2. Get the function to call from the stack.
- // r0: actual number of argument
+ // r0: actual number of arguments
{ Label done, non_function, function;
__ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
__ tst(r1, Operand(kSmiTagMask));
@@ -997,13 +997,27 @@
__ bind(&done);
}
- // 4. Shift stuff one slot down the stack
+ // 4. Handle non-functions.
// r0: actual number of arguments (including call() receiver)
// r1: function
+ { Label done;
+ __ tst(r1, r1);
+ __ b(ne, &done);
+ __ mov(r2, Operand(0)); // expected arguments is 0 for
CALL_NON_FUNCTION
+ // Transfer the receiver from the first argument to the top of the
+ // caller's expression stack simply by decrementing argc.
+ __ sub(r0, r0, Operand(1));
+ __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
+ __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
+ RelocInfo::CODE_TARGET);
+ __ bind(&done);
+ }
+
+ // 5. Shift arguments one slot toward the bottom of the
+ // stack, overwriting the receiver.
{ Label loop;
// Calculate the copy start address (destination). Copy end address is
sp.
__ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
- __ add(r2, r2, Operand(kPointerSize)); // copy receiver too
__ bind(&loop);
__ ldr(ip, MemOperand(r2, -kPointerSize));
@@ -1011,43 +1025,28 @@
__ sub(r2, r2, Operand(kPointerSize));
__ cmp(r2, sp);
__ b(ne, &loop);
- }
-
- // 5. Adjust the actual number of arguments and remove the top element.
- // r0: actual number of arguments (including call() receiver)
- // r1: function
- __ sub(r0, r0, Operand(1));
- __ add(sp, sp, Operand(kPointerSize));
+ // Adjust the actual number of arguments and remove the top element.
+ __ sub(r0, r0, Operand(1));
+ __ pop();
+ }
// 6. Get the code for the function or the non-function builtin.
// If number of expected arguments matches, then call. Otherwise
restart
// the arguments adaptor stub.
// r0: actual number of arguments
// r1: function
- { Label invoke;
- __ tst(r1, r1);
- __ b(ne, &invoke);
- __ mov(r2, Operand(0)); // expected arguments is 0 for
CALL_NON_FUNCTION
- __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
- __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
- RelocInfo::CODE_TARGET);
-
- __ bind(&invoke);
- __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
- __ ldr(r2,
- FieldMemOperand(r3,
-
SharedFunctionInfo::kFormalParameterCountOffset));
- __ ldr(r3,
- MemOperand(r3, SharedFunctionInfo::kCodeOffset -
kHeapObjectTag));
- __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
- __ cmp(r2, r0); // Check formal and actual parameter counts.
- __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
- RelocInfo::CODE_TARGET, ne);
-
- // 7. Jump to the code in r3 without checking arguments.
- ParameterCount expected(0);
- __ InvokeCode(r3, expected, expected, JUMP_FUNCTION);
- }
+ __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
+ __ ldr(r2,
+ FieldMemOperand(r3,
SharedFunctionInfo::kFormalParameterCountOffset));
+ __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset));
+ __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
+ __ cmp(r2, r0); // Check formal and actual parameter counts.
+ __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
+ RelocInfo::CODE_TARGET, ne);
+
+ // 7. Jump (tail-call) to the code in r3 without checking arguments.
+ ParameterCount expected(0);
+ __ InvokeCode(r3, expected, expected, JUMP_FUNCTION);
}
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc Thu Feb 11 04:28:49 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc Mon Feb 15 04:26:07 2010
@@ -3023,11 +3023,6 @@
// ----------------------------------
// JavaScript example: 'foo(1, 2, 3)' // foo is global
// ----------------------------------
-
- // Push the name of the function and the receiver onto the stack.
- __ mov(r0, Operand(var->name()));
- frame_->EmitPush(r0);
-
// Pass the global object as the receiver and let the IC stub
// patch the stack to use the global proxy as 'this' in the
// invoked function.
@@ -3039,15 +3034,14 @@
LoadAndSpill(args->at(i));
}
- // Setup the receiver register and call the IC initialization code.
+ // Setup the name register and call the IC initialization code.
+ __ mov(r2, Operand(var->name()));
InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop);
CodeForSourcePosition(node->position());
frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT,
arg_count + 1);
__ ldr(cp, frame_->Context());
- // Remove the function from the stack.
- frame_->Drop();
frame_->EmitPush(r0);
} else if (var != NULL && var->slot() != NULL &&
@@ -3080,28 +3074,21 @@
// JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)'
// ------------------------------------------------------------------
- // Push the name of the function and the receiver onto the stack.
- __ mov(r0, Operand(literal->handle()));
- frame_->EmitPush(r0);
- LoadAndSpill(property->obj());
-
+ LoadAndSpill(property->obj()); // Receiver.
// Load the arguments.
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
LoadAndSpill(args->at(i));
}
- // Set the receiver register and call the IC initialization code.
+ // Set the name register and call the IC initialization code.
+ __ mov(r2, Operand(literal->handle()));
InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop);
CodeForSourcePosition(node->position());
frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
__ ldr(cp, frame_->Context());
-
- // Remove the function from the stack.
- frame_->Drop();
-
- frame_->EmitPush(r0); // push after get rid of function from the
stack
+ frame_->EmitPush(r0);
} else {
// -------------------------------------------
@@ -3636,8 +3623,6 @@
if (function == NULL) {
// Prepare stack for calling JS runtime function.
- __ mov(r0, Operand(node->name()));
- frame_->EmitPush(r0);
// Push the builtins object found in the current global object.
__ ldr(r1, GlobalObject());
__ ldr(r0, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset));
@@ -3652,11 +3637,11 @@
if (function == NULL) {
// Call the JS runtime function.
+ __ mov(r2, Operand(node->name()));
InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop);
frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
__ ldr(cp, frame_->Context());
- frame_->Drop();
frame_->EmitPush(r0);
} else {
// Call the C runtime function.
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Wed Feb 10 07:06:08
2010
+++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Mon Feb 15 04:26:07
2010
@@ -1090,7 +1090,7 @@
}
void FullCodeGenerator::EmitCallWithIC(Call* expr,
- Handle<Object> ignored,
+ Handle<Object> name,
RelocInfo::Mode mode) {
// Code common for calls using the IC.
ZoneList<Expression*>* args = expr->arguments();
@@ -1098,16 +1098,16 @@
for (int i = 0; i < arg_count; i++) {
VisitForValue(args->at(i), kStack);
}
+ __ mov(r2, Operand(name));
// Record source position for debugger.
SetSourcePosition(expr->position());
// Call the IC initialization code.
- Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
- NOT_IN_LOOP);
+ InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
+ Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
in_loop);
__ Call(ic, mode);
// Restore context register.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
- // Discard the function left on TOS.
- DropAndApply(1, context_, r0);
+ Apply(context_, r0);
}
@@ -1124,7 +1124,6 @@
__ CallStub(&stub);
// Restore context register.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
- // Discard the function left on TOS.
DropAndApply(1, context_, r0);
}
@@ -1138,11 +1137,9 @@
// Call to the identifier 'eval'.
UNREACHABLE();
} else if (var != NULL && !var->is_this() && var->is_global()) {
- // Call to a global variable.
- __ mov(r1, Operand(var->name()));
- // Push global object as receiver for the call IC lookup.
+ // Push global object as receiver for the call IC.
__ ldr(r0, CodeGenerator::GlobalObject());
- __ stm(db_w, sp, r1.bit() | r0.bit());
+ __ push(r0);
EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
} else if (var != NULL && var->slot() != NULL &&
var->slot()->type() == Slot::LOOKUP) {
@@ -1154,8 +1151,6 @@
Literal* key = prop->key()->AsLiteral();
if (key != NULL && key->handle()->IsSymbol()) {
// Call to a named property, use call IC.
- __ mov(r0, Operand(key->handle()));
- __ push(r0);
VisitForValue(prop->obj(), kStack);
EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
} else {
@@ -1241,10 +1236,9 @@
if (expr->is_jsruntime()) {
// Prepare for calling JS runtime function.
- __ mov(r1, Operand(expr->name()));
__ ldr(r0, CodeGenerator::GlobalObject());
__ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset));
- __ stm(db_w, sp, r1.bit() | r0.bit());
+ __ push(r0);
}
// Push the arguments ("left-to-right").
@@ -1255,18 +1249,17 @@
if (expr->is_jsruntime()) {
// Call the JS runtime function.
+ __ mov(r2, Operand(expr->name()));
Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
NOT_IN_LOOP);
__ Call(ic, RelocInfo::CODE_TARGET);
// Restore context register.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
- // Discard the function left on TOS.
- DropAndApply(1, context_, r0);
} else {
// Call the C runtime function.
__ CallRuntime(expr->function(), arg_count);
- Apply(context_, r0);
- }
+ }
+ Apply(context_, r0);
}
=======================================
--- /branches/bleeding_edge/src/arm/ic-arm.cc Fri Feb 12 06:21:18 2010
+++ /branches/bleeding_edge/src/arm/ic-arm.cc Mon Feb 15 04:26:07 2010
@@ -59,7 +59,7 @@
// r3 - used as temporary and to hold the capacity of the property
// dictionary.
//
- // r2 - holds the name of the property and is unchanges.
+ // r2 - holds the name of the property and is unchanged.
Label done;
@@ -219,14 +219,13 @@
void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
// ----------- S t a t e -------------
- // -- lr: return address
+ // -- r2 : name
+ // -- lr : return address
// -----------------------------------
Label number, non_number, non_string, boolean, probe, miss;
// Get the receiver of the function from the stack into r1.
__ ldr(r1, MemOperand(sp, argc * kPointerSize));
- // Get the name of the function from the stack; 1 ~ receiver.
- __ ldr(r2, MemOperand(sp, (argc + 1) * kPointerSize));
// Probe the stub cache.
Code::Flags flags =
@@ -301,9 +300,9 @@
// Patch the receiver with the global proxy if necessary.
if (is_global_object) {
- __ ldr(r2, MemOperand(sp, argc * kPointerSize));
- __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
- __ str(r2, MemOperand(sp, argc * kPointerSize));
+ __ ldr(r0, MemOperand(sp, argc * kPointerSize));
+ __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
+ __ str(r0, MemOperand(sp, argc * kPointerSize));
}
// Invoke the function.
@@ -314,14 +313,13 @@
void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
// ----------- S t a t e -------------
- // -- lr: return address
+ // -- r2 : name
+ // -- lr : return address
// -----------------------------------
Label miss, global_object, non_global_object;
// Get the receiver of the function from the stack into r1.
__ ldr(r1, MemOperand(sp, argc * kPointerSize));
- // Get the name of the function from the stack; 1 ~ receiver.
- __ ldr(r2, MemOperand(sp, (argc + 1) * kPointerSize));
// Check that the receiver isn't a smi.
__ tst(r1, Operand(kSmiTagMask));
@@ -374,18 +372,17 @@
void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
// ----------- S t a t e -------------
- // -- lr: return address
+ // -- r2 : name
+ // -- lr : return address
// -----------------------------------
// Get the receiver of the function from the stack.
- __ ldr(r2, MemOperand(sp, argc * kPointerSize));
- // Get the name of the function to call from the stack.
- __ ldr(r1, MemOperand(sp, (argc + 1) * kPointerSize));
+ __ ldr(r3, MemOperand(sp, argc * kPointerSize));
__ EnterInternalFrame();
// Push the receiver and the name of the function.
- __ stm(db_w, sp, r1.bit() | r2.bit());
+ __ stm(db_w, sp, r2.bit() | r3.bit());
// Call the entry.
__ mov(r0, Operand(2));
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Mon Feb 15 03:52:18
2010
+++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Mon Feb 15 04:26:07
2010
@@ -376,7 +376,7 @@
// Check that the function really is a function.
__ BranchOnSmi(r1, miss);
- __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
+ __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
__ b(ne, miss);
// Patch the receiver on the stack with the global proxy if
@@ -803,7 +803,8 @@
int index,
String* name) {
// ----------- S t a t e -------------
- // -- lr: return address
+ // -- r2 : name
+ // -- lr : return address
// -----------------------------------
Label miss;
@@ -817,7 +818,7 @@
// Do the right check and compute the holder register.
Register reg =
- CheckPrototypes(JSObject::cast(object), r0, holder, r3, r2, name,
&miss);
+ CheckPrototypes(JSObject::cast(object), r0, holder, r1, r3, name,
&miss);
GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
GenerateCallFunction(masm(), object, arguments(), &miss);
@@ -838,7 +839,8 @@
String* name,
CheckType check) {
// ----------- S t a t e -------------
- // -- lr: return address
+ // -- r2 : name
+ // -- lr : return address
// -----------------------------------
Label miss;
@@ -859,7 +861,7 @@
switch (check) {
case RECEIVER_MAP_CHECK:
// Check that the maps haven't changed.
- CheckPrototypes(JSObject::cast(object), r1, holder, r3, r2, name,
&miss);
+ CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name,
&miss);
// Patch the receiver on the stack with the global proxy if
// necessary.
@@ -875,13 +877,13 @@
__ jmp(&miss);
} else {
// Check that the object is a two-byte string or a symbol.
- __ CompareObjectType(r1, r2, r2, FIRST_NONSTRING_TYPE);
+ __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE);
__ b(hs, &miss);
// Check that the maps starting from the prototype haven't changed.
GenerateLoadGlobalFunctionPrototype(masm(),
Context::STRING_FUNCTION_INDEX,
- r2);
- CheckPrototypes(JSObject::cast(object->GetPrototype()), r2,
holder, r3,
+ r0);
+ CheckPrototypes(JSObject::cast(object->GetPrototype()), r0,
holder, r3,
r1, name, &miss);
}
break;
@@ -895,14 +897,14 @@
// Check that the object is a smi or a heap number.
__ tst(r1, Operand(kSmiTagMask));
__ b(eq, &fast);
- __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE);
+ __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE);
__ b(ne, &miss);
__ bind(&fast);
// Check that the maps starting from the prototype haven't changed.
GenerateLoadGlobalFunctionPrototype(masm(),
Context::NUMBER_FUNCTION_INDEX,
- r2);
- CheckPrototypes(JSObject::cast(object->GetPrototype()), r2,
holder, r3,
+ r0);
+ CheckPrototypes(JSObject::cast(object->GetPrototype()), r0,
holder, r3,
r1, name, &miss);
}
break;
@@ -925,22 +927,22 @@
// Check that the maps starting from the prototype haven't changed.
GenerateLoadGlobalFunctionPrototype(masm(),
Context::BOOLEAN_FUNCTION_INDEX,
- r2);
- CheckPrototypes(JSObject::cast(object->GetPrototype()), r2,
holder, r3,
+ r0);
+ CheckPrototypes(JSObject::cast(object->GetPrototype()), r0,
holder, r3,
r1, name, &miss);
}
break;
}
case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
- CheckPrototypes(JSObject::cast(object), r1, holder, r3, r2, name,
&miss);
+ CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name,
&miss);
// Make sure object->HasFastElements().
// Get the elements array of the object.
__ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset));
// Check that the object is in fast mode (not dictionary).
- __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
+ __ ldr(r0, FieldMemOperand(r3, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
- __ cmp(r2, ip);
+ __ cmp(r0, ip);
__ b(ne, &miss);
break;
@@ -968,15 +970,16 @@
JSObject* holder,
String* name) {
// ----------- S t a t e -------------
- // -- lr: return address
+ // -- r2 : name
+ // -- lr : return address
// -----------------------------------
ASSERT(holder->HasNamedInterceptor());
ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
Label miss;
const Register receiver = r0;
- const Register name_reg = r1;
- const Register holder_reg = r2;
+ const Register holder_reg = r1;
+ const Register name_reg = r2;
const Register scratch = r3;
// Get the number of arguments.
@@ -985,10 +988,8 @@
LookupResult lookup;
LookupPostInterceptor(holder, name, &lookup);
- // Load the receiver from the stack.
- __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
- // Load the name from the stack.
- __ ldr(name_reg, MemOperand(sp, (argc + 1) * kPointerSize));
+ // Get the receiver from the stack into r0.
+ __ ldr(r0, MemOperand(sp, argc * kPointerSize));
// Check that the receiver isn't a smi.
__ BranchOnSmi(receiver, &miss);
@@ -1060,10 +1061,8 @@
__ pop(name_reg);
__ LeaveInternalFrame();
}
-
// Move returned value, the function to call, to r1.
- // Neither receiver nor name contain their original value at this point.
__ mov(r1, r0);
// Restore receiver.
__ ldr(receiver, MemOperand(sp, argc * kPointerSize));
@@ -1086,7 +1085,8 @@
JSFunction* function,
String* name) {
// ----------- S t a t e -------------
- // -- lr: return address
+ // -- r2 : name
+ // -- lr : return address
// -----------------------------------
Label miss;
@@ -1105,7 +1105,7 @@
}
// Check that the maps haven't changed.
- CheckPrototypes(object, r0, holder, r3, r2, name, &miss);
+ CheckPrototypes(object, r0, holder, r3, r1, name, &miss);
// Get the value from the cell.
__ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell)));
@@ -1125,8 +1125,8 @@
// Check the shared function info. Make sure it hasn't changed.
__ mov(r3, Operand(Handle<SharedFunctionInfo>(function->shared())));
- __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
- __ cmp(r2, r3);
+ __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
+ __ cmp(r4, r3);
__ b(ne, &miss);
} else {
__ cmp(r1, Operand(Handle<JSFunction>(function)));
@@ -1144,7 +1144,7 @@
__ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
// Jump to the cached code (tail call).
- __ IncrementCounter(&Counters::call_global_inline, 1, r2, r3);
+ __ IncrementCounter(&Counters::call_global_inline, 1, r1, r3);
ASSERT(function->is_compiled());
Handle<Code> code(function->code());
ParameterCount expected(function->shared()->formal_parameter_count());
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev