Revision: 3484
Author: [email protected]
Date: Thu Dec 17 02:23:20 2009
Log: Streamline the calling convention of the call ICs by passing the
property name in a register rather than on the stack below the
receiver and arguments.

Implemented only for IA32, passing the name in the ecx register to
match the calling convention of the load ICs.

Review URL: http://codereview.chromium.org/502028
http://code.google.com/p/v8/source/detail?r=3484

Modified:
  /branches/bleeding_edge/src/arm/fast-codegen-arm.cc
  /branches/bleeding_edge/src/arm/ic-arm.cc
  /branches/bleeding_edge/src/fast-codegen.h
  /branches/bleeding_edge/src/ia32/builtins-ia32.cc
  /branches/bleeding_edge/src/ia32/codegen-ia32.cc
  /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc
  /branches/bleeding_edge/src/ia32/ic-ia32.cc
  /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
  /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc
  /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h
  /branches/bleeding_edge/src/ic.cc
  /branches/bleeding_edge/src/ic.h
  /branches/bleeding_edge/src/x64/fast-codegen-x64.cc
  /branches/bleeding_edge/src/x64/ic-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Wed Dec 16 01:51:07  
2009
+++ /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Thu Dec 17 02:23:20  
2009
@@ -1080,7 +1080,9 @@
    DropAndMove(expr->context(), r0);
  }

-void FastCodeGenerator::EmitCallWithIC(Call* expr, RelocInfo::Mode  
reloc_info) {
+void FastCodeGenerator::EmitCallWithIC(Call* expr,
+                                       Handle<Object> ignored,
+                                       RelocInfo::Mode mode) {
    // Code common for calls using the IC.
    ZoneList<Expression*>* args = expr->arguments();
    int arg_count = args->length();
@@ -1093,7 +1095,7 @@
    // Call the IC initialization code.
    Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
                                                           NOT_IN_LOOP);
-  __ Call(ic, reloc_info);
+  __ Call(ic, mode);
    // Restore context register.
    __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
    // Discard the function left on TOS.
@@ -1133,7 +1135,7 @@
      // Push global object as receiver for the call IC lookup.
      __ ldr(r0, CodeGenerator::GlobalObject());
      __ stm(db_w, sp, r1.bit() | r0.bit());
-    EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT);
+    EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
    } else if (var != NULL && var->slot() != NULL &&
               var->slot()->type() == Slot::LOOKUP) {
      // Call to a lookup slot.
@@ -1147,7 +1149,7 @@
        __ mov(r0, Operand(key->handle()));
        __ push(r0);
        Visit(prop->obj());
-      EmitCallWithIC(expr, RelocInfo::CODE_TARGET);
+      EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
      } else {
        // Call to a keyed property, use keyed load IC followed by function
        // call.
=======================================
--- /branches/bleeding_edge/src/arm/ic-arm.cc   Tue Dec  1 01:54:47 2009
+++ /branches/bleeding_edge/src/arm/ic-arm.cc   Thu Dec 17 02:23:20 2009
@@ -276,7 +276,7 @@

    // Cache miss: Jump to runtime.
    __ bind(&miss);
-  Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
+  GenerateMiss(masm, argc);
  }


@@ -371,13 +371,11 @@

    // Cache miss: Jump to runtime.
    __ bind(&miss);
-  Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
+  GenerateMiss(masm, argc);
  }


