Commit 2ab3fcf4 authored by mvstanton's avatar mvstanton Committed by Commit bot

Record call counts also for megamorphic calls.

To make better inlining decisions, it's good to have call counts for poly/mega-morphic cases. This CL makes it work for calls, and another will follow to better unify the code between constructor calls and normal calls (and thence, to record megamorphic call counts there as well).

BUG=

Review-Url: https://codereview.chromium.org/2325083003
Cr-Commit-Position: refs/heads/master@{#39377}
parent 6b000846
...@@ -1785,6 +1785,17 @@ void CallConstructStub::Generate(MacroAssembler* masm) { ...@@ -1785,6 +1785,17 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
__ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
} }
// Note: feedback_vector and slot are clobbered after the call.
static void IncrementCallCount(MacroAssembler* masm, Register feedback_vector,
Register slot) {
__ add(feedback_vector, feedback_vector,
Operand::PointerOffsetFromSmiKey(slot));
__ add(feedback_vector, feedback_vector,
Operand(FixedArray::kHeaderSize + kPointerSize));
__ ldr(slot, FieldMemOperand(feedback_vector, 0));
__ add(slot, slot, Operand(Smi::FromInt(1)));
__ str(slot, FieldMemOperand(feedback_vector, 0));
}
void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
// r1 - function // r1 - function
...@@ -1798,11 +1809,7 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { ...@@ -1798,11 +1809,7 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
__ mov(r0, Operand(arg_count())); __ mov(r0, Operand(arg_count()));
// Increment the call count for monomorphic function calls. // Increment the call count for monomorphic function calls.
__ add(r2, r2, Operand::PointerOffsetFromSmiKey(r3)); IncrementCallCount(masm, r2, r3);
__ add(r2, r2, Operand(FixedArray::kHeaderSize + kPointerSize));
__ ldr(r3, FieldMemOperand(r2, 0));
__ add(r3, r3, Operand(Smi::FromInt(1)));
__ str(r3, FieldMemOperand(r2, 0));
__ mov(r2, r4); __ mov(r2, r4);
__ mov(r3, r1); __ mov(r3, r1);
...@@ -1815,7 +1822,7 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1815,7 +1822,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
// r1 - function // r1 - function
// r3 - slot id (Smi) // r3 - slot id (Smi)
// r2 - vector // r2 - vector
Label extra_checks_or_miss, call, call_function; Label extra_checks_or_miss, call, call_function, call_count_incremented;
int argc = arg_count(); int argc = arg_count();
ParameterCount actual(argc); ParameterCount actual(argc);
...@@ -1845,14 +1852,11 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1845,14 +1852,11 @@ void CallICStub::Generate(MacroAssembler* masm) {
// convincing us that we have a monomorphic JSFunction. // convincing us that we have a monomorphic JSFunction.
__ JumpIfSmi(r1, &extra_checks_or_miss); __ JumpIfSmi(r1, &extra_checks_or_miss);
__ bind(&call_function);
// Increment the call count for monomorphic function calls. // Increment the call count for monomorphic function calls.
__ add(r2, r2, Operand::PointerOffsetFromSmiKey(r3)); IncrementCallCount(masm, r2, r3);
__ add(r2, r2, Operand(FixedArray::kHeaderSize + kPointerSize));
__ ldr(r3, FieldMemOperand(r2, 0));
__ add(r3, r3, Operand(Smi::FromInt(1)));
__ str(r3, FieldMemOperand(r2, 0));
__ bind(&call_function);
__ mov(r0, Operand(argc)); __ mov(r0, Operand(argc));
__ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(), __ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(),
tail_call_mode()), tail_call_mode()),
...@@ -1893,6 +1897,11 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1893,6 +1897,11 @@ void CallICStub::Generate(MacroAssembler* masm) {
__ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize)); __ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize));
__ bind(&call); __ bind(&call);
// Increment the call count for megamorphic function calls.
IncrementCallCount(masm, r2, r3);
__ bind(&call_count_incremented);
__ mov(r0, Operand(argc)); __ mov(r0, Operand(argc));
__ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()), __ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
...@@ -1919,11 +1928,6 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1919,11 +1928,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
__ cmp(r4, ip); __ cmp(r4, ip);
__ b(ne, &miss); __ b(ne, &miss);
// Initialize the call counter.
__ Move(r5, Operand(Smi::FromInt(1)));
__ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
__ str(r5, FieldMemOperand(r4, FixedArray::kHeaderSize + kPointerSize));
// Store the function. Use a stub since we need a frame for allocation. // Store the function. Use a stub since we need a frame for allocation.
// r2 - vector // r2 - vector
// r3 - slot // r3 - slot
...@@ -1931,9 +1935,13 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1931,9 +1935,13 @@ void CallICStub::Generate(MacroAssembler* masm) {
{ {
FrameScope scope(masm, StackFrame::INTERNAL); FrameScope scope(masm, StackFrame::INTERNAL);
CreateWeakCellStub create_stub(masm->isolate()); CreateWeakCellStub create_stub(masm->isolate());
__ Push(r2);
__ Push(r3);
__ Push(cp, r1); __ Push(cp, r1);
__ CallStub(&create_stub); __ CallStub(&create_stub);
__ Pop(cp, r1); __ Pop(cp, r1);
__ Pop(r3);
__ Pop(r2);
} }
__ jmp(&call_function); __ jmp(&call_function);
...@@ -1943,7 +1951,7 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1943,7 +1951,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
__ bind(&miss); __ bind(&miss);
GenerateMiss(masm); GenerateMiss(masm);
__ jmp(&call); __ jmp(&call_count_incremented);
} }
......
...@@ -1995,6 +1995,17 @@ void CallConstructStub::Generate(MacroAssembler* masm) { ...@@ -1995,6 +1995,17 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
__ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
} }
// Note: feedback_vector and slot are clobbered after the call.
static void IncrementCallCount(MacroAssembler* masm, Register feedback_vector,
Register slot) {
__ Add(feedback_vector, feedback_vector,
Operand::UntagSmiAndScale(slot, kPointerSizeLog2));
__ Add(feedback_vector, feedback_vector,
Operand(FixedArray::kHeaderSize + kPointerSize));
__ Ldr(slot, FieldMemOperand(feedback_vector, 0));
__ Add(slot, slot, Operand(Smi::FromInt(1)));
__ Str(slot, FieldMemOperand(feedback_vector, 0));
}
void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
// x1 - function // x1 - function
...@@ -2014,13 +2025,7 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { ...@@ -2014,13 +2025,7 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
__ Mov(x0, Operand(arg_count())); __ Mov(x0, Operand(arg_count()));
// Increment the call count for monomorphic function calls. // Increment the call count for monomorphic function calls.
__ Add(feedback_vector, feedback_vector, IncrementCallCount(masm, feedback_vector, index);
Operand::UntagSmiAndScale(index, kPointerSizeLog2));
__ Add(feedback_vector, feedback_vector,
Operand(FixedArray::kHeaderSize + kPointerSize));
__ Ldr(index, FieldMemOperand(feedback_vector, 0));
__ Add(index, index, Operand(Smi::FromInt(1)));
__ Str(index, FieldMemOperand(feedback_vector, 0));
// Set up arguments for the array constructor stub. // Set up arguments for the array constructor stub.
Register allocation_site_arg = feedback_vector; Register allocation_site_arg = feedback_vector;
...@@ -2038,7 +2043,7 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2038,7 +2043,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
// x1 - function // x1 - function
// x3 - slot id (Smi) // x3 - slot id (Smi)
// x2 - vector // x2 - vector
Label extra_checks_or_miss, call, call_function; Label extra_checks_or_miss, call, call_function, call_count_incremented;
int argc = arg_count(); int argc = arg_count();
ParameterCount actual(argc); ParameterCount actual(argc);
...@@ -2073,16 +2078,11 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2073,16 +2078,11 @@ void CallICStub::Generate(MacroAssembler* masm) {
// convincing us that we have a monomorphic JSFunction. // convincing us that we have a monomorphic JSFunction.
__ JumpIfSmi(function, &extra_checks_or_miss); __ JumpIfSmi(function, &extra_checks_or_miss);
__ Bind(&call_function);
// Increment the call count for monomorphic function calls. // Increment the call count for monomorphic function calls.
__ Add(feedback_vector, feedback_vector, IncrementCallCount(masm, feedback_vector, index);
Operand::UntagSmiAndScale(index, kPointerSizeLog2));
__ Add(feedback_vector, feedback_vector,
Operand(FixedArray::kHeaderSize + kPointerSize));
__ Ldr(index, FieldMemOperand(feedback_vector, 0));
__ Add(index, index, Operand(Smi::FromInt(1)));
__ Str(index, FieldMemOperand(feedback_vector, 0));
__ Bind(&call_function);
__ Mov(x0, argc); __ Mov(x0, argc);
__ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(), __ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(),
tail_call_mode()), tail_call_mode()),
...@@ -2106,6 +2106,7 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2106,6 +2106,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
__ jmp(&miss); __ jmp(&miss);
} }
// TODO(mvstanton): the code below is effectively disabled. Investigate.
__ JumpIfRoot(x4, Heap::kuninitialized_symbolRootIndex, &miss); __ JumpIfRoot(x4, Heap::kuninitialized_symbolRootIndex, &miss);
// We are going megamorphic. If the feedback is a JSFunction, it is fine // We are going megamorphic. If the feedback is a JSFunction, it is fine
...@@ -2118,6 +2119,11 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2118,6 +2119,11 @@ void CallICStub::Generate(MacroAssembler* masm) {
__ Str(x5, FieldMemOperand(x4, FixedArray::kHeaderSize)); __ Str(x5, FieldMemOperand(x4, FixedArray::kHeaderSize));
__ Bind(&call); __ Bind(&call);
// Increment the call count for megamorphic function calls.
IncrementCallCount(masm, feedback_vector, index);
__ Bind(&call_count_incremented);
__ Mov(x0, argc); __ Mov(x0, argc);
__ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()), __ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
...@@ -2143,12 +2149,6 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2143,12 +2149,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
__ Cmp(x4, x5); __ Cmp(x4, x5);
__ B(ne, &miss); __ B(ne, &miss);
// Initialize the call counter.
__ Mov(x5, Smi::FromInt(1));
__ Adds(x4, feedback_vector,
Operand::UntagSmiAndScale(index, kPointerSizeLog2));
__ Str(x5, FieldMemOperand(x4, FixedArray::kHeaderSize + kPointerSize));
// Store the function. Use a stub since we need a frame for allocation. // Store the function. Use a stub since we need a frame for allocation.
// x2 - vector // x2 - vector
// x3 - slot // x3 - slot
...@@ -2156,9 +2156,13 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2156,9 +2156,13 @@ void CallICStub::Generate(MacroAssembler* masm) {
{ {
FrameScope scope(masm, StackFrame::INTERNAL); FrameScope scope(masm, StackFrame::INTERNAL);
CreateWeakCellStub create_stub(masm->isolate()); CreateWeakCellStub create_stub(masm->isolate());
__ Push(feedback_vector, index);
__ Push(cp, function); __ Push(cp, function);
__ CallStub(&create_stub); __ CallStub(&create_stub);
__ Pop(cp, function); __ Pop(cp, function);
__ Pop(feedback_vector, index);
} }
__ B(&call_function); __ B(&call_function);
...@@ -2168,7 +2172,8 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2168,7 +2172,8 @@ void CallICStub::Generate(MacroAssembler* masm) {
__ bind(&miss); __ bind(&miss);
GenerateMiss(masm); GenerateMiss(masm);
__ B(&call); // The runtime increments the call count in the vector for us.
__ B(&call_count_incremented);
} }
......
...@@ -1431,6 +1431,12 @@ void CallConstructStub::Generate(MacroAssembler* masm) { ...@@ -1431,6 +1431,12 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
__ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
} }
static void IncrementCallCount(MacroAssembler* masm, Register feedback_vector,
Register slot) {
__ add(FieldOperand(feedback_vector, slot, times_half_pointer_size,
FixedArray::kHeaderSize + kPointerSize),
Immediate(Smi::FromInt(1)));
}
void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
// edi - function // edi - function
...@@ -1446,9 +1452,7 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { ...@@ -1446,9 +1452,7 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
FixedArray::kHeaderSize)); FixedArray::kHeaderSize));
// Increment the call count for monomorphic function calls. // Increment the call count for monomorphic function calls.
__ add(FieldOperand(ebx, edx, times_half_pointer_size, IncrementCallCount(masm, ebx, edx);
FixedArray::kHeaderSize + kPointerSize),
Immediate(Smi::FromInt(1)));
__ mov(ebx, ecx); __ mov(ebx, ecx);
__ mov(edx, edi); __ mov(edx, edi);
...@@ -1464,7 +1468,7 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1464,7 +1468,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
// edx - slot id // edx - slot id
// ebx - vector // ebx - vector
Isolate* isolate = masm->isolate(); Isolate* isolate = masm->isolate();
Label extra_checks_or_miss, call, call_function; Label extra_checks_or_miss, call, call_function, call_count_incremented;
int argc = arg_count(); int argc = arg_count();
ParameterCount actual(argc); ParameterCount actual(argc);
...@@ -1493,12 +1497,11 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1493,12 +1497,11 @@ void CallICStub::Generate(MacroAssembler* masm) {
// convincing us that we have a monomorphic JSFunction. // convincing us that we have a monomorphic JSFunction.
__ JumpIfSmi(edi, &extra_checks_or_miss); __ JumpIfSmi(edi, &extra_checks_or_miss);
__ bind(&call_function);
// Increment the call count for monomorphic function calls. // Increment the call count for monomorphic function calls.
__ add(FieldOperand(ebx, edx, times_half_pointer_size, IncrementCallCount(masm, ebx, edx);
FixedArray::kHeaderSize + kPointerSize),
Immediate(Smi::FromInt(1)));
__ bind(&call_function);
__ Set(eax, argc); __ Set(eax, argc);
__ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(), __ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(),
tail_call_mode()), tail_call_mode()),
...@@ -1539,6 +1542,12 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1539,6 +1542,12 @@ void CallICStub::Generate(MacroAssembler* masm) {
Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate)));
__ bind(&call); __ bind(&call);
// Increment the call count for megamorphic function calls.
IncrementCallCount(masm, ebx, edx);
__ bind(&call_count_incremented);
__ Set(eax, argc); __ Set(eax, argc);
__ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()), __ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
...@@ -1564,11 +1573,6 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1564,11 +1573,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
__ cmp(ecx, NativeContextOperand()); __ cmp(ecx, NativeContextOperand());
__ j(not_equal, &miss); __ j(not_equal, &miss);
// Initialize the call counter.
__ mov(FieldOperand(ebx, edx, times_half_pointer_size,
FixedArray::kHeaderSize + kPointerSize),
Immediate(Smi::FromInt(1)));
// Store the function. Use a stub since we need a frame for allocation. // Store the function. Use a stub since we need a frame for allocation.
// ebx - vector // ebx - vector
// edx - slot // edx - slot
...@@ -1576,11 +1580,15 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1576,11 +1580,15 @@ void CallICStub::Generate(MacroAssembler* masm) {
{ {
FrameScope scope(masm, StackFrame::INTERNAL); FrameScope scope(masm, StackFrame::INTERNAL);
CreateWeakCellStub create_stub(isolate); CreateWeakCellStub create_stub(isolate);
__ push(ebx);
__ push(edx);
__ push(edi); __ push(edi);
__ push(esi); __ push(esi);
__ CallStub(&create_stub); __ CallStub(&create_stub);
__ pop(esi); __ pop(esi);
__ pop(edi); __ pop(edi);
__ pop(edx);
__ pop(ebx);
} }
__ jmp(&call_function); __ jmp(&call_function);
...@@ -1590,7 +1598,7 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1590,7 +1598,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
__ bind(&miss); __ bind(&miss);
GenerateMiss(masm); GenerateMiss(masm);
__ jmp(&call); __ jmp(&call_count_incremented);
// Unreachable // Unreachable
__ int3(); __ int3();
......
...@@ -460,6 +460,17 @@ void InterpreterAssembler::CallEpilogue() { ...@@ -460,6 +460,17 @@ void InterpreterAssembler::CallEpilogue() {
} }
} }
Node* InterpreterAssembler::IncrementCallCount(Node* type_feedback_vector,
Node* slot_id) {
Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1));
Node* call_count =
LoadFixedArrayElement(type_feedback_vector, call_count_slot);
Node* new_count = SmiAdd(call_count, SmiTag(Int32Constant(1)));
// Count is Smi, so we don't need a write barrier.
return StoreFixedArrayElement(type_feedback_vector, call_count_slot,
new_count, SKIP_WRITE_BARRIER);
}
Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context,
Node* first_arg, Node* arg_count, Node* first_arg, Node* arg_count,
Node* slot_id, Node* slot_id,
...@@ -482,13 +493,13 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, ...@@ -482,13 +493,13 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context,
Variable return_value(this, MachineRepresentation::kTagged); Variable return_value(this, MachineRepresentation::kTagged);
Label handle_monomorphic(this), extra_checks(this), end(this), call(this), Label handle_monomorphic(this), extra_checks(this), end(this), call(this),
call_function(this); call_function(this), call_without_feedback(this);
// Slot id of 0 is used to indicate no typefeedback is available. Call using // Slot id of 0 is used to indicate no typefeedback is available. Call using
// call builtin. // call builtin.
STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0); STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0);
Node* is_feedback_unavailable = Word32Equal(slot_id, Int32Constant(0)); Node* is_feedback_unavailable = Word32Equal(slot_id, Int32Constant(0));
GotoIf(is_feedback_unavailable, &call); GotoIf(is_feedback_unavailable, &call_without_feedback);
// The checks. First, does function match the recorded monomorphic target? // The checks. First, does function match the recorded monomorphic target?
Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id); Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id);
...@@ -504,13 +515,7 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, ...@@ -504,13 +515,7 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context,
GotoIf(is_smi, &extra_checks); GotoIf(is_smi, &extra_checks);
// Increment the call count. // Increment the call count.
Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1)); IncrementCallCount(type_feedback_vector, slot_id);
Node* call_count =
LoadFixedArrayElement(type_feedback_vector, call_count_slot);
Node* new_count = SmiAdd(call_count, SmiTag(Int32Constant(1)));
// Count is Smi, so we don't need a write barrier.
StoreFixedArrayElement(type_feedback_vector, call_count_slot, new_count,
SKIP_WRITE_BARRIER);
// Call using call function builtin. // Call using call function builtin.
Callable callable = CodeFactory::InterpreterPushArgsAndCall( Callable callable = CodeFactory::InterpreterPushArgsAndCall(
...@@ -548,13 +553,7 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, ...@@ -548,13 +553,7 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context,
GotoUnless(is_array_function, &mark_megamorphic); GotoUnless(is_array_function, &mark_megamorphic);
// It is a monomorphic Array function. Increment the call count. // It is a monomorphic Array function. Increment the call count.
Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1)); IncrementCallCount(type_feedback_vector, slot_id);
Node* call_count =
LoadFixedArrayElement(type_feedback_vector, call_count_slot);
Node* new_count = SmiAdd(call_count, SmiTag(Int32Constant(1)));
// Count is Smi, so we don't need a write barrier.
StoreFixedArrayElement(type_feedback_vector, call_count_slot, new_count,
SKIP_WRITE_BARRIER);
// Call ArrayConstructorStub. // Call ArrayConstructorStub.
Callable callable_call = Callable callable_call =
...@@ -599,12 +598,6 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, ...@@ -599,12 +598,6 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context,
WordEqual(native_context, LoadNativeContext(context)); WordEqual(native_context, LoadNativeContext(context));
GotoUnless(is_same_native_context, &mark_megamorphic); GotoUnless(is_same_native_context, &mark_megamorphic);
// Initialize it to a monomorphic target.
Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1));
// Count is Smi, so we don't need a write barrier.
StoreFixedArrayElement(type_feedback_vector, call_count_slot,
SmiTag(Int32Constant(1)), SKIP_WRITE_BARRIER);
CreateWeakCellInFeedbackVector(type_feedback_vector, SmiTag(slot_id), CreateWeakCellInFeedbackVector(type_feedback_vector, SmiTag(slot_id),
function); function);
...@@ -620,12 +613,6 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, ...@@ -620,12 +613,6 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context,
HeapConstant(create_stub.GetCode()), context, HeapConstant(create_stub.GetCode()), context,
type_feedback_vector, SmiTag(slot_id)); type_feedback_vector, SmiTag(slot_id));
// Initialize the count to 1.
Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1));
// Count is Smi, so we don't need a write barrier.
StoreFixedArrayElement(type_feedback_vector, call_count_slot,
SmiTag(Int32Constant(1)), SKIP_WRITE_BARRIER);
// Call using CallFunction builtin. CallICs have a PREMONOMORPHIC state. // Call using CallFunction builtin. CallICs have a PREMONOMORPHIC state.
// They start collecting feedback only when a call is executed the second // They start collecting feedback only when a call is executed the second
// time. So, do not pass any feedback here. // time. So, do not pass any feedback here.
...@@ -648,6 +635,9 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, ...@@ -648,6 +635,9 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context,
Bind(&call_function); Bind(&call_function);
{ {
// Increment the call count.
IncrementCallCount(type_feedback_vector, slot_id);
Callable callable_call = CodeFactory::InterpreterPushArgsAndCall( Callable callable_call = CodeFactory::InterpreterPushArgsAndCall(
isolate(), tail_call_mode, CallableType::kJSFunction); isolate(), tail_call_mode, CallableType::kJSFunction);
Node* code_target_call = HeapConstant(callable_call.code()); Node* code_target_call = HeapConstant(callable_call.code());
...@@ -658,6 +648,21 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, ...@@ -658,6 +648,21 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context,
} }
Bind(&call); Bind(&call);
{
// Increment the call count.
IncrementCallCount(type_feedback_vector, slot_id);
// Call using call builtin.
Callable callable_call = CodeFactory::InterpreterPushArgsAndCall(
isolate(), tail_call_mode, CallableType::kAny);
Node* code_target_call = HeapConstant(callable_call.code());
Node* ret_value = CallStub(callable_call.descriptor(), code_target_call,
context, arg_count, first_arg, function);
return_value.Bind(ret_value);
Goto(&end);
}
Bind(&call_without_feedback);
{ {
// Call using call builtin. // Call using call builtin.
Callable callable_call = CodeFactory::InterpreterPushArgsAndCall( Callable callable_call = CodeFactory::InterpreterPushArgsAndCall(
......
...@@ -92,6 +92,11 @@ class InterpreterAssembler : public CodeStubAssembler { ...@@ -92,6 +92,11 @@ class InterpreterAssembler : public CodeStubAssembler {
// Load the TypeFeedbackVector for the current function. // Load the TypeFeedbackVector for the current function.
compiler::Node* LoadTypeFeedbackVector(); compiler::Node* LoadTypeFeedbackVector();
// Increment the call count for a CALL_IC or construct call.
// The call count is located at feedback_vector[slot_id + 1].
compiler::Node* IncrementCallCount(compiler::Node* type_feedback_vector,
compiler::Node* slot_id);
// Call JSFunction or Callable |function| with |arg_count| // Call JSFunction or Callable |function| with |arg_count|
// arguments (not including receiver) and the first argument // arguments (not including receiver) and the first argument
// located at |first_arg|. Type feedback is collected in the // located at |first_arg|. Type feedback is collected in the
......
...@@ -1917,6 +1917,14 @@ void CallConstructStub::Generate(MacroAssembler* masm) { ...@@ -1917,6 +1917,14 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
__ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
} }
// Note: feedback_vector and slot are clobbered after the call.
static void IncrementCallCount(MacroAssembler* masm, Register feedback_vector,
Register slot) {
__ Lsa(at, feedback_vector, slot, kPointerSizeLog2 - kSmiTagSize);
__ lw(slot, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
__ Addu(slot, slot, Operand(Smi::FromInt(1)));
__ sw(slot, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
}
void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
// a1 - function // a1 - function
...@@ -1929,10 +1937,7 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { ...@@ -1929,10 +1937,7 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
__ li(a0, Operand(arg_count())); __ li(a0, Operand(arg_count()));
// Increment the call count for monomorphic function calls. // Increment the call count for monomorphic function calls.
__ Lsa(at, a2, a3, kPointerSizeLog2 - kSmiTagSize); IncrementCallCount(masm, a2, a3);
__ lw(a3, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
__ Addu(a3, a3, Operand(Smi::FromInt(1)));
__ sw(a3, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
__ mov(a2, t0); __ mov(a2, t0);
__ mov(a3, a1); __ mov(a3, a1);
...@@ -1945,7 +1950,7 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1945,7 +1950,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
// a1 - function // a1 - function
// a3 - slot id (Smi) // a3 - slot id (Smi)
// a2 - vector // a2 - vector
Label extra_checks_or_miss, call, call_function; Label extra_checks_or_miss, call, call_function, call_count_incremented;
int argc = arg_count(); int argc = arg_count();
ParameterCount actual(argc); ParameterCount actual(argc);
...@@ -1974,13 +1979,11 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1974,13 +1979,11 @@ void CallICStub::Generate(MacroAssembler* masm) {
// convincing us that we have a monomorphic JSFunction. // convincing us that we have a monomorphic JSFunction.
__ JumpIfSmi(a1, &extra_checks_or_miss); __ JumpIfSmi(a1, &extra_checks_or_miss);
__ bind(&call_function);
// Increment the call count for monomorphic function calls. // Increment the call count for monomorphic function calls.
__ Lsa(at, a2, a3, kPointerSizeLog2 - kSmiTagSize); IncrementCallCount(masm, a2, a3);
__ lw(a3, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
__ Addu(a3, a3, Operand(Smi::FromInt(1)));
__ sw(a3, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
__ bind(&call_function);
__ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(), __ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(),
tail_call_mode()), tail_call_mode()),
RelocInfo::CODE_TARGET, al, zero_reg, Operand(zero_reg), RelocInfo::CODE_TARGET, al, zero_reg, Operand(zero_reg),
...@@ -2021,6 +2024,10 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2021,6 +2024,10 @@ void CallICStub::Generate(MacroAssembler* masm) {
__ sw(at, FieldMemOperand(t0, FixedArray::kHeaderSize)); __ sw(at, FieldMemOperand(t0, FixedArray::kHeaderSize));
__ bind(&call); __ bind(&call);
IncrementCallCount(masm, a2, a3);
__ bind(&call_count_incremented);
__ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()), __ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()),
RelocInfo::CODE_TARGET, al, zero_reg, Operand(zero_reg), RelocInfo::CODE_TARGET, al, zero_reg, Operand(zero_reg),
USE_DELAY_SLOT); USE_DELAY_SLOT);
...@@ -2046,11 +2053,6 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2046,11 +2053,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
__ lw(t1, NativeContextMemOperand()); __ lw(t1, NativeContextMemOperand());
__ Branch(&miss, ne, t0, Operand(t1)); __ Branch(&miss, ne, t0, Operand(t1));
// Initialize the call counter.
__ Lsa(at, a2, a3, kPointerSizeLog2 - kSmiTagSize);
__ li(t0, Operand(Smi::FromInt(1)));
__ sw(t0, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
// Store the function. Use a stub since we need a frame for allocation. // Store the function. Use a stub since we need a frame for allocation.
// a2 - vector // a2 - vector
// a3 - slot // a3 - slot
...@@ -2058,9 +2060,11 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2058,9 +2060,11 @@ void CallICStub::Generate(MacroAssembler* masm) {
{ {
FrameScope scope(masm, StackFrame::INTERNAL); FrameScope scope(masm, StackFrame::INTERNAL);
CreateWeakCellStub create_stub(masm->isolate()); CreateWeakCellStub create_stub(masm->isolate());
__ Push(a2, a3);
__ Push(cp, a1); __ Push(cp, a1);
__ CallStub(&create_stub); __ CallStub(&create_stub);
__ Pop(cp, a1); __ Pop(cp, a1);
__ Pop(a2, a3);
} }
__ Branch(&call_function); __ Branch(&call_function);
...@@ -2070,7 +2074,7 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2070,7 +2074,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
__ bind(&miss); __ bind(&miss);
GenerateMiss(masm); GenerateMiss(masm);
__ Branch(&call); __ Branch(&call_count_incremented);
} }
......
...@@ -1965,6 +1965,15 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { ...@@ -1965,6 +1965,15 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
__ bind(&exit_); __ bind(&exit_);
} }
// Note: feedback_vector and slot are clobbered after the call.
static void IncrementCallCount(MacroAssembler* masm, Register feedback_vector,
Register slot) {
__ dsrl(t0, slot, 32 - kPointerSizeLog2);
__ Daddu(slot, feedback_vector, Operand(t0));
__ ld(t0, FieldMemOperand(slot, FixedArray::kHeaderSize + kPointerSize));
__ Daddu(t0, t0, Operand(Smi::FromInt(1)));
__ sd(t0, FieldMemOperand(slot, FixedArray::kHeaderSize + kPointerSize));
}
void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
// a1 - function // a1 - function
...@@ -1977,11 +1986,7 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { ...@@ -1977,11 +1986,7 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
__ li(a0, Operand(arg_count())); __ li(a0, Operand(arg_count()));
// Increment the call count for monomorphic function calls. // Increment the call count for monomorphic function calls.
__ dsrl(t0, a3, 32 - kPointerSizeLog2); IncrementCallCount(masm, a2, a3);
__ Daddu(a3, a2, Operand(t0));
__ ld(t0, FieldMemOperand(a3, FixedArray::kHeaderSize + kPointerSize));
__ Daddu(t0, t0, Operand(Smi::FromInt(1)));
__ sd(t0, FieldMemOperand(a3, FixedArray::kHeaderSize + kPointerSize));
__ mov(a2, a4); __ mov(a2, a4);
__ mov(a3, a1); __ mov(a3, a1);
...@@ -1994,7 +1999,7 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1994,7 +1999,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
// a1 - function // a1 - function
// a3 - slot id (Smi) // a3 - slot id (Smi)
// a2 - vector // a2 - vector
Label extra_checks_or_miss, call, call_function; Label extra_checks_or_miss, call, call_function, call_count_incremented;
int argc = arg_count(); int argc = arg_count();
ParameterCount actual(argc); ParameterCount actual(argc);
...@@ -2024,14 +2029,10 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2024,14 +2029,10 @@ void CallICStub::Generate(MacroAssembler* masm) {
// convincing us that we have a monomorphic JSFunction. // convincing us that we have a monomorphic JSFunction.
__ JumpIfSmi(a1, &extra_checks_or_miss); __ JumpIfSmi(a1, &extra_checks_or_miss);
__ bind(&call_function);
// Increment the call count for monomorphic function calls. // Increment the call count for monomorphic function calls.
__ dsrl(t0, a3, 32 - kPointerSizeLog2); IncrementCallCount(masm, a2, a3);
__ Daddu(a3, a2, Operand(t0));
__ ld(t0, FieldMemOperand(a3, FixedArray::kHeaderSize + kPointerSize));
__ Daddu(t0, t0, Operand(Smi::FromInt(1)));
__ sd(t0, FieldMemOperand(a3, FixedArray::kHeaderSize + kPointerSize));
__ bind(&call_function);
__ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(), __ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(),
tail_call_mode()), tail_call_mode()),
RelocInfo::CODE_TARGET, al, zero_reg, Operand(zero_reg), RelocInfo::CODE_TARGET, al, zero_reg, Operand(zero_reg),
...@@ -2073,6 +2074,10 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2073,6 +2074,10 @@ void CallICStub::Generate(MacroAssembler* masm) {
__ sd(at, FieldMemOperand(a4, FixedArray::kHeaderSize)); __ sd(at, FieldMemOperand(a4, FixedArray::kHeaderSize));
__ bind(&call); __ bind(&call);
IncrementCallCount(masm, a2, a3);
__ bind(&call_count_incremented);
__ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()), __ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()),
RelocInfo::CODE_TARGET, al, zero_reg, Operand(zero_reg), RelocInfo::CODE_TARGET, al, zero_reg, Operand(zero_reg),
USE_DELAY_SLOT); USE_DELAY_SLOT);
...@@ -2098,12 +2103,6 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2098,12 +2103,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
__ ld(t1, NativeContextMemOperand()); __ ld(t1, NativeContextMemOperand());
__ Branch(&miss, ne, t0, Operand(t1)); __ Branch(&miss, ne, t0, Operand(t1));
// Initialize the call counter.
__ dsrl(at, a3, 32 - kPointerSizeLog2);
__ Daddu(at, a2, Operand(at));
__ li(t0, Operand(Smi::FromInt(1)));
__ sd(t0, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
// Store the function. Use a stub since we need a frame for allocation. // Store the function. Use a stub since we need a frame for allocation.
// a2 - vector // a2 - vector
// a3 - slot // a3 - slot
...@@ -2111,9 +2110,11 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2111,9 +2110,11 @@ void CallICStub::Generate(MacroAssembler* masm) {
{ {
FrameScope scope(masm, StackFrame::INTERNAL); FrameScope scope(masm, StackFrame::INTERNAL);
CreateWeakCellStub create_stub(masm->isolate()); CreateWeakCellStub create_stub(masm->isolate());
__ Push(a2, a3);
__ Push(cp, a1); __ Push(cp, a1);
__ CallStub(&create_stub); __ CallStub(&create_stub);
__ Pop(cp, a1); __ Pop(cp, a1);
__ Pop(a2, a3);
} }
__ Branch(&call_function); __ Branch(&call_function);
...@@ -2123,7 +2124,7 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2123,7 +2124,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
__ bind(&miss); __ bind(&miss);
GenerateMiss(masm); GenerateMiss(masm);
__ Branch(&call); __ Branch(&call_count_incremented);
} }
......
...@@ -254,8 +254,11 @@ Handle<TypeFeedbackVector> TypeFeedbackVector::New( ...@@ -254,8 +254,11 @@ Handle<TypeFeedbackVector> TypeFeedbackVector::New(
value = *uninitialized_sentinel; value = *uninitialized_sentinel;
} }
array->set(index, value, SKIP_WRITE_BARRIER); array->set(index, value, SKIP_WRITE_BARRIER);
value = kind == FeedbackVectorSlotKind::CALL_IC ? Smi::FromInt(0)
: *uninitialized_sentinel;
for (int j = 1; j < entry_size; j++) { for (int j = 1; j < entry_size; j++) {
array->set(index + j, *uninitialized_sentinel, SKIP_WRITE_BARRIER); array->set(index + j, value, SKIP_WRITE_BARRIER);
} }
i += entry_size; i += entry_size;
} }
...@@ -620,16 +623,19 @@ InlineCacheState CallICNexus::StateFromFeedback() const { ...@@ -620,16 +623,19 @@ InlineCacheState CallICNexus::StateFromFeedback() const {
int CallICNexus::ExtractCallCount() { int CallICNexus::ExtractCallCount() {
Object* call_count = GetFeedbackExtra(); Object* call_count = GetFeedbackExtra();
if (call_count->IsSmi()) { CHECK(call_count->IsSmi());
int value = Smi::cast(call_count)->value(); int value = Smi::cast(call_count)->value();
return value; return value;
}
return -1;
} }
void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); } void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); }
void CallICNexus::ConfigureUninitialized() {
Isolate* isolate = GetIsolate();
SetFeedback(*TypeFeedbackVector::UninitializedSentinel(isolate),
SKIP_WRITE_BARRIER);
SetFeedbackExtra(Smi::FromInt(0), SKIP_WRITE_BARRIER);
}
void CallICNexus::ConfigureMonomorphicArray() { void CallICNexus::ConfigureMonomorphicArray() {
Object* feedback = GetFeedback(); Object* feedback = GetFeedback();
...@@ -650,10 +656,13 @@ void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) { ...@@ -650,10 +656,13 @@ void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) {
void CallICNexus::ConfigureMegamorphic() { void CallICNexus::ConfigureMegamorphic() {
FeedbackNexus::ConfigureMegamorphic(); SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()),
SKIP_WRITE_BARRIER);
Smi* count = Smi::cast(GetFeedbackExtra());
int new_count = count->value() + 1;
SetFeedbackExtra(Smi::FromInt(new_count), SKIP_WRITE_BARRIER);
} }
void CallICNexus::ConfigureMegamorphic(int call_count) { void CallICNexus::ConfigureMegamorphic(int call_count) {
SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()), SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()),
SKIP_WRITE_BARRIER); SKIP_WRITE_BARRIER);
......
...@@ -459,6 +459,7 @@ class CallICNexus final : public FeedbackNexus { ...@@ -459,6 +459,7 @@ class CallICNexus final : public FeedbackNexus {
void Clear(Code* host); void Clear(Code* host);
void ConfigureUninitialized() override;
void ConfigureMonomorphicArray(); void ConfigureMonomorphicArray();
void ConfigureMonomorphic(Handle<JSFunction> function); void ConfigureMonomorphic(Handle<JSFunction> function);
void ConfigureMegamorphic() final; void ConfigureMegamorphic() final;
......
...@@ -1321,6 +1321,12 @@ void CallConstructStub::Generate(MacroAssembler* masm) { ...@@ -1321,6 +1321,12 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
__ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
} }
static void IncrementCallCount(MacroAssembler* masm, Register feedback_vector,
Register slot) {
__ SmiAddConstant(FieldOperand(feedback_vector, slot, times_pointer_size,
FixedArray::kHeaderSize + kPointerSize),
Smi::FromInt(1));
}
void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
// rdi - function // rdi - function
...@@ -1334,9 +1340,7 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { ...@@ -1334,9 +1340,7 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
__ movp(rax, Immediate(arg_count())); __ movp(rax, Immediate(arg_count()));
// Increment the call count for monomorphic function calls. // Increment the call count for monomorphic function calls.
__ SmiAddConstant(FieldOperand(rbx, rdx, times_pointer_size, IncrementCallCount(masm, rbx, rdx);
FixedArray::kHeaderSize + kPointerSize),
Smi::FromInt(1));
__ movp(rbx, rcx); __ movp(rbx, rcx);
__ movp(rdx, rdi); __ movp(rdx, rdi);
...@@ -1352,7 +1356,7 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1352,7 +1356,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
// -- rbx - vector // -- rbx - vector
// ----------------------------------- // -----------------------------------
Isolate* isolate = masm->isolate(); Isolate* isolate = masm->isolate();
Label extra_checks_or_miss, call, call_function; Label extra_checks_or_miss, call, call_function, call_count_incremented;
int argc = arg_count(); int argc = arg_count();
StackArgumentsAccessor args(rsp, argc); StackArgumentsAccessor args(rsp, argc);
ParameterCount actual(argc); ParameterCount actual(argc);
...@@ -1383,12 +1387,10 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1383,12 +1387,10 @@ void CallICStub::Generate(MacroAssembler* masm) {
// convincing us that we have a monomorphic JSFunction. // convincing us that we have a monomorphic JSFunction.
__ JumpIfSmi(rdi, &extra_checks_or_miss); __ JumpIfSmi(rdi, &extra_checks_or_miss);
__ bind(&call_function);
// Increment the call count for monomorphic function calls. // Increment the call count for monomorphic function calls.
__ SmiAddConstant(FieldOperand(rbx, rdx, times_pointer_size, IncrementCallCount(masm, rbx, rdx);
FixedArray::kHeaderSize + kPointerSize),
Smi::FromInt(1));
__ bind(&call_function);
__ Set(rax, argc); __ Set(rax, argc);
__ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(), __ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(),
tail_call_mode()), tail_call_mode()),
...@@ -1428,6 +1430,11 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1428,6 +1430,11 @@ void CallICStub::Generate(MacroAssembler* masm) {
TypeFeedbackVector::MegamorphicSentinel(isolate)); TypeFeedbackVector::MegamorphicSentinel(isolate));
__ bind(&call); __ bind(&call);
// Increment the call count for megamorphic function calls.
IncrementCallCount(masm, rbx, rdx);
__ bind(&call_count_incremented);
__ Set(rax, argc); __ Set(rax, argc);
__ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()), __ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
...@@ -1453,11 +1460,6 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1453,11 +1460,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
__ cmpp(rcx, NativeContextOperand()); __ cmpp(rcx, NativeContextOperand());
__ j(not_equal, &miss); __ j(not_equal, &miss);
// Initialize the call counter.
__ Move(FieldOperand(rbx, rdx, times_pointer_size,
FixedArray::kHeaderSize + kPointerSize),
Smi::FromInt(1));
// Store the function. Use a stub since we need a frame for allocation. // Store the function. Use a stub since we need a frame for allocation.
// rbx - vector // rbx - vector
// rdx - slot (needs to be in smi form) // rdx - slot (needs to be in smi form)
...@@ -1467,11 +1469,16 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1467,11 +1469,16 @@ void CallICStub::Generate(MacroAssembler* masm) {
CreateWeakCellStub create_stub(isolate); CreateWeakCellStub create_stub(isolate);
__ Integer32ToSmi(rdx, rdx); __ Integer32ToSmi(rdx, rdx);
__ Push(rbx);
__ Push(rdx);
__ Push(rdi); __ Push(rdi);
__ Push(rsi); __ Push(rsi);
__ CallStub(&create_stub); __ CallStub(&create_stub);
__ Pop(rsi); __ Pop(rsi);
__ Pop(rdi); __ Pop(rdi);
__ Pop(rdx);
__ Pop(rbx);
__ SmiToInteger32(rdx, rdx);
} }
__ jmp(&call_function); __ jmp(&call_function);
...@@ -1481,20 +1488,19 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -1481,20 +1488,19 @@ void CallICStub::Generate(MacroAssembler* masm) {
__ bind(&miss); __ bind(&miss);
GenerateMiss(masm); GenerateMiss(masm);
__ jmp(&call); __ jmp(&call_count_incremented);
// Unreachable // Unreachable
__ int3(); __ int3();
} }
void CallICStub::GenerateMiss(MacroAssembler* masm) { void CallICStub::GenerateMiss(MacroAssembler* masm) {
FrameScope scope(masm, StackFrame::INTERNAL); FrameScope scope(masm, StackFrame::INTERNAL);
// Push the receiver and the function and feedback info. // Push the receiver and the function and feedback info.
__ Integer32ToSmi(rdx, rdx);
__ Push(rdi); __ Push(rdi);
__ Push(rbx); __ Push(rbx);
__ Integer32ToSmi(rdx, rdx);
__ Push(rdx); __ Push(rdx);
// Call the entry. // Call the entry.
...@@ -1504,7 +1510,6 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) { ...@@ -1504,7 +1510,6 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) {
__ movp(rdi, rax); __ movp(rdi, rax);
} }
bool CEntryStub::NeedsImmovableCode() { bool CEntryStub::NeedsImmovableCode() {
return false; return false;
} }
......
...@@ -269,6 +269,11 @@ TEST(VectorCallCounts) { ...@@ -269,6 +269,11 @@ TEST(VectorCallCounts) {
CompileRun("f(foo); f(foo);"); CompileRun("f(foo); f(foo);");
CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
CHECK_EQ(3, nexus.ExtractCallCount()); CHECK_EQ(3, nexus.ExtractCallCount());
// Send the IC megamorphic, but we should still have incrementing counts.
CompileRun("f(function() { return 12; });");
CHECK_EQ(GENERIC, nexus.StateFromFeedback());
CHECK_EQ(4, nexus.ExtractCallCount());
} }
TEST(VectorConstructCounts) { TEST(VectorConstructCounts) {
......
...@@ -30,7 +30,7 @@ function __f_3(x) { ...@@ -30,7 +30,7 @@ function __f_3(x) {
var __v_1 = arguments; var __v_1 = arguments;
__v_1[1000] = 123; __v_1[1000] = 123;
depth++; depth++;
if (depth > 2500) return; if (depth > 2400) return;
function __f_4() { function __f_4() {
++__v_1[0]; ++__v_1[0];
__f_3(0.5); __f_3(0.5);
......
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