diff --git a/src/ic/accessor-assembler.cc b/src/ic/accessor-assembler.cc index 977ef5f256..53f6d23ed4 100644 --- a/src/ic/accessor-assembler.cc +++ b/src/ic/accessor-assembler.cc @@ -2604,46 +2604,15 @@ void AccessorAssembler::LoadIC_Noninlined(const LoadICParameters* p, } } -// TODO(8860): This check is only required so we can make prototypes fast on -// the first load. This is not really useful when there is no feedback vector -// and may not be important when lazily allocating feedback vectors. Once lazy -// allocation of feedback vectors has landed try to eliminate this check. -void AccessorAssembler::BranchIfPrototypeShouldbeFast(Node* receiver_map, - Label* prototype_not_fast, - Label* prototype_fast) { - VARIABLE(var_map, MachineRepresentation::kTagged); - var_map.Bind(receiver_map); - Label loop_body(this, &var_map); - Goto(&loop_body); - - BIND(&loop_body); - { - Node* map = var_map.value(); - Node* prototype = LoadMapPrototype(map); - GotoIf(IsNull(prototype), prototype_fast); - TNode proto_info = - LoadMapPrototypeInfo(receiver_map, prototype_not_fast); - GotoIf(IsNull(prototype), prototype_not_fast); - TNode flags = - LoadObjectField(proto_info, PrototypeInfo::kBitFieldOffset); - GotoIf(Word32Equal(flags, Uint32Constant(0)), prototype_not_fast); - - Node* prototype_map = LoadMap(prototype); - var_map.Bind(prototype_map); - Goto(&loop_body); - } -} - void AccessorAssembler::LoadIC_Uninitialized(const LoadICParameters* p) { Label miss(this, Label::kDeferred), - check_if_fast_prototype(this, Label::kDeferred), check_function_prototype(this); Node* receiver = p->receiver; GotoIf(TaggedIsSmi(receiver), &miss); Node* receiver_map = LoadMap(receiver); Node* instance_type = LoadMapInstanceType(receiver_map); - GotoIf(IsUndefined(p->vector), &check_if_fast_prototype); + GotoIf(IsUndefined(p->vector), &check_function_prototype); // Optimistically write the state transition to the vector. StoreFeedbackVectorSlot(p->vector, p->slot, LoadRoot(RootIndex::kpremonomorphic_symbol), @@ -2652,12 +2621,6 @@ void AccessorAssembler::LoadIC_Uninitialized(const LoadICParameters* p) { kTaggedSize, SMI_PARAMETERS); Goto(&check_function_prototype); - BIND(&check_if_fast_prototype); - { - BranchIfPrototypeShouldbeFast(receiver_map, &miss, - &check_function_prototype); - } - BIND(&check_function_prototype); { // Special case for Function.prototype load, because it's very common diff --git a/src/ic/accessor-assembler.h b/src/ic/accessor-assembler.h index 180d9fc43a..c3f78d6986 100644 --- a/src/ic/accessor-assembler.h +++ b/src/ic/accessor-assembler.h @@ -296,10 +296,6 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { Representation representation, Node* value, Label* bailout); - void BranchIfPrototypeShouldbeFast(Node* receiver_map, - Label* prototype_not_fast, - Label* prototype_fast); - // Extends properties backing store by JSObject::kFieldsAdded elements, // returns updated properties backing store. Node* ExtendPropertiesBackingStore(Node* object, Node* index); diff --git a/test/mjsunit/dictionary-prototypes.js b/test/mjsunit/dictionary-prototypes.js index 109f8d42a6..0186c63f91 100644 --- a/test/mjsunit/dictionary-prototypes.js +++ b/test/mjsunit/dictionary-prototypes.js @@ -47,6 +47,7 @@ function TestAddingPropertyToDictionaryPrototype() { assertEquals(1, bar_func_called); } +%EnsureFeedbackVectorForFunction(TestAddingPropertyToDictionaryPrototype); TestAddingPropertyToDictionaryPrototype(); // Same as TestAddingPropertyToDictionaryPrototype, but using o["foo"] access @@ -82,6 +83,7 @@ function TestAddingPropertyToDictionaryPrototype2() { assertEquals(1, bar_func_called); } +%EnsureFeedbackVectorForFunction(TestAddingPropertyToDictionaryPrototype2); TestAddingPropertyToDictionaryPrototype2(); function TestAddingPropertyToDictionaryPrototype_DefineProperty() { @@ -113,6 +115,7 @@ function TestAddingPropertyToDictionaryPrototype_DefineProperty() { assertEquals(1, bar_func_called); } +%EnsureFeedbackVectorForFunction(TestAddingPropertyToDictionaryPrototype_DefineProperty); TestAddingPropertyToDictionaryPrototype_DefineProperty(); function TestAddingPropertyToDictionaryPrototype_DictionaryAddSlowPath() { @@ -146,6 +149,7 @@ function TestAddingPropertyToDictionaryPrototype_DictionaryAddSlowPath() { assertEquals(1, bar_func_called); } +%EnsureFeedbackVectorForFunction(TestAddingPropertyToDictionaryPrototype_DictionaryAddSlowPath); TestAddingPropertyToDictionaryPrototype_DictionaryAddSlowPath(); function TestAddingAccessorPropertyToDictionaryPrototype() { @@ -177,6 +181,7 @@ function TestAddingAccessorPropertyToDictionaryPrototype() { assertEquals(1, bar_func_called); } +%EnsureFeedbackVectorForFunction(TestAddingAccessorPropertyToDictionaryPrototype); TestAddingAccessorPropertyToDictionaryPrototype(); function TestRemovingPropertyFromDictionaryPrototype() { @@ -208,6 +213,7 @@ function TestRemovingPropertyFromDictionaryPrototype() { assertEquals(10, bar_func_called); } +%EnsureFeedbackVectorForFunction(TestRemovingPropertyFromDictionaryPrototype); TestRemovingPropertyFromDictionaryPrototype(); // Same as TestRemovingPropertyFromDictionaryPrototype, but using o["foo"] access @@ -242,6 +248,7 @@ function TestRemovingPropertyFromDictionaryPrototype2() { assertEquals(10, bar_func_called); } +%EnsureFeedbackVectorForFunction(TestRemovingPropertyFromDictionaryPrototype2); TestRemovingPropertyFromDictionaryPrototype2(); function TestAddingPropertyToDictionaryPrototype_Monomorphic() { @@ -286,6 +293,7 @@ function TestAddingPropertyToDictionaryPrototype_Monomorphic() { assertEquals(1, bar_func_called); } +%EnsureFeedbackVectorForFunction(TestAddingPropertyToDictionaryPrototype_Monomorphic); TestAddingPropertyToDictionaryPrototype_Monomorphic(); function TestAddingKeyedPropertyToDictionaryPrototype_Monomorphic() { @@ -331,6 +339,7 @@ function TestAddingKeyedPropertyToDictionaryPrototype_Monomorphic() { assertEquals(1, bar_func_called); } +%EnsureFeedbackVectorForFunction(TestAddingKeyedPropertyToDictionaryPrototype_Monomorphic); TestAddingKeyedPropertyToDictionaryPrototype_Monomorphic(); // Like TestAddingPropertyToDictionaryPrototype, except that the prototype isn't @@ -369,6 +378,7 @@ function TestAddingPropertyToAlmostDictionaryPrototype() { assertEquals(1, bar_func_called); } +%EnsureFeedbackVectorForFunction(TestAddingPropertyToAlmostDictionaryPrototype); TestAddingPropertyToAlmostDictionaryPrototype(); function TestReconfiguringDataToAccessor() { @@ -406,4 +416,5 @@ function TestReconfiguringDataToAccessor() { assertEquals(1, setter_called); } +%EnsureFeedbackVectorForFunction(TestReconfiguringDataToAccessor); TestReconfiguringDataToAccessor(); diff --git a/test/mjsunit/fast-prototype.js b/test/mjsunit/fast-prototype.js index ad00bec629..eb3331f674 100644 --- a/test/mjsunit/fast-prototype.js +++ b/test/mjsunit/fast-prototype.js @@ -43,6 +43,7 @@ function AddProps(obj) { obj["x" + i] = 0; } } +%EnsureFeedbackVectorForFunction(AddProps); function DoProtoMagic(proto, set__proto__) { @@ -58,9 +59,11 @@ function DoProtoMagic(proto, set__proto__) { } // Prototypes are made fast when ICs encounter them. function ic() { return typeof receiver.foo; } + %EnsureFeedbackVectorForFunction(ic); ic(); ic(); } +%EnsureFeedbackVectorForFunction(DoProtoMagic); function test(use_new, add_first, set__proto__) { @@ -86,36 +89,41 @@ function test(use_new, add_first, set__proto__) { } return proto; } +%EnsureFeedbackVectorForFunction(test); // TODO(mstarzinger): This test fails easily if gc happens at the wrong time. gc(); -for (var i = 0; i < 4; i++) { - var set__proto__ = ((i & 1) != 0); - var use_new = ((i & 2) != 0); +function test_fast_prototype() { + for (var i = 0; i < 4; i++) { + var set__proto__ = ((i & 1) != 0); + var use_new = ((i & 2) != 0); - test(use_new, true, set__proto__); - test(use_new, false, set__proto__); -} + test(use_new, true, set__proto__); + test(use_new, false, set__proto__); + } -var x = {a: 1, b: 2, c: 3}; -var o = { __proto__: x }; -assertFalse(%HasFastProperties(x)); -for (key in x) { - assertTrue(key == 'a'); - break; -} -assertTrue(%HasFastProperties(x)); -delete x.b; -for (key in x) { - assertTrue(key == 'a'); - break; -} -assertTrue(%HasFastProperties(x)); -x.d = 4; -assertTrue(%HasFastProperties(x)); -for (key in x) { - assertTrue(key == 'a'); - break; + var x = {a: 1, b: 2, c: 3}; + var o = { __proto__: x }; + assertFalse(%HasFastProperties(x)); + for (key in x) { + assertTrue(key == 'a'); + break; + } + assertTrue(%HasFastProperties(x)); + delete x.b; + for (key in x) { + assertTrue(key == 'a'); + break; + } + assertTrue(%HasFastProperties(x)); + x.d = 4; + assertTrue(%HasFastProperties(x)); + for (key in x) { + assertTrue(key == 'a'); + break; + } } +%EnsureFeedbackVectorForFunction(test_fast_prototype); +test_fast_prototype(); diff --git a/test/mjsunit/regress/regress-666046.js b/test/mjsunit/regress/regress-666046.js index b4615383e0..23e991dc17 100644 --- a/test/mjsunit/regress/regress-666046.js +++ b/test/mjsunit/regress/regress-666046.js @@ -21,6 +21,7 @@ A.prototype = proto; function foo(o) { return o.a0; } +%EnsureFeedbackVectorForFunction(foo); // Ensure |proto| is in old space. gc(); diff --git a/test/mjsunit/regress/regress-crbug-827013.js b/test/mjsunit/regress/regress-crbug-827013.js index 83ace68d8d..9281fbf600 100644 --- a/test/mjsunit/regress/regress-crbug-827013.js +++ b/test/mjsunit/regress/regress-crbug-827013.js @@ -6,13 +6,16 @@ (function Test() { var f = () => 42; - delete f.length; - delete f.name; + function modify_f() { + delete f.length; + delete f.name; - var g = Object.create(f); - for (var i = 0; i < 5; i++) { - g.dummy; + var g = Object.create(f); + for (var i = 0; i < 5; i++) { + g.dummy; + } } + %EnsureFeedbackVectorForFunction(f); assertTrue(%HasFastProperties(f)); var h = f.bind(this);