-void CallIC::Generate(MacroAssembler* masm,
-                      int argc,
-                      const ExternalReference& f) {
+void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
    // ----------- S t a t e -------------
    //  -- lr: return address
    // -----------------------------------
@@ -394,7 +392,7 @@

    // Call the entry.
    __ mov(r0, Operand(2));
-  __ mov(r1, Operand(f));
+  __ mov(r1, Operand(ExternalReference(IC_Utility(kCallIC_Miss))));

    CEntryStub stub(1);
    __ CallStub(&stub);
=======================================
--- /branches/bleeding_edge/src/fast-codegen.h  Wed Dec 16 01:51:07 2009
+++ /branches/bleeding_edge/src/fast-codegen.h  Thu Dec 17 02:23:20 2009
@@ -240,7 +240,7 @@

    // Platform-specific code sequences for calls
    void EmitCallWithStub(Call* expr);
-  void EmitCallWithIC(Call* expr, RelocInfo::Mode reloc_info);
+  void EmitCallWithIC(Call* expr, Handle<Object> name, RelocInfo::Mode  
mode);

    // Platform-specific code for loading variables.
    void EmitVariableLoad(Variable* expr, Expression::Context context);
=======================================
--- /branches/bleeding_edge/src/ia32/builtins-ia32.cc   Thu Nov 12 05:55:21  
2009
+++ /branches/bleeding_edge/src/ia32/builtins-ia32.cc   Thu Dec 17 02:23:20  
2009
@@ -472,35 +472,38 @@
      __ bind(&done);
    }

-  // 4. Shift stuff one slot down the stack.
+  // 4. Check that the function really is a function.
+  { Label done;
+    __ test(edi, Operand(edi));
+    __ j(not_zero, &done, taken);
+    __ xor_(ebx, Operand(ebx));
+    // CALL_NON_FUNCTION will expect to find the non-function callee on the
+    // expression stack of the caller.  Transfer it from receiver to the
+    // caller's expression stack (and make the first argument the receiver
+    // for CALL_NON_FUNCTION) by decrementing the argument count.
+    __ dec(eax);
+    __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
+    __ jmp(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
+           RelocInfo::CODE_TARGET);
+    __ bind(&done);
+  }
+
+  // 5. Shift arguments and return address one slot down on the stack
+  //    (overwriting the receiver).
    { Label loop;
-    __ lea(ecx, Operand(eax, +1));  // +1 ~ copy receiver too
+    __ mov(ecx, eax);
      __ bind(&loop);
      __ mov(ebx, Operand(esp, ecx, times_4, 0));
      __ mov(Operand(esp, ecx, times_4, kPointerSize), ebx);
      __ dec(ecx);
-    __ j(not_zero, &loop);
+    __ j(not_sign, &loop);
+    __ pop(ebx);  // Discard copy of return address.
+    __ dec(eax);  // One fewer argument (first argument is new receiver).
    }

-  // 5. Remove TOS (copy of last arguments), but keep return address.
-  __ pop(ebx);
-  __ pop(ecx);
-  __ push(ebx);
-  __ dec(eax);
-
-  // 6. Check that function really was a function and get the code to
-  //    call from the function and check that the number of expected
-  //    arguments matches what we're providing.
-  { Label invoke;
-    __ test(edi, Operand(edi));
-    __ j(not_zero, &invoke, taken);
-    __ xor_(ebx, Operand(ebx));
-    __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
-    __ jmp(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
-           RelocInfo::CODE_TARGET);
-
-    __ bind(&invoke);
-    __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+  // 6. Get the code to call from the function and check that the number of
+  //    expected arguments matches what we're providing.
+  { __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
      __ mov(ebx,
             FieldOperand(edx,  
SharedFunctionInfo::kFormalParameterCountOffset));
      __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset));
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc    Thu Dec 17 00:53:19  
2009
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc    Thu Dec 17 02:23:20  
2009
@@ -4560,9 +4560,6 @@
      // JavaScript example: 'foo(1, 2, 3)'  // foo is global
      // ----------------------------------

-    // Push the name of the function and the receiver onto the stack.
-    frame_->Push(var->name());
-
      // 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.
@@ -4573,6 +4570,9 @@
      for (int i = 0; i < arg_count; i++) {
        Load(args->at(i));
      }
+
+    // Push the name of the function onto the frame.
+    frame_->Push(var->name());

      // Call the IC initialization code.
      CodeForSourcePosition(node->position());
@@ -4580,8 +4580,7 @@
                                         arg_count,
                                         loop_nesting());
      frame_->RestoreContextRegister();
-    // Replace the function on the stack with the result.
-    frame_->SetElementAt(0, &result);
+    frame_->Push(&result);

    } else if (var != NULL && var->slot() != NULL &&
               var->slot()->type() == Slot::LOOKUP) {
@@ -4634,8 +4633,7 @@
                        node->position());

        } else {
-        // Push the name of the function and the receiver onto the stack.
-        frame_->Push(name);
+        // Push the receiver onto the frame.
          Load(property->obj());

          // Load the arguments.
@@ -4643,6 +4641,9 @@
          for (int i = 0; i < arg_count; i++) {
            Load(args->at(i));
          }
+
+        // Push the name of the function onto the frame.
+        frame_->Push(name);

          // Call the IC initialization code.
          CodeForSourcePosition(node->position());
@@ -4650,8 +4651,7 @@
              frame_->CallCallIC(RelocInfo::CODE_TARGET, arg_count,
                                 loop_nesting());
          frame_->RestoreContextRegister();
-        // Replace the function on the stack with the result.
-        frame_->SetElementAt(0, &result);
+        frame_->Push(&result);
        }

      } else {
@@ -5309,8 +5309,6 @@
    Runtime::Function* function = node->function();

    if (function == NULL) {
-    // Prepare stack for calling JS runtime function.
-    frame_->Push(node->name());
      // Push the builtins object found in the current global object.
      Result temp = allocator()->Allocate();
      ASSERT(temp.is_valid());
@@ -5327,11 +5325,12 @@

    if (function == NULL) {
      // Call the JS runtime function.
+    frame_->Push(node->name());
      Result answer = frame_->CallCallIC(RelocInfo::CODE_TARGET,
                                         arg_count,
                                         loop_nesting_);
      frame_->RestoreContextRegister();
-    frame_->SetElementAt(0, &answer);
+    frame_->Push(&answer);
    } else {
      // Call the C runtime function.
      Result answer = frame_->CallRuntime(function, arg_count);
=======================================
--- /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Wed Dec 16  
01:51:07 2009
+++ /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Thu Dec 17  
02:23:20 2009
@@ -1066,7 +1066,9 @@
  }


-void FastCodeGenerator::EmitCallWithIC(Call* expr, RelocInfo::Mode  
reloc_info) {
+void FastCodeGenerator::EmitCallWithIC(Call* expr,
+                                       Handle<Object> name,
+                                       RelocInfo::Mode mode) {
    // Code common for calls using the IC.
    ZoneList<Expression*>* args = expr->arguments();
    int arg_count = args->length();
@@ -1074,16 +1076,15 @@
      Visit(args->at(i));
      ASSERT_EQ(Expression::kValue, args->at(i)->context());
    }
-  // Record source position for debugger.
+  __ Set(ecx, Immediate(name));
+  // Record source position of the IC call.
    SetSourcePosition(expr->position());
-  // Call the IC initialization code.
-  Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
-                                                         NOT_IN_LOOP);
-  __ call(ic, reloc_info);
+  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.
    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-  // Discard the function left on TOS.
-  DropAndMove(expr->context(), eax);
+  Move(expr->context(), eax);
  }


@@ -1100,7 +1101,6 @@
    __ CallStub(&stub);
    // Restore context register.
    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-  // Discard the function left on TOS.
    DropAndMove(expr->context(), eax);
  }

