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