Port change (r1837) that allows call-as-function handlers to be called
through new to ARM. Added simple test case of the current behavior. For consistency, changed a number of occurences of explicit moves to pc to use Jump instead. Review URL: http://codereview.chromium.org/115014 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1889 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
9ab31a82c3
commit
7adff828a0
@ -58,6 +58,16 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
|
||||
// -- sp[...]: constructor arguments
|
||||
// -----------------------------------
|
||||
|
||||
Label non_function_call;
|
||||
// Check that the function is not a smi.
|
||||
__ tst(r1, Operand(kSmiTagMask));
|
||||
__ b(eq, &non_function_call);
|
||||
// Check that the function is a JSFunction.
|
||||
__ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
|
||||
__ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
|
||||
__ cmp(r2, Operand(JS_FUNCTION_TYPE));
|
||||
__ b(ne, &non_function_call);
|
||||
|
||||
// Enter a construct frame.
|
||||
__ EnterConstructFrame();
|
||||
|
||||
@ -169,7 +179,17 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
|
||||
__ LeaveConstructFrame();
|
||||
__ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
|
||||
__ add(sp, sp, Operand(kPointerSize));
|
||||
__ mov(pc, Operand(lr));
|
||||
__ Jump(lr);
|
||||
|
||||
// r0: number of arguments
|
||||
// r1: called object
|
||||
__ bind(&non_function_call);
|
||||
|
||||
// Set expected number of arguments to zero (not changing r0).
|
||||
__ mov(r2, Operand(0));
|
||||
__ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
|
||||
__ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
|
||||
RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
@ -235,7 +255,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
|
||||
// Exit the JS frame and remove the parameters (except function), and return.
|
||||
// Respect ABI stack constraint.
|
||||
__ LeaveInternalFrame();
|
||||
__ mov(pc, lr);
|
||||
__ Jump(lr);
|
||||
|
||||
// r0: result
|
||||
}
|
||||
@ -544,7 +564,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
||||
// Tear down the internal frame and remove function, receiver and args.
|
||||
__ LeaveInternalFrame();
|
||||
__ add(sp, sp, Operand(3 * kPointerSize));
|
||||
__ mov(pc, lr);
|
||||
__ Jump(lr);
|
||||
}
|
||||
|
||||
|
||||
@ -663,14 +683,14 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
|
||||
|
||||
// Exit frame and return.
|
||||
LeaveArgumentsAdaptorFrame(masm);
|
||||
__ mov(pc, lr);
|
||||
__ Jump(lr);
|
||||
|
||||
|
||||
// -------------------------------------------
|
||||
// Dont adapt arguments.
|
||||
// -------------------------------------------
|
||||
__ bind(&dont_adapt_arguments);
|
||||
__ mov(pc, r3);
|
||||
__ Jump(r3);
|
||||
}
|
||||
|
||||
|
||||
|
@ -277,7 +277,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
|
||||
frame_->Exit();
|
||||
|
||||
__ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize));
|
||||
__ mov(pc, lr);
|
||||
__ Jump(lr);
|
||||
}
|
||||
|
||||
// Code generation state must be reset.
|
||||
@ -5034,13 +5034,13 @@ void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) {
|
||||
|
||||
// Nothing to do: The formal number of parameters has already been
|
||||
// passed in register r0 by calling function. Just return it.
|
||||
__ mov(pc, lr);
|
||||
__ Jump(lr);
|
||||
|
||||
// Arguments adaptor case: Read the arguments length from the
|
||||
// adaptor frame and return it.
|
||||
__ bind(&adaptor);
|
||||
__ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
||||
__ mov(pc, lr);
|
||||
__ Jump(lr);
|
||||
}
|
||||
|
||||
|
||||
@ -5072,7 +5072,7 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
|
||||
__ sub(r3, r0, r1);
|
||||
__ add(r3, fp, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
|
||||
__ ldr(r0, MemOperand(r3, kDisplacement));
|
||||
__ mov(pc, lr);
|
||||
__ Jump(lr);
|
||||
|
||||
// Arguments adaptor case: Check index against actual arguments
|
||||
// limit found in the arguments adaptor frame. Use unsigned
|
||||
@ -5086,7 +5086,7 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
|
||||
__ sub(r3, r0, r1);
|
||||
__ add(r3, r2, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
|
||||
__ ldr(r0, MemOperand(r3, kDisplacement));
|
||||
__ mov(pc, lr);
|
||||
__ Jump(lr);
|
||||
|
||||
// Slow-case: Handle non-smi or out-of-bounds access to arguments
|
||||
// by calling the runtime system.
|
||||
|
@ -4627,35 +4627,42 @@ THREADED_TEST(CallAsFunction) {
|
||||
Local<Value> value;
|
||||
CHECK(!try_catch.HasCaught());
|
||||
|
||||
value = Script::Compile(v8_str("obj(42)"))->Run();
|
||||
value = CompileRun("obj(42)");
|
||||
CHECK(!try_catch.HasCaught());
|
||||
CHECK_EQ(42, value->Int32Value());
|
||||
|
||||
value = Script::Compile(v8_str("(function(o){return o(49)})(obj)"))->Run();
|
||||
value = CompileRun("(function(o){return o(49)})(obj)");
|
||||
CHECK(!try_catch.HasCaught());
|
||||
CHECK_EQ(49, value->Int32Value());
|
||||
|
||||
// test special case of call as function
|
||||
value = Script::Compile(v8_str("[obj]['0'](45)"))->Run();
|
||||
value = CompileRun("[obj]['0'](45)");
|
||||
CHECK(!try_catch.HasCaught());
|
||||
CHECK_EQ(45, value->Int32Value());
|
||||
|
||||
value = Script::Compile(v8_str("obj.call = Function.prototype.call;"
|
||||
"obj.call(null, 87)"))->Run();
|
||||
value = CompileRun("obj.call = Function.prototype.call;"
|
||||
"obj.call(null, 87)");
|
||||
CHECK(!try_catch.HasCaught());
|
||||
CHECK_EQ(87, value->Int32Value());
|
||||
|
||||
// Regression tests for bug #1116356: Calling call through call/apply
|
||||
// must work for non-function receivers.
|
||||
const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
|
||||
value = Script::Compile(v8_str(apply_99))->Run();
|
||||
value = CompileRun(apply_99);
|
||||
CHECK(!try_catch.HasCaught());
|
||||
CHECK_EQ(99, value->Int32Value());
|
||||
|
||||
const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
|
||||
value = Script::Compile(v8_str(call_17))->Run();
|
||||
value = CompileRun(call_17);
|
||||
CHECK(!try_catch.HasCaught());
|
||||
CHECK_EQ(17, value->Int32Value());
|
||||
|
||||
// Check that the call-as-function handler can be called through
|
||||
// new. Currently, there is no way to check in the call-as-function
|
||||
// handler if it has been called through new or not.
|
||||
value = CompileRun("new obj(42)");
|
||||
CHECK(!try_catch.HasCaught());
|
||||
CHECK_EQ(42, value->Int32Value());
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user