@@ -1114,11 +1114,9 @@
      // Call to the identifier 'eval'.
      UNREACHABLE();
    } else if (var != NULL && !var->is_this() && var->is_global()) {
-    // Call to a global variable.
-    __ push(Immediate(var->name()));
-    // Push global object as receiver for the call IC lookup.
+    // Push global object as receiver for the call IC.
      __ push(CodeGenerator::GlobalObject());
-    EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT);
+    EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
    } else if (var != NULL && var->slot() != NULL &&
               var->slot()->type() == Slot::LOOKUP) {
      // Call to a lookup slot.
@@ -1129,9 +1127,8 @@
      Literal* key = prop->key()->AsLiteral();
      if (key != NULL && key->handle()->IsSymbol()) {
        // Call to a named property, use call IC.
-      __ push(Immediate(key->handle()));
        Visit(prop->obj());
-      EmitCallWithIC(expr, RelocInfo::CODE_TARGET);
+      EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
      } else {
        // Call to a keyed property, use keyed load IC followed by function
        // call.
@@ -1223,7 +1220,6 @@

    if (expr->is_jsruntime()) {
      // Prepare for calling JS runtime function.
-    __ push(Immediate(expr->name()));
      __ mov(eax, CodeGenerator::GlobalObject());
      __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
    }
@@ -1236,19 +1232,18 @@
    }

    if (expr->is_jsruntime()) {
-    // Call the JS runtime function.
-    Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
-                                                           NOT_IN_LOOP);
+    // Call the JS runtime function via a call IC.
+    __ Set(ecx, Immediate(expr->name()));
+    InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
+    Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,  
in_loop);
      __ call(ic, RelocInfo::CODE_TARGET);
        // Restore context register.
      __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-    // Discard the function left on TOS.
-    DropAndMove(expr->context(), eax);
    } else {
      // Call the C runtime function.
      __ CallRuntime(expr->function(), arg_count);
-    Move(expr->context(), eax);
-  }
+  }
+  Move(expr->context(), eax);
  }


=======================================
--- /branches/bleeding_edge/src/ia32/ic-ia32.cc Thu Dec 10 07:10:50 2009
+++ /branches/bleeding_edge/src/ia32/ic-ia32.cc Thu Dec 17 02:23:20 2009
@@ -888,13 +888,16 @@

  void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
    // ----------- S t a t e -------------
+  //  -- ecx                 : name
+  //  -- esp[0]              : return address
+  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- esp[(argc + 1) * 4] : receiver
    // -----------------------------------
    Label number, non_number, non_string, boolean, probe, miss;

    // Get the receiver of the function from the stack; 1 ~ return address.
    __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
-  // Get the name of the function from the stack; 2 ~ return address,  
receiver
-  __ mov(ecx, Operand(esp, (argc + 2) * kPointerSize));

    // Probe the stub cache.
    Code::Flags flags =
@@ -940,7 +943,7 @@

    // Cache miss: Jump to runtime.
    __ bind(&miss);
-  Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
+  GenerateMiss(masm, argc);
  }


@@ -948,27 +951,34 @@
                                   int argc,
                                   bool is_global_object,
                                   Label* miss) {
-  // Search dictionary - put result in register edx.
-  GenerateDictionaryLoad(masm, miss, eax, edx, ebx, ecx, CHECK_DICTIONARY);
-
-  // Move the result to register edi and check that it isn't a smi.
-  __ mov(edi, Operand(edx));
-  __ test(edx, Immediate(kSmiTagMask));
+  // ----------- S t a t e -------------
+  //  -- ecx                 : name
+  //  -- edx                 : receiver
+  //  -- esp[0]              : return address
+  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- esp[(argc + 1) * 4] : receiver
+  // -----------------------------------
+
+  // Search dictionary - put result in register edi.
+  __ mov(edi, edx);
+  GenerateDictionaryLoad(masm, miss, eax, edi, ebx, ecx, CHECK_DICTIONARY);
+
+  // Check that the result is not a smi.
+  __ test(edi, Immediate(kSmiTagMask));
    __ j(zero, miss, not_taken);

-  // Check that the value is a JavaScript function.
-  __ CmpObjectType(edx, JS_FUNCTION_TYPE, edx);
+  // Check that the value is a JavaScript function, fetching its map into  
eax.
+  __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax);
    __ j(not_equal, miss, not_taken);

-  // Check that the function has been loaded.
-  __ mov(edx, FieldOperand(edi, JSFunction::kMapOffset));
-  __ mov(edx, FieldOperand(edx, Map::kBitField2Offset));
-  __ test(edx, Immediate(1 << Map::kNeedsLoading));
+  // Check that the function has been loaded.  eax holds function's map.
+  __ mov(eax, FieldOperand(eax, Map::kBitField2Offset));
+  __ test(eax, Immediate(1 << Map::kNeedsLoading));
    __ j(not_zero, miss, not_taken);

