In the IA32 code genrator, handle call ICs and constructor calls the
authorkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 26 Mar 2009 13:00:03 +0000 (13:00 +0000)
committerkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 26 Mar 2009 13:00:03 +0000 (13:00 +0000)
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

src/codegen-ia32.cc
src/virtual-frame-arm.cc
src/virtual-frame-arm.h
src/virtual-frame-ia32.cc
src/virtual-frame-ia32.h
src/virtual-frame.cc

index 05234c5..cb82b06 100644 (file)
@@ -3877,16 +3877,12 @@ void CodeGenerator::VisitCall(Call* node) {
       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);
 
@@ -3929,15 +3925,10 @@ void CodeGenerator::VisitCall(Call* node) {
       }
 
       // 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);
 
@@ -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<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);
 }
@@ -4439,10 +4410,9 @@ void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
   }
 
   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 {
index 1564c35..eed1463 100644 (file)
@@ -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> code,
 
 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;
index ccaf851..3891dfc 100644 (file)
@@ -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).
index 685f688..0fadfb9 100644 (file)
@@ -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> 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);
 }
 
 
index d75fbf5..8727c54 100644 (file)
@@ -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<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.
@@ -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).
index 716daeb..67380f1 100644 (file)
@@ -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> 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);
 }