PPC: Remove CallFunctionStub, always call through the Call builtin (also from CallIC).
Port 44c44521ae
Original commit message:
This fixes receiver conversion since the Call builtin does it correctly.
R=verwaest@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com, dstence@us.ibm.com
BUG=v8:4526
LOG=n
Review URL: https://codereview.chromium.org/1423973006
Cr-Commit-Position: refs/heads/master@{#31901}
This commit is contained in:
parent
aca03dfca1
commit
44fcc2e795
@ -4051,7 +4051,6 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) {
|
||||
DCHECK(ToRegister(instr->result()).is(r3));
|
||||
|
||||
int arity = instr->arity();
|
||||
CallFunctionFlags flags = instr->hydrogen()->function_flags();
|
||||
if (instr->hydrogen()->HasVectorAndSlot()) {
|
||||
Register slot_register = ToRegister(instr->temp_slot());
|
||||
Register vector_register = ToRegister(instr->temp_vector());
|
||||
@ -4065,15 +4064,12 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) {
|
||||
__ Move(vector_register, vector);
|
||||
__ LoadSmiLiteral(slot_register, Smi::FromInt(index));
|
||||
|
||||
CallICState::CallType call_type =
|
||||
(flags & CALL_AS_METHOD) ? CallICState::METHOD : CallICState::FUNCTION;
|
||||
|
||||
Handle<Code> ic =
|
||||
CodeFactory::CallICInOptimizedCode(isolate(), arity, call_type).code();
|
||||
CodeFactory::CallICInOptimizedCode(isolate(), arity).code();
|
||||
CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
||||
} else {
|
||||
CallFunctionStub stub(isolate(), arity, flags);
|
||||
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
||||
__ mov(r3, Operand(arity));
|
||||
CallCode(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET, instr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2088,8 +2088,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
__ mr(r4, r3);
|
||||
__ StoreP(r4, MemOperand(sp, 2 * kPointerSize));
|
||||
SetCallPosition(expr, 1);
|
||||
CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD);
|
||||
__ CallStub(&stub);
|
||||
__ li(r3, Operand(1));
|
||||
__ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
|
||||
|
||||
__ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
__ Drop(1); // The function is still on the stack; drop it.
|
||||
@ -2814,11 +2814,8 @@ void FullCodeGenerator::CallIC(Handle<Code> code, TypeFeedbackId ast_id) {
|
||||
void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
|
||||
Expression* callee = expr->expression();
|
||||
|
||||
CallICState::CallType call_type =
|
||||
callee->IsVariableProxy() ? CallICState::FUNCTION : CallICState::METHOD;
|
||||
|
||||
// Get the target function.
|
||||
if (call_type == CallICState::FUNCTION) {
|
||||
if (callee->IsVariableProxy()) {
|
||||
{
|
||||
StackValueContext context(this);
|
||||
EmitVariableLoad(callee->AsVariableProxy());
|
||||
@ -2841,7 +2838,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
|
||||
__ StoreP(r3, MemOperand(sp, kPointerSize));
|
||||
}
|
||||
|
||||
EmitCall(expr, call_type);
|
||||
EmitCall(expr);
|
||||
}
|
||||
|
||||
|
||||
@ -2879,7 +2876,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
// Stack here:
|
||||
// - target function
|
||||
// - this (receiver)
|
||||
EmitCall(expr, CallICState::METHOD);
|
||||
EmitCall(expr);
|
||||
}
|
||||
|
||||
|
||||
@ -2902,7 +2899,7 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, Expression* key) {
|
||||
__ push(ip);
|
||||
__ StoreP(r3, MemOperand(sp, kPointerSize));
|
||||
|
||||
EmitCall(expr, CallICState::METHOD);
|
||||
EmitCall(expr);
|
||||
}
|
||||
|
||||
|
||||
@ -2938,11 +2935,11 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
// Stack here:
|
||||
// - target function
|
||||
// - this (receiver)
|
||||
EmitCall(expr, CallICState::METHOD);
|
||||
EmitCall(expr);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
|
||||
void FullCodeGenerator::EmitCall(Call* expr) {
|
||||
// Load the arguments.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
@ -2952,7 +2949,7 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
|
||||
|
||||
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
|
||||
SetCallPosition(expr, arg_count);
|
||||
Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code();
|
||||
Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count).code();
|
||||
__ LoadSmiLiteral(r6, SmiFromSlot(expr->CallFeedbackICSlot()));
|
||||
__ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
|
||||
// Don't assign a type feedback id to the IC, since type feedback is provided
|
||||
@ -3060,9 +3057,9 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
|
||||
|
||||
// Record source position for debugger.
|
||||
SetCallPosition(expr, arg_count);
|
||||
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
|
||||
__ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
|
||||
__ CallStub(&stub);
|
||||
__ mov(r3, Operand(arg_count));
|
||||
__ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
|
||||
RecordJSReturnSite(expr);
|
||||
// Restore context register.
|
||||
__ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
@ -4259,9 +4256,9 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
|
||||
int arg_count = args->length();
|
||||
|
||||
SetCallPosition(expr, arg_count);
|
||||
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
|
||||
__ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
|
||||
__ CallStub(&stub);
|
||||
__ mov(r3, Operand(arg_count));
|
||||
__ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2529,119 +2529,6 @@ static void GenerateRecordCallTarget(MacroAssembler* masm, bool is_super) {
|
||||
}
|
||||
|
||||
|
||||
static void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r4 : the function to call
|
||||
// -- r6 : the function's shared function info
|
||||
// -----------------------------------
|
||||
// Do not transform the receiver for strict mode functions and natives.
|
||||
__ lwz(r7, FieldMemOperand(r6, SharedFunctionInfo::kCompilerHintsOffset));
|
||||
__ andi(r0, r7, Operand((1 << SharedFunctionInfo::kStrictModeBit) |
|
||||
(1 << SharedFunctionInfo::kNativeBit)));
|
||||
__ bne(cont, cr0);
|
||||
}
|
||||
|
||||
|
||||
static void EmitSlowCase(MacroAssembler* masm, int argc) {
|
||||
__ mov(r3, Operand(argc));
|
||||
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
|
||||
// Wrap the receiver and patch it back onto the stack.
|
||||
{
|
||||
FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL);
|
||||
__ push(r4);
|
||||
__ mr(r3, r6);
|
||||
ToObjectStub stub(masm->isolate());
|
||||
__ CallStub(&stub);
|
||||
__ pop(r4);
|
||||
}
|
||||
__ StoreP(r3, MemOperand(sp, argc * kPointerSize), r0);
|
||||
__ b(cont);
|
||||
}
|
||||
|
||||
|
||||
static void EmitClassConstructorCallCheck(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r4 : the function to call
|
||||
// -- r6 : the function's shared function info
|
||||
// -----------------------------------
|
||||
// ClassConstructor Check: ES6 section 9.2.1 [[Call]]
|
||||
Label non_class_constructor;
|
||||
// Check whether the current function is a classConstructor.
|
||||
__ lwz(r7, FieldMemOperand(r6, SharedFunctionInfo::kCompilerHintsOffset));
|
||||
__ TestBitMask(r7, SharedFunctionInfo::kClassConstructorBits, r0);
|
||||
__ beq(&non_class_constructor, cr0);
|
||||
// If we call a classConstructor Function throw a TypeError
|
||||
// indirectly via the CallFunction builtin.
|
||||
__ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
|
||||
__ bind(&non_class_constructor);
|
||||
}
|
||||
|
||||
|
||||
static void CallFunctionNoFeedback(MacroAssembler* masm, int argc,
|
||||
bool needs_checks, bool call_as_method) {
|
||||
// r4 : the function to call
|
||||
Label slow, wrap, cont;
|
||||
|
||||
if (needs_checks) {
|
||||
// Check that the function is really a JavaScript function.
|
||||
// r4: pushed function (to be verified)
|
||||
__ JumpIfSmi(r4, &slow);
|
||||
|
||||
// Goto slow case if we do not have a function.
|
||||
__ CompareObjectType(r4, r7, r7, JS_FUNCTION_TYPE);
|
||||
__ bne(&slow);
|
||||
}
|
||||
|
||||
__ LoadP(r6, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
|
||||
EmitClassConstructorCallCheck(masm);
|
||||
|
||||
// Fast-case: Invoke the function now.
|
||||
// r4: pushed function
|
||||
ParameterCount actual(argc);
|
||||
|
||||
if (call_as_method) {
|
||||
if (needs_checks) {
|
||||
EmitContinueIfStrictOrNative(masm, &cont);
|
||||
}
|
||||
|
||||
// Compute the receiver in sloppy mode.
|
||||
__ LoadP(r6, MemOperand(sp, argc * kPointerSize), r0);
|
||||
|
||||
if (needs_checks) {
|
||||
__ JumpIfSmi(r6, &wrap);
|
||||
__ CompareObjectType(r6, r7, r7, FIRST_SPEC_OBJECT_TYPE);
|
||||
__ blt(&wrap);
|
||||
} else {
|
||||
__ b(&wrap);
|
||||
}
|
||||
|
||||
__ bind(&cont);
|
||||
}
|
||||
|
||||
__ InvokeFunction(r4, actual, JUMP_FUNCTION, NullCallWrapper());
|
||||
|
||||
if (needs_checks) {
|
||||
// Slow-case: Non-function called.
|
||||
__ bind(&slow);
|
||||
EmitSlowCase(masm, argc);
|
||||
}
|
||||
|
||||
if (call_as_method) {
|
||||
__ bind(&wrap);
|
||||
EmitWrapCase(masm, argc, &cont);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CallFunctionStub::Generate(MacroAssembler* masm) {
|
||||
CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod());
|
||||
}
|
||||
|
||||
|
||||
void CallConstructStub::Generate(MacroAssembler* masm) {
|
||||
// r3 : number of arguments
|
||||
// r4 : the function to call
|
||||
@ -2732,9 +2619,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex);
|
||||
const int generic_offset =
|
||||
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex);
|
||||
Label extra_checks_or_miss, slow_start;
|
||||
Label slow, wrap, cont;
|
||||
Label have_js_function;
|
||||
Label extra_checks_or_miss, call;
|
||||
int argc = arg_count();
|
||||
ParameterCount actual(argc);
|
||||
|
||||
@ -2771,38 +2656,15 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ AddSmiLiteral(r6, r6, Smi::FromInt(CallICNexus::kCallCountIncrement), r0);
|
||||
__ StoreP(r6, FieldMemOperand(r9, count_offset), r0);
|
||||
|
||||
__ bind(&have_js_function);
|
||||
|
||||
__ LoadP(r6, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
|
||||
EmitClassConstructorCallCheck(masm);
|
||||
|
||||
if (CallAsMethod()) {
|
||||
EmitContinueIfStrictOrNative(masm, &cont);
|
||||
// Compute the receiver in sloppy mode.
|
||||
__ LoadP(r6, MemOperand(sp, argc * kPointerSize), r0);
|
||||
|
||||
__ JumpIfSmi(r6, &wrap);
|
||||
__ CompareObjectType(r6, r7, r7, FIRST_SPEC_OBJECT_TYPE);
|
||||
__ blt(&wrap);
|
||||
|
||||
__ bind(&cont);
|
||||
}
|
||||
|
||||
__ InvokeFunction(r4, actual, JUMP_FUNCTION, NullCallWrapper());
|
||||
|
||||
__ bind(&slow);
|
||||
EmitSlowCase(masm, argc);
|
||||
|
||||
if (CallAsMethod()) {
|
||||
__ bind(&wrap);
|
||||
EmitWrapCase(masm, argc, &cont);
|
||||
}
|
||||
__ bind(&call);
|
||||
__ mov(r3, Operand(argc));
|
||||
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
|
||||
|
||||
__ bind(&extra_checks_or_miss);
|
||||
Label uninitialized, miss, not_allocation_site;
|
||||
|
||||
__ CompareRoot(r7, Heap::kmegamorphic_symbolRootIndex);
|
||||
__ beq(&slow_start);
|
||||
__ beq(&call);
|
||||
|
||||
// Verify that r7 contains an AllocationSite
|
||||
__ LoadP(r8, FieldMemOperand(r7, HeapObject::kMapOffset));
|
||||
@ -2837,7 +2699,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ LoadP(r7, FieldMemOperand(r5, generic_offset));
|
||||
__ AddSmiLiteral(r7, r7, Smi::FromInt(1), r0);
|
||||
__ StoreP(r7, FieldMemOperand(r5, generic_offset), r0);
|
||||
__ b(&slow_start);
|
||||
__ b(&call);
|
||||
|
||||
__ bind(&uninitialized);
|
||||
|
||||
@ -2875,23 +2737,14 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ Pop(r4);
|
||||
}
|
||||
|
||||
__ b(&have_js_function);
|
||||
__ b(&call);
|
||||
|
||||
// We are here because tracing is on or we encountered a MISS case we can't
|
||||
// handle here.
|
||||
__ bind(&miss);
|
||||
GenerateMiss(masm);
|
||||
|
||||
// the slow case
|
||||
__ bind(&slow_start);
|
||||
// Check that the function is really a JavaScript function.
|
||||
// r4: pushed function (to be verified)
|
||||
__ JumpIfSmi(r4, &slow);
|
||||
|
||||
// Goto slow case if we do not have a function.
|
||||
__ CompareObjectType(r4, r7, r7, JS_FUNCTION_TYPE);
|
||||
__ bne(&slow);
|
||||
__ b(&have_js_function);
|
||||
__ b(&call);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user