-  // Patch the receiver with the global proxy if necessary.
+  // Patch the receiver on stack with the global proxy if necessary.
    if (is_global_object) {
-    __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
      __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
      __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
    }
@@ -981,14 +991,17 @@

  void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
    // ----------- S t a t e -------------
+  //  -- ecx                 : name
+  //  -- esp[0]              : return address
+  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- esp[(argc + 1) * 4] : receiver
    // -----------------------------------

    Label miss, global_object, non_global_object;

    // Get the receiver of the function from the stack; 1 ~ return address.
    __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
-  // Get the name of the function from the stack; 2 ~ return address,  
receiver.
-  __ mov(ecx, Operand(esp, (argc + 2) * kPointerSize));

    // Check that the receiver isn't a smi.
    __ test(edx, Immediate(kSmiTagMask));
@@ -1037,33 +1050,33 @@

    // Cache miss: Jump to runtime.
    __ bind(&miss);
-  Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
+  GenerateMiss(masm, argc);
  }


-void CallIC::Generate(MacroAssembler* masm,
-                      int argc,
-                      const ExternalReference& f) {
+void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
    // ----------- S t a t e -------------
+  //  -- ecx                 : name
+  //  -- esp[0]              : return address
+  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- esp[(argc + 1) * 4] : receiver
    // -----------------------------------

    // Get the receiver of the function from the stack; 1 ~ return address.
    __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
-  // Get the name of the function to call from the stack.
-  // 2 ~ receiver, return address.
-  __ mov(ebx, Operand(esp, (argc + 2) * kPointerSize));

    // Enter an internal frame.
    __ EnterInternalFrame();

    // Push the receiver and the name of the function.
    __ push(edx);
-  __ push(ebx);
+  __ push(ecx);

    // Call the entry.
    CEntryStub stub(1);
    __ mov(eax, Immediate(2));
-  __ mov(ebx, Immediate(f));
+  __ mov(ebx, Immediate(ExternalReference(IC_Utility(kCallIC_Miss))));
    __ CallStub(&stub);

    // Move result to edi and exit the internal frame.
@@ -1075,11 +1088,11 @@
    __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));  // receiver
    __ test(edx, Immediate(kSmiTagMask));
    __ j(zero, &invoke, not_taken);
-  __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
-  __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
-  __ cmp(ecx, JS_GLOBAL_OBJECT_TYPE);
+  __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
+  __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
+  __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE);
    __ j(equal, &global);
-  __ cmp(ecx, JS_BUILTINS_OBJECT_TYPE);
+  __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE);
    __ j(not_equal, &invoke);

    // Patch the receiver on the stack.
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Wed Dec 16 07:43:20  
2009
+++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Thu Dec 17 02:23:20  
2009
@@ -152,11 +152,10 @@
  }


-template <typename Pushable>
  static void PushInterceptorArguments(MacroAssembler* masm,
                                       Register receiver,
                                       Register holder,
-                                     Pushable name,
+                                     Register name,
                                       JSObject* holder_obj) {
    __ push(receiver);
    __ push(holder);
@@ -285,11 +284,10 @@
  }


-template <class Pushable>
  static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm,
                                                     Register receiver,
                                                     Register holder,
