From fb24808c70fb8111725059b332054802cbc75213 Mon Sep 17 00:00:00 2001 From: "vegorov@chromium.org" Date: Tue, 17 Jan 2012 15:53:58 +0000 Subject: [PATCH] Allow call-known-global and call-constant-function to be used for call-sites with mismatched number of arguments. Adjust InvokeFunction to avoid generating dead code when number when arity mismatch is detected in compile time. R=fschneider@google.com Review URL: https://chromiumcodereview.appspot.com/9178017 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10424 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/lithium-codegen-arm.cc | 54 ++++++++++++++++++------------- src/arm/macro-assembler-arm.cc | 70 +++++++++++++++++++++++----------------- src/arm/macro-assembler-arm.h | 2 ++ src/arm/stub-cache-arm.cc | 14 +++++--- src/ast.cc | 15 ++------- src/ia32/lithium-codegen-ia32.cc | 61 ++++++++++++++++++++-------------- src/ia32/macro-assembler-ia32.cc | 61 ++++++++++++++++++++-------------- src/ia32/macro-assembler-ia32.h | 1 + src/x64/lithium-codegen-x64.cc | 61 ++++++++++++++++++++-------------- src/x64/macro-assembler-x64.cc | 55 +++++++++++++++++++------------ src/x64/macro-assembler-x64.h | 1 + 11 files changed, 229 insertions(+), 166 deletions(-) diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index af1c3b2..0e050fe 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -2828,7 +2828,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { this, pointers, Safepoint::kLazyDeopt); // The number of arguments is stored in receiver which is r0, as expected // by InvokeFunction. - v8::internal::ParameterCount actual(receiver); + ParameterCount actual(receiver); __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator, CALL_AS_METHOD); __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); @@ -2883,31 +2883,41 @@ void LCodeGen::CallKnownFunction(Handle function, int arity, LInstruction* instr, CallKind call_kind) { - // Change context if needed. - bool change_context = - (info()->closure()->context() != function->context()) || - scope()->contains_with() || - (scope()->num_heap_slots() > 0); - if (change_context) { - __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); - } - - // Set r0 to arguments count if adaption is not needed. Assumes that r0 - // is available to write to at this point. - if (!function->NeedsArgumentsAdaption()) { - __ mov(r0, Operand(arity)); - } + bool can_invoke_directly = !function->NeedsArgumentsAdaption() || + function->shared()->formal_parameter_count() == arity; LPointerMap* pointers = instr->pointer_map(); RecordPosition(pointers->position()); - // Invoke function. - __ SetCallKind(r5, call_kind); - __ ldr(ip, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); - __ Call(ip); + if (can_invoke_directly) { + __ LoadHeapObject(r1, function); + // Change context if needed. + bool change_context = + (info()->closure()->context() != function->context()) || + scope()->contains_with() || + (scope()->num_heap_slots() > 0); + if (change_context) { + __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); + } - // Set up deoptimization. - RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); + // Set r0 to arguments count if adaption is not needed. Assumes that r0 + // is available to write to at this point. + if (!function->NeedsArgumentsAdaption()) { + __ mov(r0, Operand(arity)); + } + + // Invoke function. + __ SetCallKind(r5, call_kind); + __ ldr(ip, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); + __ Call(ip); + + // Set up deoptimization. + RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); + } else { + SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); + ParameterCount count(arity); + __ InvokeFunction(function, count, CALL_FUNCTION, generator, call_kind); + } // Restore context. __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); @@ -2916,7 +2926,6 @@ void LCodeGen::CallKnownFunction(Handle function, void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { ASSERT(ToRegister(instr->result()).is(r0)); - __ LoadHeapObject(r1, instr->function()); CallKnownFunction(instr->function(), instr->arity(), instr, @@ -3351,7 +3360,6 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) { void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { ASSERT(ToRegister(instr->result()).is(r0)); - __ LoadHeapObject(r1, instr->target()); CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION); } diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index d3d85db..9894ff2 100644 --- a/src/arm/macro-assembler-arm.cc +++ b/src/arm/macro-assembler-arm.cc @@ -957,10 +957,12 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, Handle code_constant, Register code_reg, Label* done, + bool* definitely_mismatches, InvokeFlag flag, const CallWrapper& call_wrapper, CallKind call_kind) { bool definitely_matches = false; + *definitely_mismatches = false; Label regular_invoke; // Check whether the expected and actual arguments count match. If not, @@ -991,6 +993,7 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, // arguments. definitely_matches = true; } else { + *definitely_mismatches = true; mov(r2, Operand(expected.immediate())); } } @@ -1018,7 +1021,9 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, SetCallKind(r5, call_kind); Call(adaptor); call_wrapper.AfterCall(); - b(done); + if (!*definitely_mismatches) { + b(done); + } } else { SetCallKind(r5, call_kind); Jump(adaptor, RelocInfo::CODE_TARGET); @@ -1038,23 +1043,26 @@ void MacroAssembler::InvokeCode(Register code, ASSERT(flag == JUMP_FUNCTION || has_frame()); Label done; - - InvokePrologue(expected, actual, Handle::null(), code, &done, flag, + bool definitely_mismatches = false; + InvokePrologue(expected, actual, Handle::null(), code, + &done, &definitely_mismatches, flag, call_wrapper, call_kind); - if (flag == CALL_FUNCTION) { - call_wrapper.BeforeCall(CallSize(code)); - SetCallKind(r5, call_kind); - Call(code); - call_wrapper.AfterCall(); - } else { - ASSERT(flag == JUMP_FUNCTION); - SetCallKind(r5, call_kind); - Jump(code); - } + if (!definitely_mismatches) { + if (flag == CALL_FUNCTION) { + call_wrapper.BeforeCall(CallSize(code)); + SetCallKind(r5, call_kind); + Call(code); + call_wrapper.AfterCall(); + } else { + ASSERT(flag == JUMP_FUNCTION); + SetCallKind(r5, call_kind); + Jump(code); + } - // Continue here if InvokePrologue does handle the invocation due to - // mismatched parameter counts. - bind(&done); + // Continue here if InvokePrologue does handle the invocation due to + // mismatched parameter counts. + bind(&done); + } } @@ -1068,20 +1076,23 @@ void MacroAssembler::InvokeCode(Handle code, ASSERT(flag == JUMP_FUNCTION || has_frame()); Label done; - - InvokePrologue(expected, actual, code, no_reg, &done, flag, + bool definitely_mismatches = false; + InvokePrologue(expected, actual, code, no_reg, + &done, &definitely_mismatches, flag, NullCallWrapper(), call_kind); - if (flag == CALL_FUNCTION) { - SetCallKind(r5, call_kind); - Call(code, rmode); - } else { - SetCallKind(r5, call_kind); - Jump(code, rmode); - } + if (!definitely_mismatches) { + if (flag == CALL_FUNCTION) { + SetCallKind(r5, call_kind); + Call(code, rmode); + } else { + SetCallKind(r5, call_kind); + Jump(code, rmode); + } - // Continue here if InvokePrologue does handle the invocation due to - // mismatched parameter counts. - bind(&done); + // Continue here if InvokePrologue does handle the invocation due to + // mismatched parameter counts. + bind(&done); + } } @@ -1116,6 +1127,7 @@ void MacroAssembler::InvokeFunction(Register fun, void MacroAssembler::InvokeFunction(Handle function, const ParameterCount& actual, InvokeFlag flag, + const CallWrapper& call_wrapper, CallKind call_kind) { // You can't call a function without a valid frame. ASSERT(flag == JUMP_FUNCTION || has_frame()); @@ -1129,7 +1141,7 @@ void MacroAssembler::InvokeFunction(Handle function, // allow recompilation to take effect without changing any of the // call sites. ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); - InvokeCode(r3, expected, actual, flag, NullCallWrapper(), call_kind); + InvokeCode(r3, expected, actual, flag, call_wrapper, call_kind); } diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h index 2c89a34..60c2e6f 100644 --- a/src/arm/macro-assembler-arm.h +++ b/src/arm/macro-assembler-arm.h @@ -539,6 +539,7 @@ class MacroAssembler: public Assembler { void InvokeFunction(Handle function, const ParameterCount& actual, InvokeFlag flag, + const CallWrapper& call_wrapper, CallKind call_kind); void IsObjectJSObjectType(Register heap_object, @@ -1248,6 +1249,7 @@ class MacroAssembler: public Assembler { Handle code_constant, Register code_reg, Label* done, + bool* definitely_mismatches, InvokeFlag flag, const CallWrapper& call_wrapper, CallKind call_kind); diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc index e4f3dcd..cf2d4e2 100644 --- a/src/arm/stub-cache-arm.cc +++ b/src/arm/stub-cache-arm.cc @@ -738,7 +738,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { ? CALL_AS_FUNCTION : CALL_AS_METHOD; __ InvokeFunction(optimization.constant_function(), arguments_, - JUMP_FUNCTION, call_kind); + JUMP_FUNCTION, NullCallWrapper(), call_kind); } // Deferred code for fast API call case---clean preallocated space. @@ -1904,7 +1904,8 @@ Handle CallStubCompiler::CompileStringFromCharCodeCall( // Tail call the full function. We do not have to patch the receiver // because the function makes no use of it. __ bind(&slow); - __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); + __ InvokeFunction( + function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); __ bind(&miss); // r2: function name. @@ -2049,7 +2050,8 @@ Handle CallStubCompiler::CompileMathFloorCall( __ bind(&slow); // Tail call the full function. We do not have to patch the receiver // because the function makes no use of it. - __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); + __ InvokeFunction( + function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); __ bind(&miss); // r2: function name. @@ -2147,7 +2149,8 @@ Handle CallStubCompiler::CompileMathAbsCall( // Tail call the full function. We do not have to patch the receiver // because the function makes no use of it. __ bind(&slow); - __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); + __ InvokeFunction( + function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); __ bind(&miss); // r2: function name. @@ -2325,7 +2328,8 @@ Handle CallStubCompiler::CompileCallConstant(Handle object, CallKind call_kind = CallICBase::Contextual::decode(extra_state_) ? CALL_AS_FUNCTION : CALL_AS_METHOD; - __ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind); + __ InvokeFunction( + function, arguments(), JUMP_FUNCTION, NullCallWrapper(), call_kind); // Handle call cache miss. __ bind(&miss); diff --git a/src/ast.cc b/src/ast.cc index 2e26999..ab37053 100644 --- a/src/ast.cc +++ b/src/ast.cc @@ -724,16 +724,6 @@ void CaseClause::RecordTypeFeedback(TypeFeedbackOracle* oracle) { } -static bool CanCallWithoutIC(Handle target, int arity) { - SharedFunctionInfo* info = target->shared(); - // If the number of formal parameters of the target function does - // not match the number of arguments we're passing, we don't want to - // deal with it. Otherwise, we can call it directly. - return !target->NeedsArgumentsAdaption() || - info->formal_parameter_count() == arity; -} - - bool Call::ComputeTarget(Handle type, Handle name) { if (check_type_ == RECEIVER_MAP_CHECK) { // For primitive checks the holder is set up to point to the @@ -754,7 +744,7 @@ bool Call::ComputeTarget(Handle type, Handle name) { type = Handle(holder()->map()); } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) { target_ = Handle(lookup.GetConstantFunctionFromMap(*type)); - return CanCallWithoutIC(target_, arguments()->length()); + return true; } else { return false; } @@ -774,8 +764,7 @@ bool Call::ComputeGlobalTarget(Handle global, Handle candidate(JSFunction::cast(cell_->value())); // If the function is in new space we assume it's more likely to // change and thus prefer the general IC code. - if (!HEAP->InNewSpace(*candidate) && - CanCallWithoutIC(candidate, arguments()->length())) { + if (!HEAP->InNewSpace(*candidate)) { target_ = candidate; return true; } diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 8d412fd..a5c96b0 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -2701,41 +2701,53 @@ void LCodeGen::CallKnownFunction(Handle function, int arity, LInstruction* instr, CallKind call_kind) { - // Change context if needed. - bool change_context = - (info()->closure()->context() != function->context()) || - scope()->contains_with() || - (scope()->num_heap_slots() > 0); - if (change_context) { - __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); - } else { - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); - } - - // Set eax to arguments count if adaption is not needed. Assumes that eax - // is available to write to at this point. - if (!function->NeedsArgumentsAdaption()) { - __ mov(eax, arity); - } + bool can_invoke_directly = !function->NeedsArgumentsAdaption() || + function->shared()->formal_parameter_count() == arity; LPointerMap* pointers = instr->pointer_map(); RecordPosition(pointers->position()); - // Invoke function. - __ SetCallKind(ecx, call_kind); - if (*function == *info()->closure()) { - __ CallSelf(); + if (can_invoke_directly) { + __ LoadHeapObject(edi, function); + + // Change context if needed. + bool change_context = + (info()->closure()->context() != function->context()) || + scope()->contains_with() || + (scope()->num_heap_slots() > 0); + + if (change_context) { + __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); + } else { + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); + } + + // Set eax to arguments count if adaption is not needed. Assumes that eax + // is available to write to at this point. + if (!function->NeedsArgumentsAdaption()) { + __ mov(eax, arity); + } + + // Invoke function directly. + __ SetCallKind(ecx, call_kind); + if (*function == *info()->closure()) { + __ CallSelf(); + } else { + __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset)); + } + RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); } else { - __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset)); + // We need to adapt arguments. + SafepointGenerator generator( + this, pointers, Safepoint::kLazyDeopt); + ParameterCount count(arity); + __ InvokeFunction(function, count, CALL_FUNCTION, generator, call_kind); } - - RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); } void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { ASSERT(ToRegister(instr->result()).is(eax)); - __ LoadHeapObject(edi, instr->function()); CallKnownFunction(instr->function(), instr->arity(), instr, @@ -3190,7 +3202,6 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) { void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { ASSERT(ToRegister(instr->result()).is(eax)); - __ LoadHeapObject(edi, instr->target()); CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION); } diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc index 36291ea..d0d9e19 100644 --- a/src/ia32/macro-assembler-ia32.cc +++ b/src/ia32/macro-assembler-ia32.cc @@ -1933,11 +1933,13 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, Handle code_constant, const Operand& code_operand, Label* done, + bool* definitely_mismatches, InvokeFlag flag, Label::Distance done_near, const CallWrapper& call_wrapper, CallKind call_kind) { bool definitely_matches = false; + *definitely_mismatches = false; Label invoke; if (expected.is_immediate()) { ASSERT(actual.is_immediate()); @@ -1953,6 +1955,7 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, // arguments. definitely_matches = true; } else { + *definitely_mismatches = true; mov(ebx, expected.immediate()); } } @@ -1990,7 +1993,9 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, SetCallKind(ecx, call_kind); call(adaptor, RelocInfo::CODE_TARGET); call_wrapper.AfterCall(); - jmp(done, done_near); + if (!*definitely_mismatches) { + jmp(done, done_near); + } } else { SetCallKind(ecx, call_kind); jmp(adaptor, RelocInfo::CODE_TARGET); @@ -2010,20 +2015,23 @@ void MacroAssembler::InvokeCode(const Operand& code, ASSERT(flag == JUMP_FUNCTION || has_frame()); Label done; + bool definitely_mismatches = false; InvokePrologue(expected, actual, Handle::null(), code, - &done, flag, Label::kNear, call_wrapper, - call_kind); - if (flag == CALL_FUNCTION) { - call_wrapper.BeforeCall(CallSize(code)); - SetCallKind(ecx, call_kind); - call(code); - call_wrapper.AfterCall(); - } else { - ASSERT(flag == JUMP_FUNCTION); - SetCallKind(ecx, call_kind); - jmp(code); + &done, &definitely_mismatches, flag, Label::kNear, + call_wrapper, call_kind); + if (!definitely_mismatches) { + if (flag == CALL_FUNCTION) { + call_wrapper.BeforeCall(CallSize(code)); + SetCallKind(ecx, call_kind); + call(code); + call_wrapper.AfterCall(); + } else { + ASSERT(flag == JUMP_FUNCTION); + SetCallKind(ecx, call_kind); + jmp(code); + } + bind(&done); } - bind(&done); } @@ -2039,19 +2047,22 @@ void MacroAssembler::InvokeCode(Handle code, Label done; Operand dummy(eax, 0); - InvokePrologue(expected, actual, code, dummy, &done, flag, Label::kNear, - call_wrapper, call_kind); - if (flag == CALL_FUNCTION) { - call_wrapper.BeforeCall(CallSize(code, rmode)); - SetCallKind(ecx, call_kind); - call(code, rmode); - call_wrapper.AfterCall(); - } else { - ASSERT(flag == JUMP_FUNCTION); - SetCallKind(ecx, call_kind); - jmp(code, rmode); + bool definitely_mismatches = false; + InvokePrologue(expected, actual, code, dummy, &done, &definitely_mismatches, + flag, Label::kNear, call_wrapper, call_kind); + if (!definitely_mismatches) { + if (flag == CALL_FUNCTION) { + call_wrapper.BeforeCall(CallSize(code, rmode)); + SetCallKind(ecx, call_kind); + call(code, rmode); + call_wrapper.AfterCall(); + } else { + ASSERT(flag == JUMP_FUNCTION); + SetCallKind(ecx, call_kind); + jmp(code, rmode); + } + bind(&done); } - bind(&done); } diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h index 2cb8743..0fcb94f 100644 --- a/src/ia32/macro-assembler-ia32.h +++ b/src/ia32/macro-assembler-ia32.h @@ -827,6 +827,7 @@ class MacroAssembler: public Assembler { Handle code_constant, const Operand& code_operand, Label* done, + bool* definitely_mismatches, InvokeFlag flag, Label::Distance done_distance, const CallWrapper& call_wrapper = NullCallWrapper(), diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 392c74d..291901e 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -2565,7 +2565,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { RecordPosition(pointers->position()); SafepointGenerator safepoint_generator( this, pointers, Safepoint::kLazyDeopt); - v8::internal::ParameterCount actual(rax); + ParameterCount actual(rax); __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator, CALL_AS_METHOD); __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); @@ -2615,35 +2615,48 @@ void LCodeGen::CallKnownFunction(Handle function, int arity, LInstruction* instr, CallKind call_kind) { - // Change context if needed. - bool change_context = - (info()->closure()->context() != function->context()) || - scope()->contains_with() || - (scope()->num_heap_slots() > 0); - if (change_context) { - __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); - } - - // Set rax to arguments count if adaption is not needed. Assumes that rax - // is available to write to at this point. - if (!function->NeedsArgumentsAdaption()) { - __ Set(rax, arity); - } + bool can_invoke_directly = !function->NeedsArgumentsAdaption() || + function->shared()->formal_parameter_count() == arity; LPointerMap* pointers = instr->pointer_map(); RecordPosition(pointers->position()); - // Invoke function. - __ SetCallKind(rcx, call_kind); - if (*function == *info()->closure()) { - __ CallSelf(); + if (can_invoke_directly) { + __ LoadHeapObject(rdi, function); + + // Change context if needed. + bool change_context = + (info()->closure()->context() != function->context()) || + scope()->contains_with() || + (scope()->num_heap_slots() > 0); + if (change_context) { + __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); + } + + // Set rax to arguments count if adaption is not needed. Assumes that rax + // is available to write to at this point. + if (!function->NeedsArgumentsAdaption()) { + __ Set(rax, arity); + } + + // Invoke function. + __ SetCallKind(rcx, call_kind); + if (*function == *info()->closure()) { + __ CallSelf(); + } else { + __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); + } + + // Set up deoptimization. + RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); } else { - __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); + // We need to adapt arguments. + SafepointGenerator generator( + this, pointers, Safepoint::kLazyDeopt); + ParameterCount count(arity); + __ InvokeFunction(function, count, CALL_FUNCTION, generator, call_kind); } - // Set up deoptimization. - RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); - // Restore context. __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); } @@ -2651,7 +2664,6 @@ void LCodeGen::CallKnownFunction(Handle function, void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { ASSERT(ToRegister(instr->result()).is(rax)); - __ LoadHeapObject(rdi, instr->function()); CallKnownFunction(instr->function(), instr->arity(), instr, @@ -3094,7 +3106,6 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) { void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { ASSERT(ToRegister(instr->result()).is(rax)); - __ LoadHeapObject(rdi, instr->target()); CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION); } diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc index 2f1c3fe..2d6bd08 100644 --- a/src/x64/macro-assembler-x64.cc +++ b/src/x64/macro-assembler-x64.cc @@ -3030,26 +3030,30 @@ void MacroAssembler::InvokeCode(Register code, ASSERT(flag == JUMP_FUNCTION || has_frame()); Label done; + bool definitely_mismatches = false; InvokePrologue(expected, actual, Handle::null(), code, &done, + &definitely_mismatches, flag, Label::kNear, call_wrapper, call_kind); - if (flag == CALL_FUNCTION) { - call_wrapper.BeforeCall(CallSize(code)); - SetCallKind(rcx, call_kind); - call(code); - call_wrapper.AfterCall(); - } else { - ASSERT(flag == JUMP_FUNCTION); - SetCallKind(rcx, call_kind); - jmp(code); + if (!definitely_mismatches) { + if (flag == CALL_FUNCTION) { + call_wrapper.BeforeCall(CallSize(code)); + SetCallKind(rcx, call_kind); + call(code); + call_wrapper.AfterCall(); + } else { + ASSERT(flag == JUMP_FUNCTION); + SetCallKind(rcx, call_kind); + jmp(code); + } + bind(&done); } - bind(&done); } @@ -3064,27 +3068,31 @@ void MacroAssembler::InvokeCode(Handle code, ASSERT(flag == JUMP_FUNCTION || has_frame()); Label done; + bool definitely_mismatches = false; Register dummy = rax; InvokePrologue(expected, actual, code, dummy, &done, + &definitely_mismatches, flag, Label::kNear, call_wrapper, call_kind); - if (flag == CALL_FUNCTION) { - call_wrapper.BeforeCall(CallSize(code)); - SetCallKind(rcx, call_kind); - Call(code, rmode); - call_wrapper.AfterCall(); - } else { - ASSERT(flag == JUMP_FUNCTION); - SetCallKind(rcx, call_kind); - Jump(code, rmode); + if (!definitely_mismatches) { + if (flag == CALL_FUNCTION) { + call_wrapper.BeforeCall(CallSize(code)); + SetCallKind(rcx, call_kind); + Call(code, rmode); + call_wrapper.AfterCall(); + } else { + ASSERT(flag == JUMP_FUNCTION); + SetCallKind(rcx, call_kind); + Jump(code, rmode); + } + bind(&done); } - bind(&done); } @@ -3136,11 +3144,13 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, Handle code_constant, Register code_register, Label* done, + bool* definitely_mismatches, InvokeFlag flag, Label::Distance near_jump, const CallWrapper& call_wrapper, CallKind call_kind) { bool definitely_matches = false; + *definitely_mismatches = false; Label invoke; if (expected.is_immediate()) { ASSERT(actual.is_immediate()); @@ -3156,6 +3166,7 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, // arguments. definitely_matches = true; } else { + *definitely_mismatches = true; Set(rbx, expected.immediate()); } } @@ -3192,7 +3203,9 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, SetCallKind(rcx, call_kind); Call(adaptor, RelocInfo::CODE_TARGET); call_wrapper.AfterCall(); - jmp(done, near_jump); + if (!*definitely_mismatches) { + jmp(done, near_jump); + } } else { SetCallKind(rcx, call_kind); Jump(adaptor, RelocInfo::CODE_TARGET); diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h index 09e4a06..aad76bc 100644 --- a/src/x64/macro-assembler-x64.h +++ b/src/x64/macro-assembler-x64.h @@ -1309,6 +1309,7 @@ class MacroAssembler: public Assembler { Handle code_constant, Register code_register, Label* done, + bool* definitely_mismatches, InvokeFlag flag, Label::Distance near_jump = Label::kFar, const CallWrapper& call_wrapper = NullCallWrapper(), -- 2.7.4