Commit 7adff828 authored by ager@chromium.org's avatar ager@chromium.org

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
parent 9ab31a82
......@@ -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());
}
......
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