Load(args->at(i));
}
- // Setup the receiver register and call the IC initialization code.
- Handle<Code> stub = (loop_nesting() > 0)
- ? ComputeCallInitializeInLoop(arg_count)
- : ComputeCallInitialize(arg_count);
+ // Call the IC initialization code.
CodeForSourcePosition(node->position());
- Result result = frame_->CallCodeObject(stub,
- RelocInfo::CODE_TARGET_CONTEXT,
- arg_count + 1);
+ Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT,
+ arg_count,
+ loop_nesting());
frame_->RestoreContextRegister();
-
// Replace the function on the stack with the result.
frame_->SetElementAt(0, &result);
}
// Call the IC initialization code.
- Handle<Code> stub = (loop_nesting() > 0)
- ? ComputeCallInitializeInLoop(arg_count)
- : ComputeCallInitialize(arg_count);
CodeForSourcePosition(node->position());
- Result result = frame_->CallCodeObject(stub,
- RelocInfo::CODE_TARGET,
- arg_count + 1);
+ Result result =
+ frame_->CallCallIC(RelocInfo::CODE_TARGET, arg_count, loop_nesting());
frame_->RestoreContextRegister();
-
// Replace the function on the stack with the result.
frame_->SetElementAt(0, &result);
Load(args->at(i));
}
- // Constructors are called with the number of arguments in register
- // eax for now. Another option would be to have separate construct
- // call trampolines per different arguments counts encountered.
- Result num_args = allocator()->Allocate(eax);
- ASSERT(num_args.is_valid());
- __ Set(num_args.reg(), Immediate(arg_count));
-
- // Load the function into temporary function slot as per calling
- // convention.
- frame_->PushElementAt(arg_count + 1);
- Result function = frame_->Pop();
- function.ToRegister(edi);
- ASSERT(function.is_valid());
-
// Call the construct call builtin that handles allocation and
// constructor invocation.
CodeForSourcePosition(node->position());
- Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
- Result result = frame_->CallCodeObject(ic,
- RelocInfo::CONSTRUCT_CALL,
- &num_args,
- &function,
- arg_count + 1);
-
+ Result result = frame_->CallConstructor(arg_count);
// Replace the function on the stack with the result.
frame_->SetElementAt(0, &result);
}
}
if (function == NULL) {
- // Call the JS runtime function.
- Handle<Code> stub = ComputeCallInitialize(arg_count);
- Result answer =
- frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
+ // Call the JS runtime function. Pass 0 as the loop nesting depth
+ // because we do not handle runtime calls specially in loops.
+ Result answer = frame_->CallCallIC(RelocInfo::CODE_TARGET, arg_count, 0);
frame_->RestoreContextRegister();
frame_->SetElementAt(0, &answer);
} else {
}
-Result VirtualFrame::RawCallStub(CodeStub* stub, int frame_arg_count) {
+Result VirtualFrame::RawCallStub(CodeStub* stub) {
ASSERT(cgen_->HasValidEntryRegisters());
__ CallStub(stub);
Result result = cgen_->allocator()->Allocate(r0);
}
-Result VirtualFrame::CallRuntime(Runtime::Function* f,
- int frame_arg_count) {
- PrepareForCall(frame_arg_count, frame_arg_count);
+Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) {
+ PrepareForCall(arg_count, arg_count);
ASSERT(cgen_->HasValidEntryRegisters());
- __ CallRuntime(f, frame_arg_count);
+ __ CallRuntime(f, arg_count);
Result result = cgen_->allocator()->Allocate(r0);
ASSERT(result.is_valid());
return result;
}
-Result VirtualFrame::CallRuntime(Runtime::FunctionId id,
- int frame_arg_count) {
- PrepareForCall(frame_arg_count, frame_arg_count);
+Result VirtualFrame::CallRuntime(Runtime::FunctionId id, int arg_count) {
+ PrepareForCall(arg_count, arg_count);
ASSERT(cgen_->HasValidEntryRegisters());
- __ CallRuntime(id, frame_arg_count);
+ __ CallRuntime(id, arg_count);
Result result = cgen_->allocator()->Allocate(r0);
ASSERT(result.is_valid());
return result;
Result VirtualFrame::InvokeBuiltin(Builtins::JavaScript id,
InvokeJSFlags flags,
Result* arg_count_register,
- int frame_arg_count) {
+ int arg_count) {
ASSERT(arg_count_register->reg().is(r0));
- PrepareForCall(frame_arg_count, frame_arg_count);
+ PrepareForCall(arg_count, arg_count);
arg_count_register->Unuse();
__ InvokeBuiltin(id, flags);
Result result = cgen_->allocator()->Allocate(r0);
Result VirtualFrame::CallCodeObject(Handle<Code> code,
RelocInfo::Mode rmode,
+ int dropped_args) {
+ int spilled_args = 0;
+ switch (code->kind()) {
+ case Code::CALL_IC:
+ spilled_args = dropped_args + 1;
+ break;
+ case Code::FUNCTION:
+ spilled_args = dropped_args + 1;
+ break;
+ case Code::KEYED_LOAD_IC:
+ ASSERT(dropped_args == 0);
+ spilled_args = 2;
+ break;
+ default:
+ // The other types of code objects are called with values
+ // in specific registers, and are handled in functions with
+ // a different signature.
+ UNREACHABLE();
+ break;
+ }
+ PrepareForCall(spilled_args, dropped_args);
+ return RawCallCodeObject(code, rmode);
+}
+
+
+Result VirtualFrame::CallCodeObject(Handle<Code> code,
+ RelocInfo::Mode rmode,
Result* arg,
int dropped_args) {
int spilled_args = 0;
// Call a code stub, given the number of arguments it expects on (and
// removes from) the top of the physical frame.
- Result CallStub(CodeStub* stub, int frame_arg_count);
- Result CallStub(CodeStub* stub, Result* arg, int frame_arg_count);
- Result CallStub(CodeStub* stub,
- Result* arg0,
- Result* arg1,
- int frame_arg_count);
+ Result CallStub(CodeStub* stub, int arg_count);
+ Result CallStub(CodeStub* stub, Result* arg, int arg_count);
+ Result CallStub(CodeStub* stub, Result* arg0, Result* arg1, int arg_count);
// Call the runtime, given the number of arguments expected on (and
// removed from) the top of the physical frame.
- Result CallRuntime(Runtime::Function* f, int frame_arg_count);
- Result CallRuntime(Runtime::FunctionId id, int frame_arg_count);
+ Result CallRuntime(Runtime::Function* f, int arg_count);
+ Result CallRuntime(Runtime::FunctionId id, int arg_count);
// Invoke a builtin, given the number of arguments it expects on (and
// removes from) the top of the physical frame.
Result InvokeBuiltin(Builtins::JavaScript id,
InvokeJSFlags flag,
Result* arg_count_register,
- int frame_arg_count);
+ int arg_count);
// Call into a JS code object, given the number of arguments it
// removes from the top of the physical frame.
// Call a code stub that has already been prepared for calling (via
// PrepareForCall).
- Result RawCallStub(CodeStub* stub, int frame_arg_count);
+ Result RawCallStub(CodeStub* stub);
// Calls a code object which has already been prepared for calling
// (via PrepareForCall).
}
-Result VirtualFrame::RawCallStub(CodeStub* stub, int frame_arg_count) {
+Result VirtualFrame::RawCallStub(CodeStub* stub) {
ASSERT(cgen_->HasValidEntryRegisters());
__ CallStub(stub);
Result result = cgen_->allocator()->Allocate(eax);
}
-Result VirtualFrame::CallRuntime(Runtime::Function* f,
- int frame_arg_count) {
- PrepareForCall(frame_arg_count, frame_arg_count);
+Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) {
+ PrepareForCall(arg_count, arg_count);
ASSERT(cgen_->HasValidEntryRegisters());
- __ CallRuntime(f, frame_arg_count);
+ __ CallRuntime(f, arg_count);
Result result = cgen_->allocator()->Allocate(eax);
ASSERT(result.is_valid());
return result;
}
-Result VirtualFrame::CallRuntime(Runtime::FunctionId id,
- int frame_arg_count) {
- PrepareForCall(frame_arg_count, frame_arg_count);
+Result VirtualFrame::CallRuntime(Runtime::FunctionId id, int arg_count) {
+ PrepareForCall(arg_count, arg_count);
ASSERT(cgen_->HasValidEntryRegisters());
- __ CallRuntime(id, frame_arg_count);
+ __ CallRuntime(id, arg_count);
Result result = cgen_->allocator()->Allocate(eax);
ASSERT(result.is_valid());
return result;
Result VirtualFrame::InvokeBuiltin(Builtins::JavaScript id,
InvokeFlag flag,
- int frame_arg_count) {
- PrepareForCall(frame_arg_count, frame_arg_count);
+ int arg_count) {
+ PrepareForCall(arg_count, arg_count);
ASSERT(cgen_->HasValidEntryRegisters());
__ InvokeBuiltin(id, flag);
Result result = cgen_->allocator()->Allocate(eax);
}
-Result VirtualFrame::CallCodeObject(Handle<Code> code,
- RelocInfo::Mode rmode,
- Result* arg0,
- Result* arg1,
- int dropped_args) {
- int spilled_args = 1;
- switch (code->kind()) {
- case Code::BUILTIN:
- ASSERT(*code == Builtins::builtin(Builtins::JSConstructCall));
- ASSERT(arg0->reg().is(eax));
- ASSERT(arg1->reg().is(edi));
- spilled_args = dropped_args + 1;
- break;
- default:
- // No other types of code objects are called with values
- // in exactly two registers.
- UNREACHABLE();
- break;
- }
- PrepareForCall(spilled_args, dropped_args);
- arg0->Unuse();
- arg1->Unuse();
- return RawCallCodeObject(code, rmode);
+Result VirtualFrame::CallCallIC(RelocInfo::Mode mode,
+ int arg_count,
+ int loop_nesting) {
+ // Arguments, receiver, and function name are on top of the frame.
+ // The IC expects them on the stack. It does not drop the function
+ // name slot (but it does drop the rest).
+ Handle<Code> ic = (loop_nesting > 0)
+ ? cgen_->ComputeCallInitializeInLoop(arg_count)
+ : cgen_->ComputeCallInitialize(arg_count);
+ // Spill args, receiver, and function. The call will drop args and
+ // receiver.
+ PrepareForCall(arg_count + 2, arg_count + 1);
+ return RawCallCodeObject(ic, mode);
+}
+
+
+Result VirtualFrame::CallConstructor(int arg_count) {
+ // Arguments, receiver, and function are on top of the frame. The
+ // IC expects arg count in eax, function in edi, and the arguments
+ // and receiver on the stack.
+ Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
+ // Duplicate the function before preparing the frame.
+ PushElementAt(arg_count + 1);
+ Result function = Pop();
+ PrepareForCall(arg_count + 1, arg_count + 1); // Spill args and receiver.
+ function.ToRegister(edi);
+
+ // Constructors are called with the number of arguments in register
+ // eax for now. Another option would be to have separate construct
+ // call trampolines per different arguments counts encountered.
+ Result num_args = cgen_->allocator()->Allocate(eax);
+ ASSERT(num_args.is_valid());
+ __ Set(num_args.reg(), Immediate(arg_count));
+
+ function.Unuse();
+ num_args.Unuse();
+ return RawCallCodeObject(ic, RelocInfo::CONSTRUCT_CALL);
}
// Call a code stub, given the number of arguments it expects on (and
// removes from) the top of the physical frame.
- Result CallStub(CodeStub* stub, int frame_arg_count);
- Result CallStub(CodeStub* stub, Result* arg, int frame_arg_count);
- Result CallStub(CodeStub* stub,
- Result* arg0,
- Result* arg1,
- int frame_arg_count);
+ Result CallStub(CodeStub* stub, int arg_count);
+ Result CallStub(CodeStub* stub, Result* arg, int arg_count);
+ Result CallStub(CodeStub* stub, Result* arg0, Result* arg1, int arg_count);
// Call the runtime, given the number of arguments expected on (and
// removed from) the top of the physical frame.
- Result CallRuntime(Runtime::Function* f, int frame_arg_count);
- Result CallRuntime(Runtime::FunctionId id, int frame_arg_count);
+ Result CallRuntime(Runtime::Function* f, int arg_count);
+ Result CallRuntime(Runtime::FunctionId id, int arg_count);
// Invoke a builtin, given the number of arguments it expects on (and
// removes from) the top of the physical frame.
Result InvokeBuiltin(Builtins::JavaScript id,
InvokeFlag flag,
- int frame_arg_count);
-
- // Call into a call IC or a JS code object given the number of
- // arguments it drops from the top of the stack. Arguments passed
- // in registers are given as results and invalidated by the call.
- Result CallCodeObject(Handle<Code> ic,
- RelocInfo::Mode rmode,
- int dropped_args);
- Result CallCodeObject(Handle<Code> ic,
- RelocInfo::Mode rmode,
- Result* arg0,
- Result* arg1,
- int dropped_args);
+ int arg_count);
// Call load IC. Name and receiver are found on top of the frame.
// Receiver is not dropped.
// of the frame. Key and receiver are not dropped.
Result CallKeyedStoreIC();
+ // Call call IC. Arguments, reciever, and function name are found
+ // on top of the frame. Function name slot is not dropped. The
+ // argument count does not include the receiver.
+ Result CallCallIC(RelocInfo::Mode mode, int arg_count, int loop_nesting);
+
+ // Allocate and call JS function as constructor. Arguments,
+ // receiver (global object), and function are found on top of the
+ // frame. Function is not dropped. The argument count does not
+ // include the receiver.
+ Result CallConstructor(int arg_count);
+
// Drop a number of elements from the top of the expression stack. May
// emit code to affect the physical frame. Does not clobber any registers
// excepting possibly the stack pointer.
// Call a code stub that has already been prepared for calling (via
// PrepareForCall).
- Result RawCallStub(CodeStub* stub, int frame_arg_count);
+ Result RawCallStub(CodeStub* stub);
// Calls a code object which has already been prepared for calling
// (via PrepareForCall).
}
-Result VirtualFrame::CallStub(CodeStub* stub, int frame_arg_count) {
- PrepareForCall(frame_arg_count, frame_arg_count);
- return RawCallStub(stub, frame_arg_count);
+Result VirtualFrame::CallStub(CodeStub* stub, int arg_count) {
+ PrepareForCall(arg_count, arg_count);
+ return RawCallStub(stub);
}
-Result VirtualFrame::CallStub(CodeStub* stub,
- Result* arg,
- int frame_arg_count) {
- PrepareForCall(frame_arg_count, frame_arg_count);
+Result VirtualFrame::CallStub(CodeStub* stub, Result* arg, int arg_count) {
+ PrepareForCall(arg_count, arg_count);
arg->Unuse();
- return RawCallStub(stub, frame_arg_count);
+ return RawCallStub(stub);
}
Result VirtualFrame::CallStub(CodeStub* stub,
Result* arg0,
Result* arg1,
- int frame_arg_count) {
- PrepareForCall(frame_arg_count, frame_arg_count);
+ int arg_count) {
+ PrepareForCall(arg_count, arg_count);
arg0->Unuse();
arg1->Unuse();
- return RawCallStub(stub, frame_arg_count);
-}
-
-
-Result VirtualFrame::CallCodeObject(Handle<Code> code,
- RelocInfo::Mode rmode,
- int dropped_args) {
- int spilled_args = 0;
- switch (code->kind()) {
- case Code::CALL_IC:
- spilled_args = dropped_args + 1;
- break;
- case Code::FUNCTION:
- spilled_args = dropped_args + 1;
- break;
-#ifdef ARM
- case Code::KEYED_LOAD_IC:
- ASSERT(dropped_args == 0);
- spilled_args = 2;
- break;
-#endif
- default:
- // The other types of code objects are called with values
- // in specific registers, and are handled in functions with
- // a different signature.
- UNREACHABLE();
- break;
- }
- PrepareForCall(spilled_args, dropped_args);
- return RawCallCodeObject(code, rmode);
+ return RawCallStub(stub);
}