Revision: 6707
Author: [email protected]
Date: Wed Feb  9 08:43:23 2011
Log: Make optimized Function.prototype.apply safe for non-JSObject first arguments.

If we have a property access of the form this.x, where the access site sees
the global object, we can specialize the IC stub so that it performs a map
check without first performing a heap object check.

Ensure that we do not get in JS code with a non-JSObject this value by
deoptimizing at Function.prototype.apply if the first argument is not a
JSObject.

BUG=v8:1128

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

Modified:
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.h
 /branches/bleeding_edge/test/mjsunit/compiler/regress-arguments.js

=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Feb 9 04:46:22 2011 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Feb 9 08:43:23 2011
@@ -2116,6 +2116,9 @@

 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
   Register receiver = ToRegister(instr->receiver());
+  Register length = ToRegister(instr->length());
+  Register elements = ToRegister(instr->elements());
+  Register temp = ToRegister(instr->TempAt(0));
   ASSERT(ToRegister(instr->function()).is(edi));
   ASSERT(ToRegister(instr->result()).is(eax));

@@ -2125,14 +2128,19 @@
   __ cmp(receiver, Factory::null_value());
   __ j(equal, &global_receiver);
   __ cmp(receiver, Factory::undefined_value());
-  __ j(not_equal, &receiver_ok);
+  __ j(equal, &global_receiver);
+
+  // The receiver should be a JS object.
+  __ test(receiver, Immediate(kSmiTagMask));
+  DeoptimizeIf(equal, instr->environment());
+  __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, temp);
+  DeoptimizeIf(below, instr->environment());
+  __ jmp(&receiver_ok);
+
   __ bind(&global_receiver);
   __ mov(receiver, GlobalObjectOperand());
   __ bind(&receiver_ok);

-  Register length = ToRegister(instr->length());
-  Register elements = ToRegister(instr->elements());
-
   Label invoke;

   // Copy the arguments to this function possibly from the
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Wed Feb 9 04:39:15 2011 +++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Wed Feb 9 08:43:23 2011
@@ -1157,10 +1157,12 @@
   LOperand* receiver = UseFixed(instr->receiver(), eax);
   LOperand* length = UseRegisterAtStart(instr->length());
   LOperand* elements = UseRegisterAtStart(instr->elements());
+  LOperand* temp = FixedTemp(ebx);
   LApplyArguments* result = new LApplyArguments(function,
                                                 receiver,
                                                 length,
-                                                elements);
+                                                elements,
+                                                temp);
return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY);
 }

=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h     Wed Feb  9 04:39:15 2011
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.h     Wed Feb  9 08:43:23 2011
@@ -461,16 +461,18 @@
 };


-class LApplyArguments: public LTemplateInstruction<1, 4, 0> {
+class LApplyArguments: public LTemplateInstruction<1, 4, 1> {
  public:
   LApplyArguments(LOperand* function,
                   LOperand* receiver,
                   LOperand* length,
-                  LOperand* elements) {
+                  LOperand* elements,
+                  LOperand* temp) {
     inputs_[0] = function;
     inputs_[1] = receiver;
     inputs_[2] = length;
     inputs_[3] = elements;
+    temps_[0] = temp;
   }

   DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply-arguments")
=======================================
--- /branches/bleeding_edge/test/mjsunit/compiler/regress-arguments.js Tue Dec 7 03:31:57 2010 +++ /branches/bleeding_edge/test/mjsunit/compiler/regress-arguments.js Wed Feb 9 08:43:23 2011
@@ -46,4 +46,7 @@
  return f.apply(v, arguments);
 }

-for (var i=0; i<1000000; i++) assertEquals(void 0, u());
+Number.prototype.foo = 42;
+delete Number.prototype.foo;
+
+for (var i=0; i<100000; i++) assertEquals(void 0, u());

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

Reply via email to