Reviewers: danno, mvstanton, Paul Lind, palfia, kisg,
Description:
MIPS: Correct handling of arrays with callbacks in the prototype chain.
Port r17525 (55b95f3)
Original commit message:
Our generic KeyedStoreIC doesn't handle the case when a callback is
set on array elements in the prototype chain of the object, nor do
we recognize that we need to avoid the monomorphic case if these
callbacks exist.
This CL addresses the issue by looking for dictionary elements in
the prototype chain on IC misses and crankshaft element store
instructions. When found, the generic IC is used. The generic IC is
changed to go to the runtime in this case too.
In general, keyed loads are immune from this problem because they
won't return the hole: discovery of the hole goes to the runtime where
the callback will be found in the prototype chain. Double array loads
in crankshaft can return the hole but only if the prototype chain is
unaltered (we will catch such alterations).
Includes the following patch as well (already reviewed by bmeurer):
Performance regression found in test regress-2185-2.js. The problem was
that the bailout method for TransitionAndStoreStub was not performing
the appropriate transition.
(Review URL for the ElementsTransitionAndStoreIC_Miss change:
https://codereview.chromium.org/26911007)
BUG=
Please review this at https://codereview.chromium.org/63083002/
SVN Base: [email protected]:paul99/v8m-rb.git@master
Affected files (+59, -0 lines):
M src/mips/ic-mips.cc
M src/mips/macro-assembler-mips.h
M src/mips/macro-assembler-mips.cc
Index: src/mips/ic-mips.cc
diff --git a/src/mips/ic-mips.cc b/src/mips/ic-mips.cc
index
9813da4a2b8d33b48abdd367921138a959dfcad4..0fe044a6c5a02dfc66fa51b02748672122a61eba
100644
--- a/src/mips/ic-mips.cc
+++ b/src/mips/ic-mips.cc
@@ -1180,6 +1180,22 @@ static void KeyedStoreGenerateGenericHelper(
__ Branch(fast_double, ne, elements_map,
Operand(masm->isolate()->factory()->fixed_array_map()));
}
+
+ // HOLECHECK: guards "A[i] = V"
+ // We have to go to the runtime if the current value is the hole because
+ // there may be a callback on the element.
+ Label holecheck_passed1;
+ __ Addu(address, elements, FixedArray::kHeaderSize - kHeapObjectTag);
+ __ sll(at, key, kPointerSizeLog2 - kSmiTagSize);
+ __ addu(address, address, at);
+ __ lw(scratch_value, MemOperand(address));
+ __ Branch(&holecheck_passed1, ne, scratch_value,
+ Operand(masm->isolate()->factory()->the_hole_value()));
+ __ JumpIfDictionaryInPrototypeChain(receiver, elements_map,
scratch_value,
+ slow);
+
+ __ bind(&holecheck_passed1);
+
// Smi stores don't require further checks.
Label non_smi_value;
__ JumpIfNotSmi(value, &non_smi_value);
@@ -1230,6 +1246,21 @@ static void KeyedStoreGenerateGenericHelper(
__ LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex);
__ Branch(slow, ne, elements_map, Operand(at));
}
+
+ // HOLECHECK: guards "A[i] double hole?"
+ // We have to see if the double version of the hole is present. If so
+ // go to the runtime.
+ __ Addu(address, elements,
+ Operand(FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32)
+ - kHeapObjectTag));
+ __ sll(at, key, kPointerSizeLog2);
+ __ addu(address, address, at);
+ __ lw(scratch_value, MemOperand(address));
+ __ Branch(&fast_double_without_map_check, ne, scratch_value,
+ Operand(kHoleNanUpper32));
+ __ JumpIfDictionaryInPrototypeChain(receiver, elements_map,
scratch_value,
+ slow);
+
__ bind(&fast_double_without_map_check);
__ StoreNumberToDoubleElements(value,
key,
Index: src/mips/macro-assembler-mips.cc
diff --git a/src/mips/macro-assembler-mips.cc
b/src/mips/macro-assembler-mips.cc
index
c434c31148c38d30671ab6f13f881a2e45a15e68..f751e59b005eb4c6a834dc744f567ffc4703e87f
100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -5654,6 +5654,30 @@ Register GetRegisterThatIsNotOneOf(Register reg1,
}
+void MacroAssembler::JumpIfDictionaryInPrototypeChain(
+ Register object,
+ Register scratch0,
+ Register scratch1,
+ Label* found) {
+ ASSERT(!scratch1.is(scratch0));
+ Factory* factory = isolate()->factory();
+ Register current = scratch0;
+ Label loop_again;
+
+ // Scratch contained elements pointer.
+ Move(current, object);
+
+ // Loop based on the map going up the prototype chain.
+ bind(&loop_again);
+ lw(current, FieldMemOperand(current, HeapObject::kMapOffset));
+ lb(scratch1, FieldMemOperand(current, Map::kBitField2Offset));
+ Ext(scratch1, scratch1, Map::kElementsKindShift,
Map::kElementsKindBitCount);
+ Branch(found, eq, scratch1, Operand(DICTIONARY_ELEMENTS));
+ lw(current, FieldMemOperand(current, Map::kPrototypeOffset));
+ Branch(&loop_again, ne, current, Operand(factory->null_value()));
+}
+
+
bool AreAliased(Register r1, Register r2, Register r3, Register r4) {
if (r1.is(r2)) return true;
if (r1.is(r3)) return true;
Index: src/mips/macro-assembler-mips.h
diff --git a/src/mips/macro-assembler-mips.h
b/src/mips/macro-assembler-mips.h
index
0d232e4a58d08694982dcb5d20cebfa0f5c03683..77f1e9b907a181c9f99ad89b61921e55ee1f5a4a
100644
--- a/src/mips/macro-assembler-mips.h
+++ b/src/mips/macro-assembler-mips.h
@@ -1526,6 +1526,10 @@ class MacroAssembler: public Assembler {
bind(&no_memento_found);
}
+ // Jumps to found label if a prototype map has dictionary elements.
+ void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0,
+ Register scratch1, Label* found);
+
private:
void CallCFunctionHelper(Register function,
int num_reg_arguments,
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.