-                                                   Pushable name,
+                                                   Register name,
                                                     JSObject* holder_obj) {
    PushInterceptorArguments(masm, receiver, holder, name, holder_obj);

@@ -495,8 +493,8 @@

  class CallInterceptorCompiler BASE_EMBEDDED {
   public:
-  explicit CallInterceptorCompiler(const ParameterCount& arguments)
-      : arguments_(arguments), argc_(arguments.immediate()) {}
+  CallInterceptorCompiler(const ParameterCount& arguments, Register name)
+      : arguments_(arguments), argc_(arguments.immediate()), name_(name) {}

    void CompileCacheable(MacroAssembler* masm,
                          StubCompiler* stub_compiler,
@@ -527,17 +525,17 @@
      }

      __ EnterInternalFrame();
-    __ push(holder);  // save the holder
-
-    CompileCallLoadPropertyWithInterceptor(
-        masm,
-        receiver,
-        holder,
-        // Under EnterInternalFrame this refers to name.
-        Operand(ebp, (argc_ + 3) * kPointerSize),
-        holder_obj);
-
-    __ pop(receiver);  // restore holder
+    __ push(holder);  // Save the holder.
+    __ push(name_);  // Save the name.
+
+    CompileCallLoadPropertyWithInterceptor(masm,
+                                           receiver,
+                                           holder,
+                                           name_,
+                                           holder_obj);
+
+    __ pop(name_);  // Restore the name.
+    __ pop(receiver);  // Restore the holder.
      __ LeaveInternalFrame();

      __ cmp(eax, Factory::no_interceptor_result_sentinel());
@@ -577,11 +575,13 @@
                        JSObject* holder_obj,
                        Label* miss_label) {
      __ EnterInternalFrame();
+    // Save the name_ register across the call.
+    __ push(name_);

      PushInterceptorArguments(masm,
                               receiver,
                               holder,
-                             Operand(ebp, (argc_ + 3) * kPointerSize),
+                             name_,
                               holder_obj);

      ExternalReference ref = ExternalReference(
@@ -592,12 +592,15 @@
      CEntryStub stub(1);
      __ CallStub(&stub);

+    // Restore the name_ register.
+    __ pop(name_);
      __ LeaveInternalFrame();
    }

   private:
    const ParameterCount& arguments_;
    int argc_;
+  Register name_;
  };


@@ -894,6 +897,11 @@
                                             int index,
                                             String* name) {
    // ----------- S t a t e -------------
+  //  -- ecx                 : name
+  //  -- esp[0]              : return address
+  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- esp[(argc + 1) * 4] : receiver
    // -----------------------------------
    Label miss;

@@ -908,7 +916,7 @@
    // Do the right check and compute the holder register.
    Register reg =
        CheckPrototypes(JSObject::cast(object), edx, holder,
-                      ebx, ecx, name, &miss);
+                      ebx, eax, name, &miss);

    GenerateFastPropertyLoad(masm(), edi, reg, holder, index);

@@ -944,6 +952,11 @@
                                                String* name,
                                                CheckType check) {
    // ----------- S t a t e -------------
+  //  -- ecx                 : name
+  //  -- esp[0]              : return address
+  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- esp[(argc + 1) * 4] : receiver
    // -----------------------------------
    Label miss;

@@ -965,7 +978,7 @@
      case RECEIVER_MAP_CHECK:
        // Check that the maps haven't changed.
        CheckPrototypes(JSObject::cast(object), edx, holder,
-                      ebx, ecx, name, &miss);
+                      ebx, eax, name, &miss);

        // Patch the receiver on the stack with the global proxy if
        // necessary.
@@ -977,15 +990,15 @@

      case STRING_CHECK:
        // Check that the object is a two-byte string or a symbol.
-      __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
-      __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
-      __ cmp(ecx, FIRST_NONSTRING_TYPE);
+      __ mov(eax, FieldOperand(edx, HeapObject::kMapOffset));
+      __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset));
+      __ cmp(eax, FIRST_NONSTRING_TYPE);
        __ j(above_equal, &miss, not_taken);
        // Check that the maps starting from the prototype haven't changed.
        GenerateLoadGlobalFunctionPrototype(masm(),
                                            Context::STRING_FUNCTION_INDEX,
-                                          ecx);
-      CheckPrototypes(JSObject::cast(object->GetPrototype()), ecx, holder,
+                                          eax);
+      CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder,
                        ebx, edx, name, &miss);
        break;

@@ -994,14 +1007,14 @@
        // Check that the object is a smi or a heap number.
        __ test(edx, Immediate(kSmiTagMask));
        __ j(zero, &fast, taken);
