Commit 544191e7 authored by ager@chromium.org's avatar ager@chromium.org

Update apply with arguments optimization for strict mode functions and builtins.

Do not convert to object for values for strict-mode functions and
builtins.

R=ricow@chromium.org
BUG=v8:1412
TEST=mjsunit/regress/regress-1412.js

Review URL: http://codereview.chromium.org/7096006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8120 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 4ba07be9
......@@ -2707,12 +2707,26 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
ASSERT(function.is(r1)); // Required by InvokeFunction.
ASSERT(ToRegister(instr->result()).is(r0));
// TODO(1412): This is not correct if the called function is a
// strict mode function or a native.
//
// If the receiver is null or undefined, we have to pass the global object
// as a receiver.
// If the receiver is null or undefined, we have to pass the global
// object as a receiver to normal functions. Values have to be
// passed unchanged to builtins and strict-mode functions.
Label global_object, receiver_ok;
// Do not transform the receiver to object for strict mode
// functions.
__ ldr(scratch,
FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
__ ldr(scratch,
FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
__ tst(scratch,
Operand(1 << (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize)));
__ b(ne, &receiver_ok);
// Do not transform the receiver to object for builtins.
__ tst(scratch, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
__ b(ne, &receiver_ok);
// Normal function. Replace undefined or null with global receiver.
__ LoadRoot(scratch, Heap::kNullValueRootIndex);
__ cmp(receiver, scratch);
__ b(eq, &global_object);
......
......@@ -2602,12 +2602,25 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
ASSERT(function.is(edi)); // Required by InvokeFunction.
ASSERT(ToRegister(instr->result()).is(eax));
// TODO(1412): This is not correct if the called function is a
// strict mode function or a native.
//
// If the receiver is null or undefined, we have to pass the global object
// as a receiver.
// If the receiver is null or undefined, we have to pass the global
// object as a receiver to normal functions. Values have to be
// passed unchanged to builtins and strict-mode functions.
Label global_object, receiver_ok;
// Do not transform the receiver to object for strict mode
// functions.
__ mov(scratch,
FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
__ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset),
1 << SharedFunctionInfo::kStrictModeBitWithinByte);
__ j(not_equal, &receiver_ok, Label::kNear);
// Do not transform the receiver to object for builtins.
__ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset),
1 << SharedFunctionInfo::kNativeBitWithinByte);
__ j(not_equal, &receiver_ok, Label::kNear);
// Normal function. Replace undefined or null with global receiver.
__ cmp(receiver, factory()->null_value());
__ j(equal, &global_object, Label::kNear);
__ cmp(receiver, factory()->undefined_value());
......
......@@ -849,7 +849,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
// Do not transform the receiver for natives.
__ testb(FieldOperand(rdx, SharedFunctionInfo::kNativeByteOffset),
Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
__ j(not_zero, &push_receiver);
__ j(not_equal, &push_receiver);
// Compute the receiver in non-strict mode.
__ JumpIfSmi(rbx, &call_to_object, Label::kNear);
......
......@@ -2608,12 +2608,27 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
ASSERT(function.is(rdi)); // Required by InvokeFunction.
ASSERT(ToRegister(instr->result()).is(rax));
// TODO(1412): This is not correct if the called function is a
// strict mode function or a native.
//
// If the receiver is null or undefined, we have to pass the global object
// as a receiver.
// If the receiver is null or undefined, we have to pass the global
// object as a receiver to normal functions. Values have to be
// passed unchanged to builtins and strict-mode functions.
Label global_object, receiver_ok;
// Do not transform the receiver to object for strict mode
// functions.
__ movq(kScratchRegister,
FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
__ testb(FieldOperand(kScratchRegister,
SharedFunctionInfo::kStrictModeByteOffset),
Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
__ j(not_equal, &receiver_ok, Label::kNear);
// Do not transform the receiver to object for builtins.
__ testb(FieldOperand(kScratchRegister,
SharedFunctionInfo::kNativeByteOffset),
Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
__ j(not_equal, &receiver_ok, Label::kNear);
// Normal function. Replace undefined or null with global receiver.
__ CompareRoot(receiver, Heap::kNullValueRootIndex);
__ j(equal, &global_object, Label::kNear);
__ CompareRoot(receiver, Heap::kUndefinedValueRootIndex);
......
......@@ -25,10 +25,35 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function f() { "use strict"; print(this); }
// Test that the apply with arguments optimization passes values
// unchanged to strict-mode functions and builtins.
function g() { assertEquals(void 0, f.apply(undefined, arguments)); }
// Flags: --allow-natives-syntax
for (var i = 0; i < 10; i++) g();
%OptimizeFunctionOnNextCall(g);
g();
function strict() { "use strict"; return this; }
function test_strict() {
assertEquals(void 0, strict.apply(undefined, arguments));
assertEquals(42, strict.apply(42, arguments));
assertEquals("asdf", strict.apply("asdf", arguments));
}
for (var i = 0; i < 10; i++) test_strict();
%OptimizeFunctionOnNextCall(test_strict);
test_strict();
function test_builtin(receiver) {
Object.prototype.valueOf.apply(receiver, arguments);
}
for (var i = 0; i < 10; i++) test_builtin(this);
%OptimizeFunctionOnNextCall(test_builtin);
test_builtin(this);
var exception = false;
try {
test_builtin(undefined);
} catch(e) {
exception = true;
}
assertTrue(exception);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment