From: kmillikin@chromium.org Date: Thu, 26 Mar 2009 13:00:03 +0000 (+0000) Subject: In the IA32 code genrator, handle call ICs and constructor calls the X-Git-Tag: upstream/4.7.83~24397 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4dceb3c87f55e062d5f7838875c5d741f5e2d11d;p=platform%2Fupstream%2Fv8.git In the IA32 code genrator, handle call ICs and constructor calls the same as load and store ICs. Eliminate the general function used to call any IC. Review URL: http://codereview.chromium.org/42638 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1619 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/codegen-ia32.cc b/src/codegen-ia32.cc index 05234c5..cb82b06 100644 --- a/src/codegen-ia32.cc +++ b/src/codegen-ia32.cc @@ -3877,16 +3877,12 @@ void CodeGenerator::VisitCall(Call* node) { Load(args->at(i)); } - // Setup the receiver register and call the IC initialization code. - Handle 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); @@ -3929,15 +3925,10 @@ void CodeGenerator::VisitCall(Call* node) { } // Call the IC initialization code. - Handle 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); @@ -4003,30 +3994,10 @@ void CodeGenerator::VisitCallNew(CallNew* node) { 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 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); } @@ -4439,10 +4410,9 @@ void CodeGenerator::VisitCallRuntime(CallRuntime* node) { } if (function == NULL) { - // Call the JS runtime function. - Handle 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 { diff --git a/src/virtual-frame-arm.cc b/src/virtual-frame-arm.cc index 1564c35..eed1463 100644 --- a/src/virtual-frame-arm.cc +++ b/src/virtual-frame-arm.cc @@ -232,7 +232,7 @@ void VirtualFrame::PushTryHandler(HandlerType type) { } -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); @@ -241,22 +241,20 @@ Result VirtualFrame::RawCallStub(CodeStub* stub, int frame_arg_count) { } -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; @@ -266,9 +264,9 @@ Result VirtualFrame::CallRuntime(Runtime::FunctionId id, 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); @@ -288,6 +286,33 @@ Result VirtualFrame::RawCallCodeObject(Handle code, Result VirtualFrame::CallCodeObject(Handle 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, + RelocInfo::Mode rmode, Result* arg, int dropped_args) { int spilled_args = 0; diff --git a/src/virtual-frame-arm.h b/src/virtual-frame-arm.h index ccaf851..3891dfc 100644 --- a/src/virtual-frame-arm.h +++ b/src/virtual-frame-arm.h @@ -250,24 +250,21 @@ class VirtualFrame : public Malloced { // 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. @@ -460,7 +457,7 @@ class VirtualFrame : public Malloced { // 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). diff --git a/src/virtual-frame-ia32.cc b/src/virtual-frame-ia32.cc index 685f688..0fadfb9 100644 --- a/src/virtual-frame-ia32.cc +++ b/src/virtual-frame-ia32.cc @@ -725,7 +725,7 @@ void VirtualFrame::PushTryHandler(HandlerType type) { } -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); @@ -734,22 +734,20 @@ Result VirtualFrame::RawCallStub(CodeStub* stub, int frame_arg_count) { } -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; @@ -758,8 +756,8 @@ Result VirtualFrame::CallRuntime(Runtime::FunctionId id, 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); @@ -845,29 +843,43 @@ Result VirtualFrame::CallKeyedStoreIC() { } -Result VirtualFrame::CallCodeObject(Handle 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 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 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); } diff --git a/src/virtual-frame-ia32.h b/src/virtual-frame-ia32.h index d75fbf5..8727c54 100644 --- a/src/virtual-frame-ia32.h +++ b/src/virtual-frame-ia32.h @@ -243,35 +243,20 @@ class VirtualFrame : public Malloced { // 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 ic, - RelocInfo::Mode rmode, - int dropped_args); - Result CallCodeObject(Handle 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. @@ -289,6 +274,17 @@ class VirtualFrame : public Malloced { // 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. @@ -467,7 +463,7 @@ class VirtualFrame : public Malloced { // 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). diff --git a/src/virtual-frame.cc b/src/virtual-frame.cc index 716daeb..67380f1 100644 --- a/src/virtual-frame.cc +++ b/src/virtual-frame.cc @@ -431,58 +431,27 @@ void VirtualFrame::PushFrameSlotAt(int index) { } -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, - 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); }