-      __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx);
+      __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax);
        __ j(not_equal, &miss, not_taken);
        __ bind(&fast);
        // Check that the maps starting from the prototype haven't changed.
        GenerateLoadGlobalFunctionPrototype(masm(),
                                            Context::NUMBER_FUNCTION_INDEX,
-                                          ecx);
-      CheckPrototypes(JSObject::cast(object->GetPrototype()), ecx, holder,
+                                          eax);
+      CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder,
                        ebx, edx, name, &miss);
        break;
      }
@@ -1017,15 +1030,15 @@
        // Check that the maps starting from the prototype haven't changed.
        GenerateLoadGlobalFunctionPrototype(masm(),
                                            Context::BOOLEAN_FUNCTION_INDEX,
-                                          ecx);
-      CheckPrototypes(JSObject::cast(object->GetPrototype()), ecx, holder,
+                                          eax);
+      CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder,
                        ebx, edx, name, &miss);
        break;
      }

      case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
        CheckPrototypes(JSObject::cast(object), edx, holder,
-                      ebx, ecx, name, &miss);
+                      ebx, eax, name, &miss);
        // Make sure object->HasFastElements().
        // Get the elements array of the object.
        __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
@@ -1068,6 +1081,11 @@
                                                   JSObject* holder,
                                                   String* name) {
    // ----------- S t a t e -------------
+  //  -- ecx                 : name
+  //  -- esp[0]              : return address
+  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- esp[(argc + 1) * 4] : receiver
    // -----------------------------------
    Label miss;

@@ -1080,7 +1098,7 @@
    // Get the receiver from the stack.
    __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));

-  CallInterceptorCompiler compiler(arguments());
+  CallInterceptorCompiler compiler(arguments(), ecx);
    CompileLoadInterceptor(&compiler,
                           this,
                           masm(),
@@ -1090,7 +1108,7 @@
                           &lookup,
                           edx,
                           ebx,
-                         ecx,
+                         edi,
                           &miss);

    // Restore receiver.
@@ -1129,6 +1147,11 @@
                                              JSFunction* function,
                                              String* name) {
    // ----------- S t a t e -------------
+  //  -- ecx                 : name
+  //  -- esp[0]              : return address
+  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- esp[(argc + 1) * 4] : receiver
    // -----------------------------------
    Label miss;

@@ -1147,7 +1170,7 @@
    }

    // Check that the maps haven't changed.
-  CheckPrototypes(object, edx, holder, ebx, ecx, name, &miss);
+  CheckPrototypes(object, edx, holder, ebx, eax, name, &miss);

    // Get the value from the cell.
    __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell)));
=======================================
--- /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc      Mon Nov 16  
15:11:19 2009
+++ /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc      Thu Dec 17  
02:23:20 2009
@@ -925,14 +925,17 @@
  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).
+  // Function name, arguments, and receiver are on top of the frame.
+  // The IC expects the name in ecx and the rest on the stack and
+  // drops them all.
    InLoopFlag in_loop = loop_nesting > 0 ? IN_LOOP : NOT_IN_LOOP;
    Handle<Code> ic = cgen()->ComputeCallInitialize(arg_count, in_loop);
    // Spill args, receiver, and function.  The call will drop args and
    // receiver.
-  PrepareForCall(arg_count + 2, arg_count + 1);
+  Result name = Pop();
+  PrepareForCall(arg_count + 1, arg_count + 1);  // Arguments + receiver.
+  name.ToRegister(ecx);
+  name.Unuse();
    return RawCallCodeObject(ic, mode);
  }

=======================================
--- /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h       Wed Sep  9  
03:49:40 2009
+++ /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h       Thu Dec 17  
02:23:20 2009
@@ -341,9 +341,9 @@
    // 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.
+  // Call call IC.  Function name, arguments, and receiver are found on top
+  // of the frame and dropped by the call.  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,
=======================================
--- /branches/bleeding_edge/src/ic.cc   Mon Dec 14 01:54:13 2009
+++ /branches/bleeding_edge/src/ic.cc   Thu Dec 17 02:23:20 2009
@@ -1290,16 +1290,6 @@
    }
    return *function;
  }
