Commit 975141b2 authored by plind44@gmail.com's avatar plind44@gmail.com

MIPS: Make the strict-mode calling convention for contextual calls the default one.

Port r18581 (e5df8ae)

BUG=
R=plind44@gmail.com

Review URL: https://codereview.chromium.org/138383002

Patch from Balazs Kilvady <kilvadyb@homejinni.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18596 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 72125baf
......@@ -1114,8 +1114,6 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ li(t0, Operand(0, RelocInfo::NONE32));
__ Branch(&patch_receiver);
// Use the global receiver object from the called function as the
// receiver.
__ bind(&use_global_receiver);
__ lw(a2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
__ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset));
......@@ -1205,14 +1203,14 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset));
__ sra(a2, a2, kSmiTagSize);
__ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
__ SetCallKind(t1, CALL_AS_METHOD);
__ SetCallKind(t1, CALL_AS_FUNCTION);
// Check formal and actual parameter counts.
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
RelocInfo::CODE_TARGET, ne, a2, Operand(a0));
ParameterCount expected(0);
__ InvokeCode(a3, expected, expected, JUMP_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
NullCallWrapper(), CALL_AS_FUNCTION);
}
......@@ -1305,7 +1303,6 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
__ mov(a0, v0); // Put object in a0 to match other paths to push_receiver.
__ Branch(&push_receiver);
// Use the current global receiver object as the receiver.
__ bind(&use_global_receiver);
__ lw(a0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
__ lw(a0, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset));
......@@ -1342,7 +1339,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
__ lw(a1, MemOperand(fp, kLimitOffset));
__ Branch(&loop, ne, a0, Operand(a1));
// Invoke the function.
// Call the function.
Label call_proxy;
ParameterCount actual(a0);
__ sra(a0, a0, kSmiTagSize);
......@@ -1351,18 +1348,18 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
__ Branch(&call_proxy, ne, a2, Operand(JS_FUNCTION_TYPE));
__ InvokeFunction(a1, actual, CALL_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
NullCallWrapper(), CALL_AS_FUNCTION);
frame_scope.GenerateLeaveFrame();
__ Ret(USE_DELAY_SLOT);
__ Addu(sp, sp, Operand(3 * kPointerSize)); // In delay slot.
// Invoke the function proxy.
// Call the function proxy.
__ bind(&call_proxy);
__ push(a1); // Add function proxy as last argument.
__ Addu(a0, a0, Operand(1));
__ li(a2, Operand(0, RelocInfo::NONE32));
__ SetCallKind(t1, CALL_AS_METHOD);
__ SetCallKind(t1, CALL_AS_FUNCTION);
__ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY);
__ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
RelocInfo::CODE_TARGET);
......
......@@ -3332,43 +3332,9 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
// a1: pushed function (to be verified)
__ JumpIfSmi(a1, &non_function);
// The receiver might implicitly be the global object. This is
// indicated by passing the hole as the receiver to the call
// function stub.
if (ReceiverMightBeImplicit() || ReceiverIsImplicit()) {
Label try_call, call, patch_current_context;
if (ReceiverMightBeImplicit()) {
// Get the receiver from the stack.
// function, receiver [, arguments]
__ lw(t0, MemOperand(sp, argc_ * kPointerSize));
// Call as function is indicated with the hole.
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ Branch(&try_call, ne, t0, Operand(at));
}
// Patch the receiver on the stack with the global receiver object.
// Goto slow case if we do not have a function.
__ GetObjectType(a1, a3, a3);
__ Branch(&patch_current_context, ne, a3, Operand(JS_FUNCTION_TYPE));
CallStubCompiler::FetchGlobalProxy(masm, a3, a1);
__ sw(a3, MemOperand(sp, argc_ * kPointerSize));
__ Branch(&call);
__ bind(&patch_current_context);
__ LoadRoot(t0, Heap::kUndefinedValueRootIndex);
__ sw(t0, MemOperand(sp, argc_ * kPointerSize));
__ Branch(&slow);
__ bind(&try_call);
// Get the map of the function object.
__ GetObjectType(a1, a3, a3);
__ Branch(&slow, ne, a3, Operand(JS_FUNCTION_TYPE));
__ bind(&call);
} else {
// Get the map of the function object.
__ GetObjectType(a1, a3, a3);
__ Branch(&slow, ne, a3, Operand(JS_FUNCTION_TYPE));
}
// Goto slow case if we do not have a function.
__ GetObjectType(a1, a3, a3);
__ Branch(&slow, ne, a3, Operand(JS_FUNCTION_TYPE));
if (RecordCallTarget()) {
GenerateRecordCallTarget(masm);
......@@ -3378,17 +3344,6 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
// a1: pushed function
ParameterCount actual(argc_);
if (ReceiverMightBeImplicit()) {
Label call_as_function;
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ Branch(&call_as_function, eq, t0, Operand(at));
__ InvokeFunction(a1,
actual,
JUMP_FUNCTION,
NullCallWrapper(),
CALL_AS_METHOD);
__ bind(&call_as_function);
}
__ InvokeFunction(a1,
actual,
JUMP_FUNCTION,
......@@ -3426,7 +3381,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
__ li(a0, Operand(argc_)); // Set up the number of arguments.
__ mov(a2, zero_reg);
__ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION);
__ SetCallKind(t1, CALL_AS_METHOD);
__ SetCallKind(t1, CALL_AS_FUNCTION);
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
RelocInfo::CODE_TARGET);
}
......
......@@ -152,16 +152,22 @@ void FullCodeGenerator::Generate() {
}
#endif
// Strict mode functions and builtins need to replace the receiver
// with undefined when called as functions (without an explicit
// receiver object). t1 is zero for method calls and non-zero for
// function calls.
if (!info->is_classic_mode() || info->is_native()) {
// Classic mode functions and builtins need to replace the receiver with the
// global proxy when called as functions (without an explicit receiver
// object).
if (info->is_classic_mode() && !info->is_native()) {
Label ok;
__ Branch(&ok, eq, t1, Operand(zero_reg));
int receiver_offset = info->scope()->num_parameters() * kPointerSize;
__ lw(at, MemOperand(sp, receiver_offset));
__ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
__ Branch(&ok, ne, a2, Operand(at));
__ lw(a2, GlobalObjectOperand());
__ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset));
__ sw(a2, MemOperand(sp, receiver_offset));
__ bind(&ok);
}
......@@ -2786,7 +2792,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
}
// Record source position for debugger.
SetSourcePosition(expr->position());
CallFunctionStub stub(arg_count, RECEIVER_MIGHT_BE_IMPLICIT);
CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS);
__ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
RecordJSReturnSite(expr);
......@@ -2828,15 +2834,14 @@ void FullCodeGenerator::VisitCall(Call* expr) {
__ push(v0);
// The receiver is implicitly the global receiver. Indicate this
// by passing the hole to the call function stub.
__ LoadRoot(a1, Heap::kTheHoleValueRootIndex);
__ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
__ push(a1);
__ bind(&call);
}
// The receiver is either the global receiver or an object found
// by LoadContextSlot. That object could be the hole if the
// receiver is implicitly the global object.
EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT);
// by LoadContextSlot.
EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
} else if (property != NULL) {
{ PreservePositionScope scope(masm()->positions_recorder());
VisitForStackValue(property->obj());
......@@ -2853,12 +2858,10 @@ void FullCodeGenerator::VisitCall(Call* expr) {
{ PreservePositionScope scope(masm()->positions_recorder());
VisitForStackValue(callee);
}
// Push the hole as receiver.
// It will be correctly replaced in the call stub.
__ LoadRoot(a1, Heap::kTheHoleValueRootIndex);
__ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
__ push(a1);
// Emit function call.
EmitCallWithStub(expr, RECEIVER_IS_IMPLICIT);
EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
}
#ifdef DEBUG
......@@ -3799,7 +3802,7 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
__ mov(a1, result_register());
ParameterCount count(arg_count);
__ InvokeFunction(a1, count, CALL_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
NullCallWrapper(), CALL_AS_FUNCTION);
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ jmp(&done);
......
......@@ -493,7 +493,7 @@ void CallICBase::GenerateMiss(MacroAssembler* masm,
// Patch the receiver on the stack.
__ bind(&global);
CallStubCompiler::FetchGlobalProxy(masm, a2, a1);
__ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
__ sw(a2, MemOperand(sp, argc * kPointerSize));
__ bind(&invoke);
}
......
......@@ -146,17 +146,25 @@ bool LCodeGen::GeneratePrologue() {
// fp: Caller's frame pointer.
// lr: Caller's pc.
// Strict mode functions and builtins need to replace the receiver
// with undefined when called as functions (without an explicit
// receiver object). r5 is zero for method calls and non-zero for
// function calls.
if (!info_->is_classic_mode() || info_->is_native()) {
// Classic mode functions and builtins need to replace the receiver with the
// global proxy when called as functions (without an explicit receiver
// object).
if (info_->this_has_uses() &&
info_->is_classic_mode() &&
!info_->is_native()) {
Label ok;
__ Branch(&ok, eq, t1, Operand(zero_reg));
int receiver_offset = scope()->num_parameters() * kPointerSize;
__ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
int receiver_offset = info_->scope()->num_parameters() * kPointerSize;
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ lw(a2, MemOperand(sp, receiver_offset));
__ Branch(&ok, ne, a2, Operand(at));
__ lw(a2, GlobalObjectOperand());
__ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset));
__ sw(a2, MemOperand(sp, receiver_offset));
__ bind(&ok);
}
}
......@@ -3370,7 +3378,12 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
__ Branch(&result_in_receiver);
__ bind(&global_object);
CallStubCompiler::FetchGlobalProxy(masm(), receiver, function);
__ lw(receiver, FieldMemOperand(function, JSFunction::kContextOffset));
__ lw(receiver,
ContextOperand(receiver,
Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
__ lw(receiver,
FieldMemOperand(receiver, GlobalObject::kGlobalReceiverOffset));
if (result.is(receiver)) {
__ bind(&result_in_receiver);
......@@ -3429,7 +3442,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
// by InvokeFunction.
ParameterCount actual(receiver);
__ InvokeFunction(function, actual, CALL_FUNCTION,
safepoint_generator, CALL_AS_METHOD);
safepoint_generator, CALL_AS_FUNCTION);
}
......@@ -3550,7 +3563,7 @@ void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
instr->hydrogen()->formal_parameter_count(),
instr->arity(),
instr,
CALL_AS_METHOD,
CALL_AS_FUNCTION,
A1_UNINITIALIZED);
}
......@@ -3873,13 +3886,13 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
LPointerMap* pointers = instr->pointer_map();
SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
ParameterCount count(instr->arity());
__ InvokeFunction(a1, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
__ InvokeFunction(a1, count, CALL_FUNCTION, generator, CALL_AS_FUNCTION);
} else {
CallKnownFunction(known_function,
instr->hydrogen()->formal_parameter_count(),
instr->arity(),
instr,
CALL_AS_METHOD,
CALL_AS_FUNCTION,
A1_CONTAINS_TARGET);
}
}
......@@ -3914,10 +3927,7 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) {
ASSERT(ToRegister(instr->result()).is(v0));
int arity = instr->arity();
CallFunctionFlags flags =
instr->hydrogen()->IsContextualCall() ?
RECEIVER_IS_IMPLICIT : NO_CALL_FUNCTION_FLAGS;
CallFunctionStub stub(arity, flags);
CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS);
if (instr->hydrogen()->IsTailCall()) {
if (NeedsEagerFrame()) __ mov(sp, fp);
__ Jump(stub.GetCode(isolate()), RelocInfo::CODE_TARGET);
......
......@@ -2437,8 +2437,7 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
instr->arguments_count(),
instr->function(),
undefined,
instr->inlining_kind(),
instr->undefined_receiver());
instr->inlining_kind());
// Only replay binding of arguments object if it wasn't removed from graph.
if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
inner->Bind(instr->arguments_var(), instr->arguments_object());
......
......@@ -2337,23 +2337,11 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
}
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object,
Handle<JSFunction> function) {
void CallStubCompiler::PatchImplicitReceiver(Handle<Object> object) {
if (object->IsGlobalObject()) {
const int argc = arguments().immediate();
const int receiver_offset = argc * kPointerSize;
__ li(a3, handle(function->context()->global_proxy()));
__ sw(a3, MemOperand(sp, receiver_offset));
}
}
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object,
Register function) {
if (object->IsGlobalObject()) {
FetchGlobalProxy(masm(), a3, function);
const int argc = arguments().immediate();
const int receiver_offset = argc * kPointerSize;
__ LoadRoot(a3, Heap::kUndefinedValueRootIndex);
__ sw(a3, MemOperand(sp, receiver_offset));
}
}
......@@ -2452,7 +2440,8 @@ void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
ASSERT(function.is(a1));
// Check that the function really is a function.
GenerateFunctionCheck(function, a3, miss);
PatchGlobalProxy(object, function);
PatchImplicitReceiver(object);
// Invoke the function.
__ InvokeFunction(a1, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind());
......@@ -2570,15 +2559,6 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
#define __ ACCESS_MASM(masm)
void CallStubCompiler::FetchGlobalProxy(MacroAssembler* masm,
Register target,
Register function) {
__ lw(target, FieldMemOperand(function, JSFunction::kContextOffset));
__ lw(target, ContextOperand(target, Context::GLOBAL_OBJECT_INDEX));
__ lw(target, FieldMemOperand(target, GlobalObject::kGlobalReceiverOffset));
}
void StoreStubCompiler::GenerateStoreViaSetter(
MacroAssembler* masm,
Handle<JSFunction> setter) {
......
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