MIPS: Try avoiding MISS for callic monomorphic case.

Port c01061044028f7a31ba51496e44900481005eb38
Port r25207

BUG=
R=mvstanton@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#25218}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25218 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 9e555db8
...@@ -2829,8 +2829,12 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) { ...@@ -2829,8 +2829,12 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
void CallICStub::Generate(MacroAssembler* masm) { void CallICStub::Generate(MacroAssembler* masm) {
// r1 - function // a1 - function
// r3 - slot id (Smi) // a3 - slot id (Smi)
const int with_types_offset =
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex);
const int generic_offset =
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex);
Label extra_checks_or_miss, slow_start; Label extra_checks_or_miss, slow_start;
Label slow, non_function, wrap, cont; Label slow, non_function, wrap, cont;
Label have_js_function; Label have_js_function;
...@@ -2869,38 +2873,71 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2869,38 +2873,71 @@ void CallICStub::Generate(MacroAssembler* masm) {
} }
__ bind(&extra_checks_or_miss); __ bind(&extra_checks_or_miss);
Label miss; Label uninitialized, miss;
__ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex); __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
__ Branch(&slow_start, eq, t0, Operand(at)); __ Branch(&slow_start, eq, t0, Operand(at));
__ LoadRoot(at, Heap::kuninitialized_symbolRootIndex);
__ Branch(&miss, eq, t0, Operand(at)); // The following cases attempt to handle MISS cases without going to the
// runtime.
if (!FLAG_trace_ic) { if (FLAG_trace_ic) {
// We are going megamorphic. If the feedback is a JSFunction, it is fine __ Branch(&miss);
// to handle it here. More complex cases are dealt with in the runtime.
__ AssertNotSmi(t0);
__ GetObjectType(t0, t1, t1);
__ Branch(&miss, ne, t1, Operand(JS_FUNCTION_TYPE));
__ sll(t0, a3, kPointerSizeLog2 - kSmiTagSize);
__ Addu(t0, a2, Operand(t0));
__ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
__ sw(at, FieldMemOperand(t0, FixedArray::kHeaderSize));
// We have to update statistics for runtime profiling.
const int with_types_offset =
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex);
__ lw(t0, FieldMemOperand(a2, with_types_offset));
__ Subu(t0, t0, Operand(Smi::FromInt(1)));
__ sw(t0, FieldMemOperand(a2, with_types_offset));
const int generic_offset =
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex);
__ lw(t0, FieldMemOperand(a2, generic_offset));
__ Addu(t0, t0, Operand(Smi::FromInt(1)));
__ sw(t0, FieldMemOperand(a2, generic_offset));
__ Branch(&slow_start);
} }
// We are here because tracing is on or we are going monomorphic. __ LoadRoot(at, Heap::kuninitialized_symbolRootIndex);
__ Branch(&uninitialized, eq, t0, Operand(at));
// We are going megamorphic. If the feedback is a JSFunction, it is fine
// to handle it here. More complex cases are dealt with in the runtime.
__ AssertNotSmi(t0);
__ GetObjectType(t0, t1, t1);
__ Branch(&miss, ne, t1, Operand(JS_FUNCTION_TYPE));
__ sll(t0, a3, kPointerSizeLog2 - kSmiTagSize);
__ Addu(t0, a2, Operand(t0));
__ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
__ sw(at, FieldMemOperand(t0, FixedArray::kHeaderSize));
// We have to update statistics for runtime profiling.
__ lw(t0, FieldMemOperand(a2, with_types_offset));
__ Subu(t0, t0, Operand(Smi::FromInt(1)));
__ sw(t0, FieldMemOperand(a2, with_types_offset));
__ lw(t0, FieldMemOperand(a2, generic_offset));
__ Addu(t0, t0, Operand(Smi::FromInt(1)));
__ Branch(USE_DELAY_SLOT, &slow_start);
__ sw(t0, FieldMemOperand(a2, generic_offset)); // In delay slot.
__ bind(&uninitialized);
// We are going monomorphic, provided we actually have a JSFunction.
__ JumpIfSmi(a1, &miss);
// Goto miss case if we do not have a function.
__ GetObjectType(a1, t0, t0);
__ Branch(&miss, ne, t0, Operand(JS_FUNCTION_TYPE));
// Make sure the function is not the Array() function, which requires special
// behavior on MISS.
__ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, t0);
__ Branch(&miss, eq, a1, Operand(t0));
// Update stats.
__ lw(t0, FieldMemOperand(a2, with_types_offset));
__ Addu(t0, t0, Operand(Smi::FromInt(1)));
__ sw(t0, FieldMemOperand(a2, with_types_offset));
// Store the function.
__ sll(t0, a3, kPointerSizeLog2 - kSmiTagSize);
__ Addu(t0, a2, Operand(t0));
__ Addu(t0, t0, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
__ sw(a1, MemOperand(t0, 0));
// Update the write barrier.
__ mov(t1, a1);
__ RecordWrite(a2, t0, t1, kRAHasNotBeenSaved, kDontSaveFPRegs,
EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
__ Branch(&have_js_function);
// We are here because tracing is on or we encountered a MISS case we can't
// handle here.
__ bind(&miss); __ bind(&miss);
GenerateMiss(masm); GenerateMiss(masm);
......
...@@ -2892,6 +2892,10 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) { ...@@ -2892,6 +2892,10 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
void CallICStub::Generate(MacroAssembler* masm) { void CallICStub::Generate(MacroAssembler* masm) {
// a1 - function // a1 - function
// a3 - slot id (Smi) // a3 - slot id (Smi)
const int with_types_offset =
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex);
const int generic_offset =
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex);
Label extra_checks_or_miss, slow_start; Label extra_checks_or_miss, slow_start;
Label slow, non_function, wrap, cont; Label slow, non_function, wrap, cont;
Label have_js_function; Label have_js_function;
...@@ -2930,38 +2934,71 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2930,38 +2934,71 @@ void CallICStub::Generate(MacroAssembler* masm) {
} }
__ bind(&extra_checks_or_miss); __ bind(&extra_checks_or_miss);
Label miss; Label uninitialized, miss;
__ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex); __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
__ Branch(&slow_start, eq, a4, Operand(at)); __ Branch(&slow_start, eq, a4, Operand(at));
__ LoadRoot(at, Heap::kuninitialized_symbolRootIndex);
__ Branch(&miss, eq, a4, Operand(at)); // The following cases attempt to handle MISS cases without going to the
// runtime.
if (!FLAG_trace_ic) { if (FLAG_trace_ic) {
// We are going megamorphic. If the feedback is a JSFunction, it is fine __ Branch(&miss);
// to handle it here. More complex cases are dealt with in the runtime.
__ AssertNotSmi(a4);
__ GetObjectType(a4, a5, a5);
__ Branch(&miss, ne, a5, Operand(JS_FUNCTION_TYPE));
__ dsrl(a4, a3, 32 - kPointerSizeLog2);
__ Daddu(a4, a2, Operand(a4));
__ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
__ sd(at, FieldMemOperand(a4, FixedArray::kHeaderSize));
// We have to update statistics for runtime profiling.
const int with_types_offset =
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex);
__ ld(a4, FieldMemOperand(a2, with_types_offset));
__ Dsubu(a4, a4, Operand(Smi::FromInt(1)));
__ sd(a4, FieldMemOperand(a2, with_types_offset));
const int generic_offset =
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex);
__ ld(a4, FieldMemOperand(a2, generic_offset));
__ Daddu(a4, a4, Operand(Smi::FromInt(1)));
__ Branch(USE_DELAY_SLOT, &slow_start);
__ sd(a4, FieldMemOperand(a2, generic_offset)); // In delay slot.
} }
// We are here because tracing is on or we are going monomorphic. __ LoadRoot(at, Heap::kuninitialized_symbolRootIndex);
__ Branch(&uninitialized, eq, a4, Operand(at));
// We are going megamorphic. If the feedback is a JSFunction, it is fine
// to handle it here. More complex cases are dealt with in the runtime.
__ AssertNotSmi(a4);
__ GetObjectType(a4, a5, a5);
__ Branch(&miss, ne, a5, Operand(JS_FUNCTION_TYPE));
__ dsrl(a4, a3, 32 - kPointerSizeLog2);
__ Daddu(a4, a2, Operand(a4));
__ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
__ sd(at, FieldMemOperand(a4, FixedArray::kHeaderSize));
// We have to update statistics for runtime profiling.
__ ld(a4, FieldMemOperand(a2, with_types_offset));
__ Dsubu(a4, a4, Operand(Smi::FromInt(1)));
__ sd(a4, FieldMemOperand(a2, with_types_offset));
__ ld(a4, FieldMemOperand(a2, generic_offset));
__ Daddu(a4, a4, Operand(Smi::FromInt(1)));
__ Branch(USE_DELAY_SLOT, &slow_start);
__ sd(a4, FieldMemOperand(a2, generic_offset)); // In delay slot.
__ bind(&uninitialized);
// We are going monomorphic, provided we actually have a JSFunction.
__ JumpIfSmi(a1, &miss);
// Goto miss case if we do not have a function.
__ GetObjectType(a1, a4, a4);
__ Branch(&miss, ne, a4, Operand(JS_FUNCTION_TYPE));
// Make sure the function is not the Array() function, which requires special
// behavior on MISS.
__ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, a4);
__ Branch(&miss, eq, a1, Operand(a4));
// Update stats.
__ ld(a4, FieldMemOperand(a2, with_types_offset));
__ Daddu(a4, a4, Operand(Smi::FromInt(1)));
__ sd(a4, FieldMemOperand(a2, with_types_offset));
// Store the function.
__ dsrl(a4, a3, 32 - kPointerSizeLog2);
__ Daddu(a4, a2, Operand(a4));
__ Daddu(a4, a4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
__ sd(a1, MemOperand(a4, 0));
// Update the write barrier.
__ mov(a5, a1);
__ RecordWrite(a2, a4, a5, kRAHasNotBeenSaved, kDontSaveFPRegs,
EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
__ Branch(&have_js_function);
// We are here because tracing is on or we encountered a MISS case we can't
// handle here.
__ bind(&miss); __ bind(&miss);
GenerateMiss(masm); GenerateMiss(masm);
......
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