-
-
-void CallIC::GenerateInitialize(MacroAssembler* masm, int argc) {
-  Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
-}
-
-
-void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
-  Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
-}


  // Used from ic_<arch>.cc.
=======================================
--- /branches/bleeding_edge/src/ic.h    Mon Dec 14 01:54:13 2009
+++ /branches/bleeding_edge/src/ic.h    Thu Dec 17 02:23:20 2009
@@ -189,16 +189,14 @@


    // Code generator routines.
-  static void GenerateInitialize(MacroAssembler* masm, int argc);
+  static void GenerateInitialize(MacroAssembler* masm, int argc) {
+    GenerateMiss(masm, argc);
+  }
    static void GenerateMiss(MacroAssembler* masm, int argc);
    static void GenerateMegamorphic(MacroAssembler* masm, int argc);
    static void GenerateNormal(MacroAssembler* masm, int argc);

   private:
-  static void Generate(MacroAssembler* masm,
-                       int argc,
-                       const ExternalReference& f);
-
    // Update the inline cache and the global stub cache based on the
    // lookup result.
    void UpdateCaches(LookupResult* lookup,
=======================================
--- /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Wed Dec 16 01:51:07  
2009
+++ /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Thu Dec 17 02:23:20  
2009
@@ -1076,7 +1076,9 @@
  }


-void FastCodeGenerator::EmitCallWithIC(Call* expr, RelocInfo::Mode  
reloc_info) {
+void FastCodeGenerator::EmitCallWithIC(Call* expr,
+                                       Handle<Object> ignored,
+                                       RelocInfo::Mode mode) {
    // Code common for calls using the IC.
    ZoneList<Expression*>* args = expr->arguments();
    int arg_count = args->length();
@@ -1089,7 +1091,7 @@
    // Call the IC initialization code.
    Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
                                                           NOT_IN_LOOP);
-  __ call(ic, reloc_info);
+  __ call(ic, mode);
    // Restore context register.
    __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
    // Discard the function left on TOS.
@@ -1128,7 +1130,7 @@
      __ Push(var->name());
      // Push global object as receiver for the call IC lookup.
      __ push(CodeGenerator::GlobalObject());
-    EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT);
+    EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
    } else if (var != NULL && var->slot() != NULL &&
               var->slot()->type() == Slot::LOOKUP) {
      // Call to a lookup slot.
@@ -1141,7 +1143,7 @@
        // Call to a named property, use call IC.
        __ Push(key->handle());
        Visit(prop->obj());
-      EmitCallWithIC(expr, RelocInfo::CODE_TARGET);
+      EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
      } else {
        // Call to a keyed property, use keyed load IC followed by function
        // call.
=======================================
--- /branches/bleeding_edge/src/x64/ic-x64.cc   Thu Dec 10 07:10:50 2009
+++ /branches/bleeding_edge/src/x64/ic-x64.cc   Thu Dec 17 02:23:20 2009
@@ -916,9 +916,7 @@
  }


-void CallIC::Generate(MacroAssembler* masm,
-                      int argc,
-                      ExternalReference const& f) {
+void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
    // Get the receiver of the function from the stack; 1 ~ return address.
    __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
    // Get the name of the function to call from the stack.
@@ -935,7 +933,7 @@
    // Call the entry.
    CEntryStub stub(1);
    __ movq(rax, Immediate(2));
-  __ movq(rbx, f);
+  __ movq(rbx, ExternalReference(IC_Utility(kCallIC_Miss)));
    __ CallStub(&stub);

    // Move result to rdi and exit the internal frame.
@@ -1026,7 +1024,7 @@

    // Cache miss: Jump to runtime.
    __ bind(&miss);
-  Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
+  GenerateMiss(masm, argc);
  }


@@ -1128,7 +1126,7 @@

    // Cache miss: Jump to runtime.
    __ bind(&miss);
-  Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
+  GenerateMiss(masm, argc);
  }


-- 
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to