diff options
author | Michaël Zasso <targos@protonmail.com> | 2018-07-25 19:30:07 +0200 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2018-07-26 08:31:50 +0200 |
commit | 6a31d05340b22fc413ee83eaacd0a5565bbbe799 (patch) | |
tree | 78f9e1c2f417244842f6422f17e1816e70317100 /deps/v8/src/ic | |
parent | 4d94bb2b1f72b6b612983a517a39c5545724a3ad (diff) | |
download | android-node-v8-6a31d05340b22fc413ee83eaacd0a5565bbbe799.tar.gz android-node-v8-6a31d05340b22fc413ee83eaacd0a5565bbbe799.tar.bz2 android-node-v8-6a31d05340b22fc413ee83eaacd0a5565bbbe799.zip |
deps: update V8 to 6.8.275.24
PR-URL: https://github.com/nodejs/node/pull/21079
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Yang Guo <yangguo@chromium.org>
Diffstat (limited to 'deps/v8/src/ic')
-rw-r--r-- | deps/v8/src/ic/accessor-assembler.cc | 383 | ||||
-rw-r--r-- | deps/v8/src/ic/accessor-assembler.h | 45 | ||||
-rw-r--r-- | deps/v8/src/ic/binary-op-assembler.cc | 56 | ||||
-rw-r--r-- | deps/v8/src/ic/handler-configuration-inl.h | 8 | ||||
-rw-r--r-- | deps/v8/src/ic/handler-configuration.cc | 49 | ||||
-rw-r--r-- | deps/v8/src/ic/handler-configuration.h | 14 | ||||
-rw-r--r-- | deps/v8/src/ic/ic-inl.h | 20 | ||||
-rw-r--r-- | deps/v8/src/ic/ic.cc | 210 | ||||
-rw-r--r-- | deps/v8/src/ic/ic.h | 46 | ||||
-rw-r--r-- | deps/v8/src/ic/keyed-store-generic.cc | 152 | ||||
-rw-r--r-- | deps/v8/src/ic/keyed-store-generic.h | 14 | ||||
-rw-r--r-- | deps/v8/src/ic/stub-cache.cc | 2 |
12 files changed, 542 insertions, 457 deletions
diff --git a/deps/v8/src/ic/accessor-assembler.cc b/deps/v8/src/ic/accessor-assembler.cc index 7ffa263410..a40ec297a6 100644 --- a/deps/v8/src/ic/accessor-assembler.cc +++ b/deps/v8/src/ic/accessor-assembler.cc @@ -63,7 +63,7 @@ TNode<Object> AccessorAssembler::LoadHandlerDataField( Node* AccessorAssembler::TryMonomorphicCase(Node* slot, Node* vector, Node* receiver_map, Label* if_handler, - Variable* var_handler, + TVariable<MaybeObject>* var_handler, Label* if_miss) { Comment("TryMonomorphicCase"); DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); @@ -76,29 +76,29 @@ Node* AccessorAssembler::TryMonomorphicCase(Node* slot, Node* vector, // into ElementOffsetFromIndex() allows it to be folded into a single // [base, index, offset] indirect memory access on x64. Node* offset = ElementOffsetFromIndex(slot, HOLEY_ELEMENTS, SMI_PARAMETERS); - Node* feedback = Load(MachineType::AnyTagged(), vector, - IntPtrAdd(offset, IntPtrConstant(header_size))); + TNode<Object> feedback = + CAST(Load(MachineType::AnyTagged(), vector, + IntPtrAdd(offset, IntPtrConstant(header_size)))); // Try to quickly handle the monomorphic case without knowing for sure // if we have a weak cell in feedback. We do know it's safe to look // at WeakCell::kValueOffset. - GotoIf(WordNotEqual(receiver_map, LoadWeakCellValueUnchecked(feedback)), + GotoIf(WordNotEqual(receiver_map, LoadWeakCellValueUnchecked(CAST(feedback))), if_miss); - Node* handler = + TNode<MaybeObject> handler = UncheckedCast<MaybeObject>( Load(MachineType::AnyTagged(), vector, - IntPtrAdd(offset, IntPtrConstant(header_size + kPointerSize))); + IntPtrAdd(offset, IntPtrConstant(header_size + kPointerSize)))); - var_handler->Bind(handler); + *var_handler = handler; Goto(if_handler); return feedback; } -void AccessorAssembler::HandlePolymorphicCase(Node* receiver_map, - Node* feedback, Label* if_handler, - Variable* var_handler, - Label* if_miss, - int min_feedback_capacity) { +void AccessorAssembler::HandlePolymorphicCase( + Node* receiver_map, TNode<WeakFixedArray> feedback, Label* if_handler, + TVariable<MaybeObject>* var_handler, Label* if_miss, + int min_feedback_capacity) { Comment("HandlePolymorphicCase"); DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); @@ -113,7 +113,7 @@ void AccessorAssembler::HandlePolymorphicCase(Node* receiver_map, // the first {min_feedback_capacity} (map, handler) pairs. Node* length = nullptr; CSA_ASSERT(this, SmiGreaterThanOrEqual( - LoadFixedArrayBaseLength(feedback), + LoadWeakFixedArrayLength(feedback), SmiConstant(min_feedback_capacity * kEntrySize))); const int kUnrolledIterations = IC::kMaxPolymorphicMapCount; @@ -122,19 +122,21 @@ void AccessorAssembler::HandlePolymorphicCase(Node* receiver_map, int handler_index = i * kEntrySize + 1; if (i >= min_feedback_capacity) { - if (length == nullptr) length = LoadFixedArrayBaseLength(feedback); - GotoIf(SmiGreaterThanOrEqual(SmiConstant(handler_index), length), + if (length == nullptr) length = LoadWeakFixedArrayLength(feedback); + GotoIf(SmiGreaterThanOrEqual(SmiConstant(handler_index), CAST(length)), if_miss); } Label next_entry(this); - Node* cached_map = - LoadWeakCellValue(CAST(LoadFixedArrayElement(feedback, map_index))); + TNode<MaybeObject> element = LoadWeakFixedArrayElement(feedback, map_index); + CSA_ASSERT(this, IsStrongHeapObject(element)); + Node* cached_map = LoadWeakCellValue(CAST(ToStrongHeapObject(element))); GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); // Found, now call handler. - Node* handler = LoadFixedArrayElement(feedback, handler_index); - var_handler->Bind(handler); + TNode<MaybeObject> handler = + LoadWeakFixedArrayElement(feedback, handler_index); + *var_handler = handler; Goto(if_handler); BIND(&next_entry); @@ -144,19 +146,21 @@ void AccessorAssembler::HandlePolymorphicCase(Node* receiver_map, // Loop from {kUnrolledIterations}*kEntrySize to {length}. BIND(&loop); Node* start_index = IntPtrConstant(kUnrolledIterations * kEntrySize); - Node* end_index = LoadAndUntagFixedArrayBaseLength(feedback); + Node* end_index = LoadAndUntagWeakFixedArrayLength(feedback); BuildFastLoop( start_index, end_index, [this, receiver_map, feedback, if_handler, var_handler](Node* index) { - Node* cached_map = - LoadWeakCellValue(CAST(LoadFixedArrayElement(feedback, index))); + TNode<MaybeObject> element = LoadWeakFixedArrayElement(feedback, index); + CSA_ASSERT(this, IsStrongHeapObject(element)); + Node* cached_map = LoadWeakCellValue(CAST(ToStrongHeapObject(element))); Label next_entry(this); GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); // Found, now call handler. - Node* handler = LoadFixedArrayElement(feedback, index, kPointerSize); - var_handler->Bind(handler); + TNode<MaybeObject> handler = + LoadWeakFixedArrayElement(feedback, index, kPointerSize); + *var_handler = handler; Goto(if_handler); BIND(&next_entry); @@ -167,10 +171,11 @@ void AccessorAssembler::HandlePolymorphicCase(Node* receiver_map, } void AccessorAssembler::HandleLoadICHandlerCase( - const LoadICParameters* p, Node* handler, Label* miss, + const LoadICParameters* p, TNode<Object> handler, Label* miss, ExitPoint* exit_point, ICMode ic_mode, OnNonExistent on_nonexistent, ElementSupport support_elements) { Comment("have_handler"); + CSA_ASSERT(this, IsObject(handler)); VARIABLE(var_holder, MachineRepresentation::kTagged, p->holder); VARIABLE(var_smi_handler, MachineRepresentation::kTagged, handler); @@ -193,7 +198,7 @@ void AccessorAssembler::HandleLoadICHandlerCase( BIND(&try_proto_handler); { - GotoIf(IsCodeMap(LoadMap(handler)), &call_handler); + GotoIf(IsCodeMap(LoadMap(CAST(handler))), &call_handler); HandleLoadICProtoHandler(p, handler, &var_holder, &var_smi_handler, &if_smi_handler, miss, exit_point, ic_mode); } @@ -423,10 +428,10 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase( BIND(&normal); { Comment("load_normal"); - Node* properties = LoadSlowProperties(holder); - VARIABLE(var_name_index, MachineType::PointerRepresentation()); + TNode<NameDictionary> properties = CAST(LoadSlowProperties(holder)); + TVARIABLE(IntPtrT, var_name_index); Label found(this, &var_name_index); - NameDictionaryLookup<NameDictionary>(properties, p->name, &found, + NameDictionaryLookup<NameDictionary>(properties, CAST(p->name), &found, &var_name_index, miss); BIND(&found); { @@ -477,7 +482,7 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase( [=] { return LoadHandlerDataField(handler, 3); }, [=] { return LoadHandlerDataField(handler, 2); }); - Node* context = LoadWeakCellValueUnchecked(context_cell); + Node* context = LoadWeakCellValueUnchecked(CAST(context_cell)); Node* foreign = LoadObjectField(call_handler_info, CallHandlerInfo::kJsCallbackOffset); Node* callback = LoadObjectField(foreign, Foreign::kForeignAddressOffset, @@ -674,10 +679,11 @@ Node* AccessorAssembler::HandleProtoHandler( CSA_ASSERT(this, Word32BinaryNot(HasInstanceType( p->receiver, JS_GLOBAL_OBJECT_TYPE))); - Node* properties = LoadSlowProperties(p->receiver); - VARIABLE(var_name_index, MachineType::PointerRepresentation()); + TNode<NameDictionary> properties = + CAST(LoadSlowProperties(p->receiver)); + TVARIABLE(IntPtrT, var_name_index); Label found(this, &var_name_index); - NameDictionaryLookup<NameDictionary>(properties, p->name, &found, + NameDictionaryLookup<NameDictionary>(properties, CAST(p->name), &found, &var_name_index, &done); BIND(&found); { @@ -784,8 +790,8 @@ void AccessorAssembler::HandleStoreICNativeDataProperty( } void AccessorAssembler::HandleStoreICHandlerCase( - const StoreICParameters* p, Node* handler, Label* miss, ICMode ic_mode, - ElementSupport support_elements) { + const StoreICParameters* p, TNode<MaybeObject> handler, Label* miss, + ICMode ic_mode, ElementSupport support_elements) { Label if_smi_handler(this), if_nonsmi_handler(this); Label if_proto_handler(this), if_element_handler(this), call_handler(this), store_transition_or_global(this); @@ -797,7 +803,8 @@ void AccessorAssembler::HandleStoreICHandlerCase( BIND(&if_smi_handler); { Node* holder = p->receiver; - Node* handler_word = SmiUntag(handler); + CSA_ASSERT(this, IsObject(handler)); + Node* handler_word = SmiUntag(CAST(ToObject(handler))); Label if_fast_smi(this), if_proxy(this); @@ -813,12 +820,12 @@ void AccessorAssembler::HandleStoreICHandlerCase( &if_proxy); CSA_ASSERT(this, WordEqual(handler_kind, IntPtrConstant(StoreHandler::kNormal))); - Node* properties = LoadSlowProperties(holder); + TNode<NameDictionary> properties = CAST(LoadSlowProperties(holder)); - VARIABLE(var_name_index, MachineType::PointerRepresentation()); + TVARIABLE(IntPtrT, var_name_index); Label dictionary_found(this, &var_name_index); - NameDictionaryLookup<NameDictionary>(properties, p->name, &dictionary_found, - &var_name_index, miss); + NameDictionaryLookup<NameDictionary>( + properties, CAST(p->name), &dictionary_found, &var_name_index, miss); BIND(&dictionary_found); { Node* details = LoadDetailsByKeyIndex<NameDictionary>( @@ -862,44 +869,54 @@ void AccessorAssembler::HandleStoreICHandlerCase( BIND(&if_nonsmi_handler); { - Node* handler_map = LoadMap(handler); - GotoIf(IsWeakCellMap(handler_map), &store_transition_or_global); + GotoIf(IsWeakOrClearedHeapObject(handler), &store_transition_or_global); + CSA_ASSERT(this, IsStrongHeapObject(handler)); + TNode<HeapObject> strong_handler = ToStrongHeapObject(handler); + TNode<Map> handler_map = LoadMap(strong_handler); Branch(IsCodeMap(handler_map), &call_handler, &if_proto_handler); - } - BIND(&if_proto_handler); - HandleStoreICProtoHandler(p, handler, miss, ic_mode, support_elements); + BIND(&if_proto_handler); + { + HandleStoreICProtoHandler(p, CAST(strong_handler), miss, ic_mode, + support_elements); + } - // |handler| is a heap object. Must be code, call it. - BIND(&call_handler); - { - StoreWithVectorDescriptor descriptor(isolate()); - TailCallStub(descriptor, handler, p->context, p->receiver, p->name, - p->value, p->slot, p->vector); + // |handler| is a heap object. Must be code, call it. + BIND(&call_handler); + { + StoreWithVectorDescriptor descriptor(isolate()); + TailCallStub(descriptor, strong_handler, p->context, p->receiver, p->name, + p->value, p->slot, p->vector); + } } BIND(&store_transition_or_global); { // Load value or miss if the {handler} weak cell is cleared. - Node* map_or_property_cell = LoadWeakCellValue(handler, miss); + CSA_ASSERT(this, IsWeakOrClearedHeapObject(handler)); + TNode<HeapObject> map_or_property_cell = ToWeakHeapObject(handler, miss); Label store_global(this), store_transition(this); Branch(IsMap(map_or_property_cell), &store_transition, &store_global); BIND(&store_global); { + TNode<PropertyCell> property_cell = CAST(map_or_property_cell); ExitPoint direct_exit(this); - StoreGlobalIC_PropertyCellCase(map_or_property_cell, p->value, - &direct_exit, miss); + StoreGlobalIC_PropertyCellCase(property_cell, p->value, &direct_exit, + miss); } BIND(&store_transition); - HandleStoreICTransitionMapHandlerCase(p, map_or_property_cell, miss, false); - Return(p->value); + { + TNode<Map> map = CAST(map_or_property_cell); + HandleStoreICTransitionMapHandlerCase(p, map, miss, false); + Return(p->value); + } } } void AccessorAssembler::HandleStoreICTransitionMapHandlerCase( - const StoreICParameters* p, Node* transition_map, Label* miss, + const StoreICParameters* p, TNode<Map> transition_map, Label* miss, bool validate_transition_handler) { Node* maybe_validity_cell = LoadObjectField(transition_map, Map::kPrototypeValidityCellOffset); @@ -1130,7 +1147,7 @@ void AccessorAssembler::OverwriteExistingFastDataProperty( BIND(&double_rep); { Node* mutable_heap_number = - LoadFixedArrayElement(properties, backing_store_index); + LoadPropertyArrayElement(properties, backing_store_index); Node* double_value = ChangeNumberToFloat64(value); StoreHeapNumberValue(mutable_heap_number, double_value); Goto(&done); @@ -1187,8 +1204,8 @@ void AccessorAssembler::HandleStoreAccessor(const StoreICParameters* p, } void AccessorAssembler::HandleStoreICProtoHandler( - const StoreICParameters* p, Node* handler, Label* miss, ICMode ic_mode, - ElementSupport support_elements) { + const StoreICParameters* p, TNode<StoreHandler> handler, Label* miss, + ICMode ic_mode, ElementSupport support_elements) { Comment("HandleStoreICProtoHandler"); OnCodeHandler on_code_handler; @@ -1281,11 +1298,11 @@ void AccessorAssembler::HandleStoreICProtoHandler( // case is covered above by LookupOnReceiver bit handling of the smi // handler. Label slow(this); - Node* receiver_map = LoadMap(p->receiver); + TNode<Map> receiver_map = LoadMap(p->receiver); InvalidateValidityCellIfPrototype(receiver_map); - Node* properties = LoadSlowProperties(p->receiver); - Add<NameDictionary>(properties, p->name, p->value, &slow); + TNode<NameDictionary> properties = CAST(LoadSlowProperties(p->receiver)); + Add<NameDictionary>(properties, CAST(p->name), p->value, &slow); Return(p->value); BIND(&slow); @@ -1312,7 +1329,7 @@ void AccessorAssembler::HandleStoreICProtoHandler( [=] { return LoadHandlerDataField(handler, 3); }, [=] { return LoadHandlerDataField(handler, 2); }); - Node* context = LoadWeakCellValueUnchecked(context_cell); + Node* context = LoadWeakCellValueUnchecked(CAST(context_cell)); Node* foreign = LoadObjectField(call_handler_info, CallHandlerInfo::kJsCallbackOffset); @@ -1693,10 +1710,11 @@ void AccessorAssembler::EmitFastElementsBoundsCheck(Node* object, } void AccessorAssembler::EmitElementLoad( - Node* object, Node* elements, Node* elements_kind, Node* intptr_index, - Node* is_jsarray_condition, Label* if_hole, Label* rebox_double, - Variable* var_double_value, Label* unimplemented_elements_kind, - Label* out_of_bounds, Label* miss, ExitPoint* exit_point) { + Node* object, Node* elements, Node* elements_kind, + SloppyTNode<IntPtrT> intptr_index, Node* is_jsarray_condition, + Label* if_hole, Label* rebox_double, Variable* var_double_value, + Label* unimplemented_elements_kind, Label* out_of_bounds, Label* miss, + ExitPoint* exit_point) { Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this), if_fast_double(this), if_fast_holey_double(this), if_nonfast(this), if_dictionary(this); @@ -1773,13 +1791,13 @@ void AccessorAssembler::EmitElementLoad( { Comment("dictionary elements"); GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), out_of_bounds); - VARIABLE(var_entry, MachineType::PointerRepresentation()); + TVARIABLE(IntPtrT, var_entry); Label if_found(this); - NumberDictionaryLookup(elements, intptr_index, &if_found, &var_entry, + NumberDictionaryLookup(CAST(elements), intptr_index, &if_found, &var_entry, if_hole); BIND(&if_found); // Check that the value is a data property. - Node* index = EntryToIndex<NumberDictionary>(var_entry.value()); + TNode<IntPtrT> index = EntryToIndex<NumberDictionary>(var_entry.value()); Node* details = LoadDetailsByKeyIndex<NumberDictionary>(elements, index); Node* kind = DecodeWord32<PropertyDetails::KindField>(details); // TODO(jkummerow): Support accessors without missing? @@ -1894,12 +1912,13 @@ void AccessorAssembler::EmitElementLoad( } } -void AccessorAssembler::NameDictionaryNegativeLookup(Node* object, Node* name, +void AccessorAssembler::NameDictionaryNegativeLookup(Node* object, + SloppyTNode<Name> name, Label* miss) { CSA_ASSERT(this, IsDictionaryMap(LoadMap(object))); - Node* properties = LoadSlowProperties(object); + TNode<NameDictionary> properties = CAST(LoadSlowProperties(object)); // Ensure the property does not exist in a dictionary-mode object. - VARIABLE(var_name_index, MachineType::PointerRepresentation()); + TVARIABLE(IntPtrT, var_name_index); Label done(this); NameDictionaryLookup<NameDictionary>(properties, name, miss, &var_name_index, &done); @@ -1961,7 +1980,7 @@ void AccessorAssembler::InvalidateValidityCellIfPrototype(Node* map, GotoIf(TaggedIsSmi(maybe_prototype_info), &cont); Node* function = ExternalConstant( - ExternalReference::invalidate_prototype_chains_function(isolate())); + ExternalReference::invalidate_prototype_chains_function()); CallCFunction1(MachineType::AnyTagged(), MachineType::AnyTagged(), function, map); Goto(&cont); @@ -1970,8 +1989,8 @@ void AccessorAssembler::InvalidateValidityCellIfPrototype(Node* map, } void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map, - Node* instance_type, Node* index, - Label* slow) { + SloppyTNode<Int32T> instance_type, + Node* index, Label* slow) { Comment("integer index"); ExitPoint direct_exit(this); @@ -1979,9 +1998,7 @@ void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map, Label if_custom(this), if_element_hole(this), if_oob(this); // Receivers requiring non-standard element accesses (interceptors, access // checks, strings and string wrappers, proxies) are handled in the runtime. - GotoIf(Int32LessThanOrEqual(instance_type, - Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), - &if_custom); + GotoIf(IsCustomElementsReceiverInstanceType(instance_type), &if_custom); Node* elements = LoadElements(receiver); Node* elements_kind = LoadMapElementsKind(receiver_map); Node* is_jsarray_condition = InstanceTypeEqual(instance_type, JS_ARRAY_TYPE); @@ -2034,7 +2051,7 @@ void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map, } void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map, - Node* instance_type, + SloppyTNode<Int32T> instance_type, const LoadICParameters* p, Label* slow, UseStubCache use_stub_cache) { @@ -2083,7 +2100,7 @@ void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map, &found_handler, &var_handler, &stub_cache_miss); BIND(&found_handler); { - HandleLoadICHandlerCase(p, var_handler.value(), &stub_cache_miss, + HandleLoadICHandlerCase(p, CAST(var_handler.value()), &stub_cache_miss, &direct_exit); } @@ -2103,11 +2120,11 @@ void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map, // We checked for LAST_CUSTOM_ELEMENTS_RECEIVER before, which rules out // seeing global objects here (which would need special handling). - VARIABLE(var_name_index, MachineType::PointerRepresentation()); + TVARIABLE(IntPtrT, var_name_index); Label dictionary_found(this, &var_name_index); - Node* properties = LoadSlowProperties(receiver); - NameDictionaryLookup<NameDictionary>(properties, p->name, &dictionary_found, - &var_name_index, + TNode<NameDictionary> properties = CAST(LoadSlowProperties(receiver)); + NameDictionaryLookup<NameDictionary>(properties, CAST(p->name), + &dictionary_found, &var_name_index, &lookup_prototype_chain); BIND(&dictionary_found); { @@ -2248,8 +2265,8 @@ void AccessorAssembler::TryProbeStubCacheTable(StubCache* stub_cache, entry_offset = IntPtrMul(entry_offset, IntPtrConstant(kMultiplier)); // Check that the key in the entry matches the name. - Node* key_base = - ExternalConstant(ExternalReference(stub_cache->key_reference(table))); + Node* key_base = ExternalConstant( + ExternalReference::Create(stub_cache->key_reference(table))); Node* entry_key = Load(MachineType::Pointer(), key_base, entry_offset); GotoIf(WordNotEqual(name, entry_key), if_miss); @@ -2327,7 +2344,7 @@ void AccessorAssembler::LoadIC_BytecodeHandler(const LoadICParameters* p, Node* recv_map = LoadReceiverMap(p->receiver); GotoIf(IsDeprecatedMap(recv_map), &miss); - VARIABLE(var_handler, MachineRepresentation::kTagged); + TVARIABLE(MaybeObject, var_handler); Label try_polymorphic(this), if_handler(this, &var_handler); Node* feedback = @@ -2335,13 +2352,14 @@ void AccessorAssembler::LoadIC_BytecodeHandler(const LoadICParameters* p, &var_handler, &try_polymorphic); BIND(&if_handler); - HandleLoadICHandlerCase(p, var_handler.value(), &miss, exit_point); + CSA_ASSERT(this, IsObject(var_handler.value())); + HandleLoadICHandlerCase(p, ToObject(var_handler.value()), &miss, + exit_point); BIND(&try_polymorphic); { - GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), - &stub_call); - HandlePolymorphicCase(recv_map, feedback, &if_handler, &var_handler, + GotoIfNot(IsWeakFixedArrayMap(LoadMap(feedback)), &stub_call); + HandlePolymorphicCase(recv_map, CAST(feedback), &if_handler, &var_handler, &miss, 2); } } @@ -2372,7 +2390,7 @@ void AccessorAssembler::LoadIC(const LoadICParameters* p) { ExitPoint direct_exit(this); - VARIABLE(var_handler, MachineRepresentation::kTagged); + TVARIABLE(MaybeObject, var_handler); Label if_handler(this, &var_handler), non_inlined(this, Label::kDeferred), try_polymorphic(this), miss(this, Label::kDeferred); @@ -2384,16 +2402,17 @@ void AccessorAssembler::LoadIC(const LoadICParameters* p) { TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, &var_handler, &try_polymorphic); BIND(&if_handler); - HandleLoadICHandlerCase(p, var_handler.value(), &miss, &direct_exit); + CSA_ASSERT(this, IsObject(var_handler.value())); + HandleLoadICHandlerCase(p, ToObject(var_handler.value()), &miss, + &direct_exit); BIND(&try_polymorphic); { // Check polymorphic case. Comment("LoadIC_try_polymorphic"); - GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), - &non_inlined); - HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, - &miss, 2); + GotoIfNot(IsWeakFixedArrayMap(LoadMap(feedback)), &non_inlined); + HandlePolymorphicCase(receiver_map, CAST(feedback), &if_handler, + &var_handler, &miss, 2); } BIND(&non_inlined); @@ -2417,7 +2436,7 @@ void AccessorAssembler::LoadIC_Noninlined(const LoadICParameters* p, CSA_ASSERT(this, Word32BinaryNot(IsDeprecatedMap(receiver_map))); CSA_ASSERT(this, WordNotEqual(receiver_map, LoadWeakCellValueUnchecked(feedback))); - CSA_ASSERT(this, WordNotEqual(LoadMap(feedback), FixedArrayMapConstant())); + CSA_ASSERT(this, Word32BinaryNot(IsWeakFixedArrayMap(LoadMap(feedback)))); DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); { @@ -2520,8 +2539,10 @@ void AccessorAssembler::LoadGlobalIC_TryPropertyCellCase( Comment("LoadGlobalIC_TryPropertyCellCase"); Label if_lexical_var(this), if_property_cell(this); - TNode<Object> maybe_weak_cell = + TNode<MaybeObject> feedback_element = LoadFeedbackVectorSlot(vector, slot, 0, slot_mode); + CSA_ASSERT(this, IsObject(feedback_element)); + TNode<Object> maybe_weak_cell = ToObject(feedback_element); Branch(TaggedIsSmi(maybe_weak_cell), &if_lexical_var, &if_property_cell); BIND(&if_property_cell); @@ -2561,7 +2582,10 @@ void AccessorAssembler::LoadGlobalIC_TryHandlerCase( Label call_handler(this), non_smi(this); - Node* handler = LoadFeedbackVectorSlot(vector, slot, kPointerSize, slot_mode); + TNode<MaybeObject> feedback_element = + LoadFeedbackVectorSlot(vector, slot, kPointerSize, slot_mode); + CSA_ASSERT(this, IsObject(feedback_element)); + TNode<Object> handler = ToObject(feedback_element); GotoIf(WordEqual(handler, LoadRoot(Heap::kuninitialized_symbolRootIndex)), miss); @@ -2585,7 +2609,7 @@ void AccessorAssembler::LoadGlobalIC_TryHandlerCase( void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { ExitPoint direct_exit(this); - VARIABLE(var_handler, MachineRepresentation::kTagged); + TVARIABLE(MaybeObject, var_handler); Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred), try_megamorphic(this, Label::kDeferred), try_polymorphic_name(this, Label::kDeferred), @@ -2600,8 +2624,9 @@ void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { &var_handler, &try_polymorphic); BIND(&if_handler); { - HandleLoadICHandlerCase(p, var_handler.value(), &miss, &direct_exit, - ICMode::kNonGlobalIC, + CSA_ASSERT(this, IsObject(var_handler.value())); + HandleLoadICHandlerCase(p, ToObject(var_handler.value()), &miss, + &direct_exit, ICMode::kNonGlobalIC, OnNonExistent::kReturnUndefined, kSupportElements); } @@ -2609,10 +2634,9 @@ void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { { // Check polymorphic case. Comment("KeyedLoadIC_try_polymorphic"); - GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), - &try_megamorphic); - HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, - &miss, 2); + GotoIfNot(IsWeakFixedArrayMap(LoadMap(feedback)), &try_megamorphic); + HandlePolymorphicCase(receiver_map, CAST(feedback), &if_handler, + &var_handler, &miss, 2); } BIND(&try_megamorphic); @@ -2627,7 +2651,8 @@ void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { } BIND(&try_polymorphic_name); { - // We might have a name in feedback, and a fixed array in the next slot. + // We might have a name in feedback, and a weak fixed array in the next + // slot. Node* name = p->name; Comment("KeyedLoadIC_try_polymorphic_name"); VARIABLE(var_name, MachineRepresentation::kTagged, name); @@ -2653,7 +2678,7 @@ void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { { // Try to internalize the {name}. Node* function = ExternalConstant( - ExternalReference::try_internalize_string_function(isolate())); + ExternalReference::try_internalize_string_function()); var_name.Bind(CallCFunction1(MachineType::AnyTagged(), MachineType::AnyTagged(), function, name)); Goto(&if_internalized); @@ -2661,8 +2686,8 @@ void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { BIND(&if_polymorphic_name); { - // If the name comparison succeeded, we know we have a fixed array with - // at least one map/handler pair. + // If the name comparison succeeded, we know we have a weak fixed array + // with at least one map/handler pair. Node* name = var_name.value(); TailCallBuiltin(Builtins::kKeyedLoadIC_PolymorphicName, p->context, p->receiver, name, p->slot, p->vector); @@ -2743,7 +2768,7 @@ void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) { } void AccessorAssembler::KeyedLoadICPolymorphicName(const LoadICParameters* p) { - VARIABLE(var_handler, MachineRepresentation::kTagged); + TVARIABLE(MaybeObject, var_handler); Label if_handler(this, &var_handler), miss(this, Label::kDeferred); Node* receiver = p->receiver; @@ -2758,20 +2783,25 @@ void AccessorAssembler::KeyedLoadICPolymorphicName(const LoadICParameters* p) { // LoadIC handler logic below. CSA_ASSERT(this, IsName(name)); CSA_ASSERT(this, Word32BinaryNot(IsDeprecatedMap(receiver_map))); - CSA_ASSERT(this, WordEqual(name, LoadFeedbackVectorSlot(vector, slot, 0, - SMI_PARAMETERS))); + CSA_ASSERT(this, IsStrongHeapObject(LoadFeedbackVectorSlot(vector, slot, 0, + SMI_PARAMETERS))); + CSA_ASSERT(this, WordEqual(name, ToStrongHeapObject(LoadFeedbackVectorSlot( + vector, slot, 0, SMI_PARAMETERS)))); // Check if we have a matching handler for the {receiver_map}. - Node* array = + TNode<MaybeObject> feedback_element = LoadFeedbackVectorSlot(vector, slot, kPointerSize, SMI_PARAMETERS); + CSA_ASSERT(this, IsObject(feedback_element)); + TNode<WeakFixedArray> array = CAST(ToObject(feedback_element)); HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, &miss, 1); BIND(&if_handler); { ExitPoint direct_exit(this); - HandleLoadICHandlerCase(p, var_handler.value(), &miss, &direct_exit, - ICMode::kNonGlobalIC, + CSA_ASSERT(this, IsObject(var_handler.value())); + HandleLoadICHandlerCase(p, ToObject(var_handler.value()), &miss, + &direct_exit, ICMode::kNonGlobalIC, OnNonExistent::kReturnUndefined, kOnlyProperties); } @@ -2784,8 +2814,12 @@ void AccessorAssembler::KeyedLoadICPolymorphicName(const LoadICParameters* p) { } void AccessorAssembler::StoreIC(const StoreICParameters* p) { - VARIABLE(var_handler, MachineRepresentation::kTagged); - Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred), + TVARIABLE(MaybeObject, var_handler, + ReinterpretCast<MaybeObject>(SmiConstant(0))); + + Label if_handler(this, &var_handler), + if_handler_from_stub_cache(this, &var_handler, Label::kDeferred), + try_polymorphic(this, Label::kDeferred), try_megamorphic(this, Label::kDeferred), try_uninitialized(this, Label::kDeferred), miss(this, Label::kDeferred); @@ -2807,11 +2841,9 @@ void AccessorAssembler::StoreIC(const StoreICParameters* p) { { // Check polymorphic case. Comment("StoreIC_try_polymorphic"); - GotoIfNot( - WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), - &try_megamorphic); - HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, - &miss, 2); + GotoIfNot(IsWeakFixedArrayMap(LoadMap(feedback)), &try_megamorphic); + HandlePolymorphicCase(receiver_map, CAST(feedback), &if_handler, + &var_handler, &miss, 2); } BIND(&try_megamorphic); @@ -2821,7 +2853,27 @@ void AccessorAssembler::StoreIC(const StoreICParameters* p) { &try_uninitialized); TryProbeStubCache(isolate()->store_stub_cache(), p->receiver, p->name, - &if_handler, &var_handler, &miss); + &if_handler_from_stub_cache, &var_handler, &miss); + } + BIND(&if_handler_from_stub_cache); + { + // If the stub cache contains a WeakCell pointing to a Map, convert it to an + // in-place weak reference. TODO(marja): This well get simplified once more + // WeakCells are converted into in-place weak references. + Comment("StoreIC_if_handler_from_stub_cache"); + GotoIf(TaggedIsSmi(var_handler.value()), &if_handler); + + CSA_ASSERT(this, IsStrongHeapObject(var_handler.value())); + TNode<HeapObject> handler = ToStrongHeapObject(var_handler.value()); + GotoIfNot(IsWeakCell(handler), &if_handler); + + TNode<HeapObject> value = CAST(LoadWeakCellValue(CAST(handler), &miss)); + TNode<Map> value_map = LoadMap(value); + GotoIfNot(Word32Or(IsMetaMap(value_map), IsPropertyCellMap(value_map)), + &if_handler); + + TNode<MaybeObject> weak_handler = MakeWeak(value); + HandleStoreICHandlerCase(p, weak_handler, &miss, ICMode::kNonGlobalIC); } BIND(&try_uninitialized); { @@ -2841,14 +2893,17 @@ void AccessorAssembler::StoreIC(const StoreICParameters* p) { void AccessorAssembler::StoreGlobalIC(const StoreICParameters* pp) { Label if_lexical_var(this), if_property_cell(this); - Node* maybe_weak_cell = + TNode<MaybeObject> feedback_element = LoadFeedbackVectorSlot(pp->vector, pp->slot, 0, SMI_PARAMETERS); + CSA_ASSERT(this, IsObject(feedback_element)); + TNode<Object> maybe_weak_cell = ToObject(feedback_element); Branch(TaggedIsSmi(maybe_weak_cell), &if_lexical_var, &if_property_cell); BIND(&if_property_cell); { Label try_handler(this), miss(this, Label::kDeferred); - Node* property_cell = LoadWeakCellValue(maybe_weak_cell, &try_handler); + TNode<PropertyCell> property_cell = + CAST(LoadWeakCellValue(CAST(maybe_weak_cell), &try_handler)); ExitPoint direct_exit(this); StoreGlobalIC_PropertyCellCase(property_cell, pp->value, &direct_exit, @@ -2857,8 +2912,8 @@ void AccessorAssembler::StoreGlobalIC(const StoreICParameters* pp) { BIND(&try_handler); { Comment("StoreGlobalIC_try_handler"); - Node* handler = LoadFeedbackVectorSlot(pp->vector, pp->slot, kPointerSize, - SMI_PARAMETERS); + TNode<MaybeObject> handler = LoadFeedbackVectorSlot( + pp->vector, pp->slot, kPointerSize, SMI_PARAMETERS); GotoIf(WordEqual(handler, LoadRoot(Heap::kuninitialized_symbolRootIndex)), &miss); @@ -2882,14 +2937,14 @@ void AccessorAssembler::StoreGlobalIC(const StoreICParameters* pp) { BIND(&if_lexical_var); { Comment("Store lexical variable"); - TNode<IntPtrT> lexical_handler = SmiUntag(maybe_weak_cell); + TNode<IntPtrT> lexical_handler = SmiUntag(CAST(maybe_weak_cell)); TNode<IntPtrT> context_index = Signed(DecodeWord<FeedbackNexus::ContextIndexBits>(lexical_handler)); TNode<IntPtrT> slot_index = Signed(DecodeWord<FeedbackNexus::SlotIndexBits>(lexical_handler)); TNode<Context> script_context = LoadScriptContext(CAST(pp->context), context_index); - StoreContextElement(script_context, slot_index, CAST(pp->value)); + StoreContextElement(script_context, slot_index, pp->value); Return(pp->value); } } @@ -2961,7 +3016,7 @@ void AccessorAssembler::StoreGlobalIC_PropertyCellCase(Node* property_cell, void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p) { Label miss(this, Label::kDeferred); { - VARIABLE(var_handler, MachineRepresentation::kTagged); + TVARIABLE(MaybeObject, var_handler); Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred), @@ -2986,11 +3041,9 @@ void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p) { { // CheckPolymorphic case. Comment("KeyedStoreIC_try_polymorphic"); - GotoIfNot( - WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), - &try_megamorphic); - HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, - &miss, 2); + GotoIfNot(IsWeakFixedArrayMap(LoadMap(feedback)), &try_megamorphic); + HandlePolymorphicCase(receiver_map, CAST(feedback), &if_handler, + &var_handler, &miss, 2); } BIND(&try_megamorphic); @@ -3011,8 +3064,10 @@ void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p) { GotoIfNot(WordEqual(feedback, p->name), &miss); // If the name comparison succeeded, we know we have a feedback vector // with at least one map/handler pair. - Node* array = LoadFeedbackVectorSlot(p->vector, p->slot, kPointerSize, - SMI_PARAMETERS); + TNode<MaybeObject> feedback_element = LoadFeedbackVectorSlot( + p->vector, p->slot, kPointerSize, SMI_PARAMETERS); + CSA_ASSERT(this, IsObject(feedback_element)); + TNode<WeakFixedArray> array = CAST(ToObject(feedback_element)); HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, &miss, 1); } @@ -3028,7 +3083,7 @@ void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p) { void AccessorAssembler::StoreInArrayLiteralIC(const StoreICParameters* p) { Label miss(this, Label::kDeferred); { - VARIABLE(var_handler, MachineRepresentation::kTagged); + TVARIABLE(MaybeObject, var_handler); Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred), @@ -3045,7 +3100,8 @@ void AccessorAssembler::StoreInArrayLiteralIC(const StoreICParameters* p) { Comment("StoreInArrayLiteralIC_if_handler"); // This is a stripped-down version of HandleStoreICHandlerCase. - Node* handler = var_handler.value(); + CSA_ASSERT(this, IsStrongHeapObject(var_handler.value())); + TNode<HeapObject> handler = ToStrongHeapObject(var_handler.value()); Label if_transitioning_element_store(this); GotoIfNot(IsCode(handler), &if_transitioning_element_store); StoreWithVectorDescriptor descriptor(isolate()); @@ -3054,7 +3110,7 @@ void AccessorAssembler::StoreInArrayLiteralIC(const StoreICParameters* p) { BIND(&if_transitioning_element_store); { - Node* transition_map_cell = LoadHandlerDataField(handler, 1); + Node* transition_map_cell = LoadHandlerDataField(CAST(handler), 1); Node* transition_map = LoadWeakCellValue(transition_map_cell, &miss); CSA_ASSERT(this, IsMap(transition_map)); GotoIf(IsDeprecatedMap(transition_map), &miss); @@ -3069,11 +3125,9 @@ void AccessorAssembler::StoreInArrayLiteralIC(const StoreICParameters* p) { BIND(&try_polymorphic); { Comment("StoreInArrayLiteralIC_try_polymorphic"); - GotoIfNot( - WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), - &try_megamorphic); - HandlePolymorphicCase(array_map, feedback, &if_handler, &var_handler, - &miss, 2); + GotoIfNot(IsWeakFixedArrayMap(LoadMap(feedback)), &try_megamorphic); + HandlePolymorphicCase(array_map, CAST(feedback), &if_handler, + &var_handler, &miss, 2); } BIND(&try_megamorphic); @@ -3134,14 +3188,17 @@ void AccessorAssembler::GenerateLoadIC_Noninlined() { Label if_handler(this, &var_handler), miss(this, Label::kDeferred); Node* receiver_map = LoadReceiverMap(receiver); - Node* feedback = LoadFeedbackVectorSlot(vector, slot, 0, SMI_PARAMETERS); + TNode<MaybeObject> feedback_element = + LoadFeedbackVectorSlot(vector, slot, 0, SMI_PARAMETERS); + CSA_ASSERT(this, IsObject(feedback_element)); + TNode<Object> feedback = ToObject(feedback_element); LoadICParameters p(context, receiver, name, slot, vector); LoadIC_Noninlined(&p, receiver_map, feedback, &var_handler, &if_handler, &miss, &direct_exit); BIND(&if_handler); - HandleLoadICHandlerCase(&p, var_handler.value(), &miss, &direct_exit); + HandleLoadICHandlerCase(&p, CAST(var_handler.value()), &miss, &direct_exit); BIND(&miss); direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name, @@ -3173,30 +3230,6 @@ void AccessorAssembler::GenerateLoadICTrampoline() { TailCallBuiltin(Builtins::kLoadIC, context, receiver, name, slot, vector); } -void AccessorAssembler::GenerateLoadField() { - typedef LoadFieldDescriptor Descriptor; - - Node* receiver = Parameter(Descriptor::kReceiver); - Node* name = nullptr; - Node* slot = nullptr; - Node* vector = nullptr; - Node* context = Parameter(Descriptor::kContext); - LoadICParameters p(context, receiver, name, slot, vector); - - ExitPoint direct_exit(this); - - VARIABLE(var_double_value, MachineRepresentation::kFloat64); - Label rebox_double(this, &var_double_value); - - Node* smi_handler = Parameter(Descriptor::kSmiHandler); - Node* handler_word = SmiUntag(smi_handler); - HandleLoadField(receiver, handler_word, &var_double_value, &rebox_double, - &direct_exit); - - BIND(&rebox_double); - Return(AllocateHeapNumberWithValue(var_double_value.value())); -} - void AccessorAssembler::GenerateLoadGlobalIC(TypeofMode typeof_mode) { typedef LoadGlobalWithVectorDescriptor Descriptor; diff --git a/deps/v8/src/ic/accessor-assembler.h b/deps/v8/src/ic/accessor-assembler.h index 7428eeec4d..24a47376a5 100644 --- a/deps/v8/src/ic/accessor-assembler.h +++ b/deps/v8/src/ic/accessor-assembler.h @@ -30,7 +30,6 @@ class AccessorAssembler : public CodeStubAssembler { void GenerateLoadIC(); void GenerateLoadIC_Noninlined(); void GenerateLoadIC_Uninitialized(); - void GenerateLoadField(); void GenerateLoadICTrampoline(); void GenerateKeyedLoadIC(); void GenerateKeyedLoadICTrampoline(); @@ -94,20 +93,21 @@ class AccessorAssembler : public CodeStubAssembler { protected: struct StoreICParameters : public LoadICParameters { - StoreICParameters(Node* context, Node* receiver, Node* name, Node* value, - Node* slot, Node* vector) + StoreICParameters(Node* context, Node* receiver, Node* name, + SloppyTNode<Object> value, Node* slot, Node* vector) : LoadICParameters(context, receiver, name, slot, vector), value(value) {} - Node* value; + SloppyTNode<Object> value; }; enum class ICMode { kNonGlobalIC, kGlobalIC }; enum ElementSupport { kOnlyProperties, kSupportElements }; void HandleStoreICHandlerCase( - const StoreICParameters* p, Node* handler, Label* miss, ICMode ic_mode, - ElementSupport support_elements = kOnlyProperties); + const StoreICParameters* p, TNode<MaybeObject> handler, Label* miss, + ICMode ic_mode, ElementSupport support_elements = kOnlyProperties); void HandleStoreICTransitionMapHandlerCase(const StoreICParameters* p, - Node* transition_map, Label* miss, + TNode<Map> transition_map, + Label* miss, bool validate_transition_handler); void JumpIfDataProperty(Node* details, Label* writable, Label* readonly); @@ -154,16 +154,17 @@ class AccessorAssembler : public CodeStubAssembler { // Checks monomorphic case. Returns {feedback} entry of the vector. Node* TryMonomorphicCase(Node* slot, Node* vector, Node* receiver_map, - Label* if_handler, Variable* var_handler, - Label* if_miss); - void HandlePolymorphicCase(Node* receiver_map, Node* feedback, - Label* if_handler, Variable* var_handler, + Label* if_handler, + TVariable<MaybeObject>* var_handler, Label* if_miss); + void HandlePolymorphicCase(Node* receiver_map, TNode<WeakFixedArray> feedback, + Label* if_handler, + TVariable<MaybeObject>* var_handler, Label* if_miss, int min_feedback_capacity); // LoadIC implementation. enum class OnNonExistent { kThrowReferenceError, kReturnUndefined }; void HandleLoadICHandlerCase( - const LoadICParameters* p, Node* handler, Label* miss, + const LoadICParameters* p, TNode<Object> handler, Label* miss, ExitPoint* exit_point, ICMode ic_mode = ICMode::kNonGlobalIC, OnNonExistent on_nonexistent = OnNonExistent::kReturnUndefined, ElementSupport support_elements = kOnlyProperties); @@ -203,8 +204,9 @@ class AccessorAssembler : public CodeStubAssembler { // StoreIC implementation. - void HandleStoreICProtoHandler(const StoreICParameters* p, Node* handler, - Label* miss, ICMode ic_mode, + void HandleStoreICProtoHandler(const StoreICParameters* p, + TNode<StoreHandler> handler, Label* miss, + ICMode ic_mode, ElementSupport support_elements); void HandleStoreICSmiHandlerCase(Node* handler_word, Node* holder, Node* value, Label* miss); @@ -225,12 +227,13 @@ class AccessorAssembler : public CodeStubAssembler { // KeyedLoadIC_Generic implementation. void GenericElementLoad(Node* receiver, Node* receiver_map, - Node* instance_type, Node* index, Label* slow); + SloppyTNode<Int32T> instance_type, Node* index, + Label* slow); enum UseStubCache { kUseStubCache, kDontUseStubCache }; void GenericPropertyLoad(Node* receiver, Node* receiver_map, - Node* instance_type, const LoadICParameters* p, - Label* slow, + SloppyTNode<Int32T> instance_type, + const LoadICParameters* p, Label* slow, UseStubCache use_stub_cache = kUseStubCache); // Low-level helpers. @@ -263,11 +266,13 @@ class AccessorAssembler : public CodeStubAssembler { Node* intptr_index, Node* is_jsarray_condition, Label* miss); void EmitElementLoad(Node* object, Node* elements, Node* elements_kind, - Node* key, Node* is_jsarray_condition, Label* if_hole, - Label* rebox_double, Variable* var_double_value, + SloppyTNode<IntPtrT> key, Node* is_jsarray_condition, + Label* if_hole, Label* rebox_double, + Variable* var_double_value, Label* unimplemented_elements_kind, Label* out_of_bounds, Label* miss, ExitPoint* exit_point); - void NameDictionaryNegativeLookup(Node* object, Node* name, Label* miss); + void NameDictionaryNegativeLookup(Node* object, SloppyTNode<Name> name, + Label* miss); // Stub cache access helpers. diff --git a/deps/v8/src/ic/binary-op-assembler.cc b/deps/v8/src/ic/binary-op-assembler.cc index 717c38e356..9016e9ba18 100644 --- a/deps/v8/src/ic/binary-op-assembler.cc +++ b/deps/v8/src/ic/binary-op-assembler.cc @@ -58,20 +58,20 @@ Node* BinaryOpAssembler::Generate_AddWithFeedback(Node* context, Node* lhs, { Comment("perform smi operation"); - // Try fast Smi addition first. - Node* pair = IntPtrAddWithOverflow(BitcastTaggedToWord(lhs), - BitcastTaggedToWord(rhs)); - Node* overflow = Projection(1, pair); - - // Check if the Smi additon overflowed. // If rhs is known to be an Smi we want to fast path Smi operation. This // is for AddSmi operation. For the normal Add operation, we want to fast // path both Smi and Number operations, so this path should not be marked // as Deferred. Label if_overflow(this, - rhs_is_smi ? Label::kDeferred : Label::kNonDeferred), - if_notoverflow(this); - Branch(overflow, &if_overflow, &if_notoverflow); + rhs_is_smi ? Label::kDeferred : Label::kNonDeferred); + TNode<Smi> smi_result = TrySmiAdd(CAST(lhs), CAST(rhs), &if_overflow); + // Not overflowed. + { + var_type_feedback.Bind( + SmiConstant(BinaryOperationFeedback::kSignedSmall)); + var_result.Bind(smi_result); + Goto(&end); + } BIND(&if_overflow); { @@ -79,14 +79,6 @@ Node* BinaryOpAssembler::Generate_AddWithFeedback(Node* context, Node* lhs, var_fadd_rhs.Bind(SmiToFloat64(rhs)); Goto(&do_fadd); } - - BIND(&if_notoverflow); - { - var_type_feedback.Bind( - SmiConstant(BinaryOperationFeedback::kSignedSmall)); - var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair))); - Goto(&end); - } } } @@ -416,34 +408,22 @@ Node* BinaryOpAssembler::Generate_SubtractWithFeedback(Node* context, Node* lhs, Node* feedback_vector, bool rhs_is_smi) { auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) { - VARIABLE(var_result, MachineRepresentation::kTagged); - // Try a fast Smi subtraction first. - Node* pair = IntPtrSubWithOverflow(BitcastTaggedToWord(lhs), - BitcastTaggedToWord(rhs)); - Node* overflow = Projection(1, pair); - - // Check if the Smi subtraction overflowed. - Label if_notoverflow(this), end(this); + Label end(this); + TVARIABLE(Number, var_result); // If rhs is known to be an Smi (for SubSmi) we want to fast path Smi // operation. For the normal Sub operation, we want to fast path both // Smi and Number operations, so this path should not be marked as Deferred. Label if_overflow(this, rhs_is_smi ? Label::kDeferred : Label::kNonDeferred); - Branch(overflow, &if_overflow, &if_notoverflow); - - BIND(&if_notoverflow); - { - var_type_feedback->Bind( - SmiConstant(BinaryOperationFeedback::kSignedSmall)); - var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair))); - Goto(&end); - } + var_result = TrySmiSub(CAST(lhs), CAST(rhs), &if_overflow); + var_type_feedback->Bind(SmiConstant(BinaryOperationFeedback::kSignedSmall)); + Goto(&end); BIND(&if_overflow); { var_type_feedback->Bind(SmiConstant(BinaryOperationFeedback::kNumber)); Node* value = Float64Sub(SmiToFloat64(lhs), SmiToFloat64(rhs)); - var_result.Bind(AllocateHeapNumberWithValue(value)); + var_result = AllocateHeapNumberWithValue(value); Goto(&end); } @@ -463,7 +443,7 @@ Node* BinaryOpAssembler::Generate_MultiplyWithFeedback(Node* context, Node* lhs, Node* feedback_vector, bool rhs_is_smi) { auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) { - Node* result = SmiMul(lhs, rhs); + TNode<Number> result = SmiMul(CAST(lhs), CAST(rhs)); var_type_feedback->Bind(SelectSmiConstant( TaggedIsSmi(result), BinaryOperationFeedback::kSignedSmall, BinaryOperationFeedback::kNumber)); @@ -487,7 +467,7 @@ Node* BinaryOpAssembler::Generate_DivideWithFeedback( // Smi and Number operations, so this path should not be marked as Deferred. Label bailout(this, rhs_is_smi ? Label::kDeferred : Label::kNonDeferred), end(this); - var_result.Bind(TrySmiDiv(lhs, rhs, &bailout)); + var_result.Bind(TrySmiDiv(CAST(lhs), CAST(rhs), &bailout)); var_type_feedback->Bind(SmiConstant(BinaryOperationFeedback::kSignedSmall)); Goto(&end); @@ -515,7 +495,7 @@ Node* BinaryOpAssembler::Generate_ModulusWithFeedback( Node* context, Node* dividend, Node* divisor, Node* slot_id, Node* feedback_vector, bool rhs_is_smi) { auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) { - Node* result = SmiMod(lhs, rhs); + TNode<Number> result = SmiMod(CAST(lhs), CAST(rhs)); var_type_feedback->Bind(SelectSmiConstant( TaggedIsSmi(result), BinaryOperationFeedback::kSignedSmall, BinaryOperationFeedback::kNumber)); diff --git a/deps/v8/src/ic/handler-configuration-inl.h b/deps/v8/src/ic/handler-configuration-inl.h index 08054ef498..e4d3d33c40 100644 --- a/deps/v8/src/ic/handler-configuration-inl.h +++ b/deps/v8/src/ic/handler-configuration-inl.h @@ -187,14 +187,6 @@ Handle<Smi> StoreHandler::StoreApiSetter(Isolate* isolate, return handle(Smi::FromInt(config), isolate); } -// static -WeakCell* StoreHandler::GetTransitionCell(Object* handler) { - DCHECK(handler->IsStoreHandler()); - WeakCell* cell = WeakCell::cast(StoreHandler::cast(handler)->data1()); - DCHECK(!cell->cleared()); - return cell; -} - } // namespace internal } // namespace v8 diff --git a/deps/v8/src/ic/handler-configuration.cc b/deps/v8/src/ic/handler-configuration.cc index 7a5d6a46f7..bd4ba68c34 100644 --- a/deps/v8/src/ic/handler-configuration.cc +++ b/deps/v8/src/ic/handler-configuration.cc @@ -162,10 +162,10 @@ Handle<Object> LoadHandler::LoadFullChain(Isolate* isolate, } // static -KeyedAccessLoadMode LoadHandler::GetKeyedAccessLoadMode(Object* handler) { +KeyedAccessLoadMode LoadHandler::GetKeyedAccessLoadMode(MaybeObject* handler) { DisallowHeapAllocation no_gc; if (handler->IsSmi()) { - int const raw_handler = Smi::cast(handler)->value(); + int const raw_handler = Smi::cast(handler->ToSmi())->value(); Kind const kind = KindBits::decode(raw_handler); if ((kind == kElement || kind == kIndexedString) && AllowOutOfBoundsBits::decode(raw_handler)) { @@ -195,8 +195,8 @@ Handle<Object> StoreHandler::StoreElementTransition( return handler; } -Handle<Object> StoreHandler::StoreTransition(Isolate* isolate, - Handle<Map> transition_map) { +MaybeObjectHandle StoreHandler::StoreTransition(Isolate* isolate, + Handle<Map> transition_map) { bool is_dictionary_map = transition_map->is_dictionary_map(); #ifdef DEBUG if (!is_dictionary_map) { @@ -229,15 +229,14 @@ Handle<Object> StoreHandler::StoreTransition(Isolate* isolate, int config = KindBits::encode(kNormal) | LookupOnReceiverBits::encode(true); handler->set_smi_handler(Smi::FromInt(config)); handler->set_validity_cell(*validity_cell); - return handler; + return MaybeObjectHandle(handler); } else { // Ensure the transition map contains a valid prototype validity cell. if (!validity_cell.is_null()) { transition_map->set_prototype_validity_cell(*validity_cell); } - Handle<WeakCell> cell = Map::WeakCellForMap(transition_map); - return cell; + return MaybeObjectHandle::Weak(transition_map); } } @@ -270,9 +269,9 @@ Handle<Object> StoreHandler::StoreThroughPrototype( } // static -Handle<Object> StoreHandler::StoreGlobal(Isolate* isolate, - Handle<PropertyCell> cell) { - return isolate->factory()->NewWeakCell(cell); +MaybeObjectHandle StoreHandler::StoreGlobal(Isolate* isolate, + Handle<PropertyCell> cell) { + return MaybeObjectHandle::Weak(cell); } // static @@ -287,35 +286,5 @@ Handle<Object> StoreHandler::StoreProxy(Isolate* isolate, holder_cell); } -Object* StoreHandler::ValidHandlerOrNull(Object* raw_handler, Name* name, - Handle<Map>* out_transition) { - Smi* valid = Smi::FromInt(Map::kPrototypeChainValid); - - DCHECK(raw_handler->IsStoreHandler()); - - // Check validity cell. - StoreHandler* handler = StoreHandler::cast(raw_handler); - - Object* raw_validity_cell = handler->validity_cell(); - // |raw_valitity_cell| can be Smi::kZero if no validity cell is required - // (which counts as valid). - if (raw_validity_cell->IsCell() && - Cell::cast(raw_validity_cell)->value() != valid) { - return nullptr; - } - // We use this ValidHandlerOrNull() function only for transitioning store - // handlers which are not applicable to receivers that require access checks. - DCHECK(handler->smi_handler()->IsSmi()); - DCHECK( - !DoAccessCheckOnReceiverBits::decode(Smi::ToInt(handler->smi_handler()))); - - // Check if the transition target is deprecated. - WeakCell* target_cell = GetTransitionCell(raw_handler); - Map* transition = Map::cast(target_cell->value()); - if (transition->is_deprecated()) return nullptr; - *out_transition = handle(transition); - return raw_handler; -} - } // namespace internal } // namespace v8 diff --git a/deps/v8/src/ic/handler-configuration.h b/deps/v8/src/ic/handler-configuration.h index 67f7a1d08e..4807ad695d 100644 --- a/deps/v8/src/ic/handler-configuration.h +++ b/deps/v8/src/ic/handler-configuration.h @@ -175,7 +175,7 @@ class LoadHandler final : public DataHandler { KeyedAccessLoadMode load_mode); // Decodes the KeyedAccessLoadMode from a {handler}. - static KeyedAccessLoadMode GetKeyedAccessLoadMode(Object* handler); + static KeyedAccessLoadMode GetKeyedAccessLoadMode(MaybeObject* handler); }; // A set of bit fields representing Smi handlers for stores and a HeapObject @@ -243,18 +243,14 @@ class StoreHandler final : public DataHandler { // Make sure we don't overflow the smi. STATIC_ASSERT(FieldIndexBits::kNext <= kSmiValueSize); - static inline WeakCell* GetTransitionCell(Object* handler); - static Object* ValidHandlerOrNull(Object* handler, Name* name, - Handle<Map>* out_transition); - // Creates a Smi-handler for storing a field to fast object. static inline Handle<Smi> StoreField(Isolate* isolate, int descriptor, FieldIndex field_index, PropertyConstness constness, Representation representation); - static Handle<Object> StoreTransition(Isolate* isolate, - Handle<Map> transition_map); + static MaybeObjectHandle StoreTransition(Isolate* isolate, + Handle<Map> transition_map); // Creates a Smi-handler for storing a native data property on a fast object. static inline Handle<Smi> StoreNativeDataProperty(Isolate* isolate, @@ -284,8 +280,8 @@ class StoreHandler final : public DataHandler { // Creates a handler for storing a property to the property cell of a global // object. - static Handle<Object> StoreGlobal(Isolate* isolate, - Handle<PropertyCell> cell); + static MaybeObjectHandle StoreGlobal(Isolate* isolate, + Handle<PropertyCell> cell); // Creates a Smi-handler for storing a property to a global proxy object. static inline Handle<Smi> StoreGlobalProxy(Isolate* isolate); diff --git a/deps/v8/src/ic/ic-inl.h b/deps/v8/src/ic/ic-inl.h index 83ab9d86b8..835b39efda 100644 --- a/deps/v8/src/ic/ic-inl.h +++ b/deps/v8/src/ic/ic-inl.h @@ -26,7 +26,7 @@ Address IC::constant_pool() const { if (FLAG_enable_embedded_constant_pool) { return raw_constant_pool(); } else { - return nullptr; + return kNullAddress; } } @@ -35,14 +35,22 @@ Address IC::raw_constant_pool() const { if (FLAG_enable_embedded_constant_pool) { return *constant_pool_address_; } else { - return nullptr; + return kNullAddress; } } - -bool IC::IsHandler(Object* object) { - return (object->IsSmi() && (object != nullptr)) || object->IsDataHandler() || - object->IsWeakCell() || object->IsCode(); +bool IC::IsHandler(MaybeObject* object, bool from_stub_cache) { + HeapObject* heap_object; + return (object->IsSmi() && (object != nullptr)) || + (object->ToWeakHeapObject(&heap_object) && + (heap_object->IsMap() || heap_object->IsPropertyCell())) || + (object->ToStrongHeapObject(&heap_object) && + (heap_object->IsDataHandler() || + (from_stub_cache && heap_object->IsWeakCell() && + (WeakCell::cast(heap_object)->cleared() || + WeakCell::cast(heap_object)->value()->IsMap() || + WeakCell::cast(heap_object)->value()->IsPropertyCell())) || + heap_object->IsCode())); } bool IC::AddressIsDeoptimizedCode() const { diff --git a/deps/v8/src/ic/ic.cc b/deps/v8/src/ic/ic.cc index 8924723951..b11bc9de98 100644 --- a/deps/v8/src/ic/ic.cc +++ b/deps/v8/src/ic/ic.cc @@ -20,6 +20,8 @@ #include "src/ic/stub-cache.h" #include "src/isolate-inl.h" #include "src/macro-assembler.h" +#include "src/objects/api-callbacks.h" +#include "src/objects/hash-table-inl.h" #include "src/prototype.h" #include "src/runtime-profiler.h" #include "src/runtime/runtime-utils.h" @@ -147,9 +149,7 @@ void IC::TraceIC(const char* type, Handle<Object> name, State old_state, ICStats::instance()->End(); } - -IC::IC(FrameDepth depth, Isolate* isolate, Handle<FeedbackVector> vector, - FeedbackSlot slot) +IC::IC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot) : isolate_(isolate), vector_set_(false), kind_(FeedbackSlotKind::kInvalid), @@ -168,21 +168,9 @@ IC::IC(FrameDepth depth, Isolate* isolate, Handle<FeedbackVector> vector, Address* pc_address = reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); - // If there's another JavaScript frame on the stack we need to look one frame - // further down the stack to find the frame pointer and the return address - // stack slot. - if (depth == EXTRA_CALL_FRAME) { - if (FLAG_enable_embedded_constant_pool) { - constant_pool = reinterpret_cast<Address*>( - fp + StandardFrameConstants::kConstantPoolOffset); - } - const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; - pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); - fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); - } #ifdef DEBUG StackFrameIterator it(isolate); - for (int i = 0; i < depth + 1; i++) it.Advance(); + for (int i = 0; i < 1; i++) it.Advance(); StackFrame* frame = it.frame(); DCHECK(fp == frame->fp() && pc_address == frame->pc_address()); #endif @@ -400,6 +388,11 @@ bool IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) { void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, Handle<Object> handler) { + ConfigureVectorState(name, map, MaybeObjectHandle(handler)); +} + +void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, + const MaybeObjectHandle& handler) { if (IsGlobalIC()) { nexus()->ConfigureHandlerMode(handler); } else { @@ -414,7 +407,7 @@ void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, } void IC::ConfigureVectorState(Handle<Name> name, MapHandles const& maps, - ObjectHandles* handlers) { + MaybeObjectHandles* handlers) { DCHECK(!IsGlobalIC()); // Non-keyed ICs don't track the name explicitly. if (!is_keyed()) name = Handle<Name>::null(); @@ -534,14 +527,15 @@ static bool AddOneReceiverMapIfMissing(MapHandles* receiver_maps, return true; } -bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> handler) { +bool IC::UpdatePolymorphicIC(Handle<Name> name, + const MaybeObjectHandle& handler) { DCHECK(IsHandler(*handler)); if (is_keyed() && state() != RECOMPUTE_HANDLER) { if (nexus()->FindFirstName() != *name) return false; } Handle<Map> map = receiver_map(); MapHandles maps; - ObjectHandles handlers; + MaybeObjectHandles handlers; TargetMaps(&maps); int number_of_maps = static_cast<int>(maps.size()); @@ -603,7 +597,8 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> handler) { return true; } -void IC::UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name) { +void IC::UpdateMonomorphicIC(const MaybeObjectHandle& handler, + Handle<Name> name) { DCHECK(IsHandler(*handler)); ConfigureVectorState(name, receiver_map(), handler); } @@ -611,11 +606,11 @@ void IC::UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name) { void IC::CopyICToMegamorphicCache(Handle<Name> name) { MapHandles maps; - ObjectHandles handlers; + MaybeObjectHandles handlers; TargetMaps(&maps); if (!nexus()->FindHandlers(&handlers, static_cast<int>(maps.size()))) return; for (int i = 0; i < static_cast<int>(maps.size()); i++) { - UpdateMegamorphicCache(*maps.at(i), *name, *handlers.at(i)); + UpdateMegamorphicCache(maps.at(i), name, handlers.at(i)); } } @@ -637,6 +632,10 @@ bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) { } void IC::PatchCache(Handle<Name> name, Handle<Object> handler) { + PatchCache(name, MaybeObjectHandle(handler)); +} + +void IC::PatchCache(Handle<Name> name, const MaybeObjectHandle& handler) { DCHECK(IsHandler(*handler)); // Currently only load and store ICs support non-code handlers. DCHECK(IsAnyLoad() || IsAnyStore()); @@ -660,7 +659,7 @@ void IC::PatchCache(Handle<Name> name, Handle<Object> handler) { ConfigureVectorState(MEGAMORPHIC, name); V8_FALLTHROUGH; case MEGAMORPHIC: - UpdateMegamorphicCache(*receiver_map(), *name, *handler); + UpdateMegamorphicCache(receiver_map(), name, handler); // Indicate that we've handled this case. vector_set_ = true; break; @@ -719,8 +718,23 @@ StubCache* IC::stub_cache() { } } -void IC::UpdateMegamorphicCache(Map* map, Name* name, Object* handler) { - stub_cache()->Set(name, map, handler); +void IC::UpdateMegamorphicCache(Handle<Map> map, Handle<Name> name, + const MaybeObjectHandle& handler) { + HeapObject* heap_object; + if (handler->ToWeakHeapObject(&heap_object)) { + // TODO(marja): remove this conversion once megamorphic stub cache supports + // weak handlers. + Handle<Object> weak_cell; + if (heap_object->IsMap()) { + weak_cell = Map::WeakCellForMap(handle(Map::cast(heap_object))); + } else { + weak_cell = isolate_->factory()->NewWeakCell( + handle(PropertyCell::cast(heap_object))); + } + stub_cache()->Set(*name, *map, *weak_cell); + } else { + stub_cache()->Set(*name, *map, handler->ToObject()); + } } void IC::TraceHandlerCacheHitStats(LookupIterator* lookup) { @@ -889,7 +903,7 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) { Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); - if (v8::ToCData<Address>(info->getter()) == nullptr || + if (v8::ToCData<Address>(info->getter()) == kNullAddress || !AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map) || !holder->HasFastProperties() || (info->is_sloppy() && !receiver->IsJSReceiver())) { @@ -974,9 +988,13 @@ static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { if (std::isnan(value)) { key = isolate->factory()->NaN_string(); } else { - int int_value = FastD2I(value); - if (value == int_value && Smi::IsValid(int_value)) { - key = handle(Smi::FromInt(int_value), isolate); + // Check bounds first to avoid undefined behavior in the conversion + // to int. + if (value <= Smi::kMaxValue && value >= Smi::kMinValue) { + int int_value = FastD2I(value); + if (value == int_value) { + key = handle(Smi::FromInt(int_value), isolate); + } } } } else if (key->IsString()) { @@ -986,9 +1004,9 @@ static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { } bool KeyedLoadIC::CanChangeToAllowOutOfBounds(Handle<Map> receiver_map) { - Handle<Object> handler; - return nexus()->FindHandlerForMap(receiver_map).ToHandle(&handler) && - LoadHandler::GetKeyedAccessLoadMode(*handler) == STANDARD_LOAD; + const MaybeObjectHandle& handler = nexus()->FindHandlerForMap(receiver_map); + if (handler.is_null()) return false; + return LoadHandler::GetKeyedAccessLoadMode(*handler) == STANDARD_LOAD; } void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver, @@ -1055,7 +1073,7 @@ void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver, return; } - ObjectHandles handlers; + MaybeObjectHandles handlers; handlers.reserve(target_receiver_maps.size()); LoadElementPolymorphicHandlers(&target_receiver_maps, &handlers, load_mode); DCHECK_LE(1, target_receiver_maps.size()); @@ -1113,7 +1131,7 @@ Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map, } void KeyedLoadIC::LoadElementPolymorphicHandlers( - MapHandles* receiver_maps, ObjectHandles* handlers, + MapHandles* receiver_maps, MaybeObjectHandles* handlers, KeyedAccessLoadMode load_mode) { // Filter out deprecated maps to ensure their instances get migrated. receiver_maps->erase( @@ -1132,12 +1150,37 @@ void KeyedLoadIC::LoadElementPolymorphicHandlers( receiver_map->NotifyLeafMapLayoutChange(); } } - handlers->push_back(LoadElementHandler(receiver_map, load_mode)); + handlers->push_back( + MaybeObjectHandle(LoadElementHandler(receiver_map, load_mode))); } } namespace { +bool ConvertKeyToIndex(Handle<Object> receiver, Handle<Object> key, + uint32_t* index) { + if (!FLAG_use_ic) return false; + if (receiver->IsAccessCheckNeeded() || receiver->IsJSValue()) return false; + + // For regular JSReceiver or String receivers, the {key} must be a positive + // array index. + if (receiver->IsJSReceiver() || receiver->IsString()) { + return key->ToArrayIndex(index); + } + // For JSTypedArray receivers, we can also support negative keys, which we + // just map into the [2**31, 2**32 - 1] range via a bit_cast. This is valid + // because JSTypedArray::length is always a Smi, so such keys will always + // be detected as OOB. + if (receiver->IsJSTypedArray()) { + int32_t signed_index; + if (key->ToInt32(&signed_index)) { + *index = bit_cast<uint32_t>(signed_index); + return true; + } + } + return false; +} + bool IsOutOfBoundsAccess(Handle<Object> receiver, uint32_t index) { uint32_t length = 0; if (receiver->IsJSArray()) { @@ -1210,21 +1253,11 @@ MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, ASSIGN_RETURN_ON_EXCEPTION(isolate(), load_handle, LoadIC::Load(object, Handle<Name>::cast(key)), Object); - } else if (FLAG_use_ic && !object->IsAccessCheckNeeded() && - !object->IsJSValue()) { - // For regular JSReceiver or String {object}s the {key} must be a positive - // array index, for JSTypedArray {object}s we can also support negative - // {key}s which we just map into the [2*31,2*32-1] range (via a bit_cast). - // This is valid since JSTypedArray::length is always a Smi. - if (((object->IsJSReceiver() || object->IsString()) && - key->ToArrayIndex(&index)) || - (object->IsJSTypedArray() && - key->ToInt32(bit_cast<int32_t*>(&index)))) { - KeyedAccessLoadMode load_mode = GetLoadMode(object, index); - UpdateLoadElement(Handle<HeapObject>::cast(object), load_mode); - if (is_vector_set()) { - TraceIC("LoadIC", key); - } + } else if (ConvertKeyToIndex(object, key, &index)) { + KeyedAccessLoadMode load_mode = GetLoadMode(object, index); + UpdateLoadElement(Handle<HeapObject>::cast(object), load_mode); + if (is_vector_set()) { + TraceIC("LoadIC", key); } } @@ -1422,7 +1455,7 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, return; } - Handle<Object> handler; + MaybeObjectHandle handler; if (LookupForWrite(lookup, value, store_mode)) { if (IsStoreGlobalIC()) { if (lookup->state() == LookupIterator::DATA && @@ -1437,14 +1470,15 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, handler = ComputeHandler(lookup); } else { set_slow_stub_reason("LookupForWrite said 'false'"); - handler = slow_stub(); + // TODO(marja): change slow_stub to return MaybeObjectHandle. + handler = MaybeObjectHandle(slow_stub()); } PatchCache(lookup->name(), handler); TraceIC("StoreIC", lookup->name()); } -Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) { +MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) { switch (lookup->state()) { case LookupIterator::TRANSITION: { Handle<JSObject> store_target = lookup->GetStoreTarget<JSObject>(); @@ -1467,7 +1501,7 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) { isolate()->factory()->NewWeakCell(lookup->transition_cell()); Handle<Object> handler = StoreHandler::StoreThroughPrototype( isolate(), receiver_map(), store_target, smi_handler, cell); - return handler; + return MaybeObjectHandle(handler); } // Dictionary-to-fast transitions are not expected and not supported. DCHECK_IMPLIES(!lookup->transition_map()->is_dictionary_map(), @@ -1485,7 +1519,7 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) { DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined(isolate())); TRACE_HANDLER_STATS(isolate(), StoreIC_StoreInterceptorStub); StoreInterceptorStub stub(isolate()); - return stub.GetCode(); + return MaybeObjectHandle(stub.GetCode()); } case LookupIterator::ACCESSOR: { @@ -1497,37 +1531,39 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) { if (!holder->HasFastProperties()) { set_slow_stub_reason("accessor on slow map"); TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); - return slow_stub(); + return MaybeObjectHandle(slow_stub()); } Handle<Object> accessors = lookup->GetAccessors(); if (accessors->IsAccessorInfo()) { Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); - if (v8::ToCData<Address>(info->setter()) == nullptr) { - set_slow_stub_reason("setter == nullptr"); + if (v8::ToCData<Address>(info->setter()) == kNullAddress) { + set_slow_stub_reason("setter == kNullAddress"); TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); - return slow_stub(); + return MaybeObjectHandle(slow_stub()); } if (AccessorInfo::cast(*accessors)->is_special_data_property() && !lookup->HolderIsReceiverOrHiddenPrototype()) { set_slow_stub_reason("special data property in prototype chain"); TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); - return slow_stub(); + return MaybeObjectHandle(slow_stub()); } if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info, receiver_map())) { set_slow_stub_reason("incompatible receiver type"); TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); - return slow_stub(); + return MaybeObjectHandle(slow_stub()); } Handle<Smi> smi_handler = StoreHandler::StoreNativeDataProperty( isolate(), lookup->GetAccessorIndex()); TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNativeDataPropertyDH); - if (receiver.is_identical_to(holder)) return smi_handler; + if (receiver.is_identical_to(holder)) { + return MaybeObjectHandle(smi_handler); + } TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNativeDataPropertyOnPrototypeDH); - return StoreHandler::StoreThroughPrototype(isolate(), receiver_map(), - holder, smi_handler); + return MaybeObjectHandle(StoreHandler::StoreThroughPrototype( + isolate(), receiver_map(), holder, smi_handler)); } else if (accessors->IsAccessorPair()) { Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(), @@ -1535,14 +1571,14 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) { if (!setter->IsJSFunction() && !setter->IsFunctionTemplateInfo()) { set_slow_stub_reason("setter not a function"); TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); - return slow_stub(); + return MaybeObjectHandle(slow_stub()); } if (setter->IsFunctionTemplateInfo() && FunctionTemplateInfo::cast(*setter)->BreakAtEntry()) { // Do not install an IC if the api function has a breakpoint. TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); - return slow_stub(); + return MaybeObjectHandle(slow_stub()); } CallOptimization call_optimization(setter); @@ -1563,31 +1599,33 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) { Handle<WeakCell> data_cell = isolate()->factory()->NewWeakCell( call_optimization.api_call_info()); TRACE_HANDLER_STATS(isolate(), StoreIC_StoreApiSetterOnPrototypeDH); - return StoreHandler::StoreThroughPrototype( + return MaybeObjectHandle(StoreHandler::StoreThroughPrototype( isolate(), receiver_map(), holder, smi_handler, data_cell, - context_cell); + context_cell)); } set_slow_stub_reason("incompatible receiver"); TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); - return slow_stub(); + return MaybeObjectHandle(slow_stub()); } else if (setter->IsFunctionTemplateInfo()) { set_slow_stub_reason("setter non-simple template"); TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); - return slow_stub(); + return MaybeObjectHandle(slow_stub()); } Handle<Smi> smi_handler = StoreHandler::StoreAccessor(isolate(), lookup->GetAccessorIndex()); TRACE_HANDLER_STATS(isolate(), StoreIC_StoreAccessorDH); - if (receiver.is_identical_to(holder)) return smi_handler; + if (receiver.is_identical_to(holder)) { + return MaybeObjectHandle(smi_handler); + } TRACE_HANDLER_STATS(isolate(), StoreIC_StoreAccessorOnPrototypeDH); - return StoreHandler::StoreThroughPrototype(isolate(), receiver_map(), - holder, smi_handler); + return MaybeObjectHandle(StoreHandler::StoreThroughPrototype( + isolate(), receiver_map(), holder, smi_handler)); } TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); - return slow_stub(); + return MaybeObjectHandle(slow_stub()); } case LookupIterator::DATA: { @@ -1601,12 +1639,12 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) { if (lookup->is_dictionary_holder()) { if (holder->IsJSGlobalObject()) { TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalDH); - return StoreHandler::StoreGlobal(isolate(), - lookup->GetPropertyCell()); + return MaybeObjectHandle( + StoreHandler::StoreGlobal(isolate(), lookup->GetPropertyCell())); } TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormalDH); DCHECK(holder.is_identical_to(receiver)); - return StoreHandler::StoreNormal(isolate()); + return MaybeObjectHandle(StoreHandler::StoreNormal(isolate())); } // -------------- Fields -------------- @@ -1620,22 +1658,22 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) { // we must store the value unconditionally even to kConst fields. constness = kMutable; } - return StoreHandler::StoreField(isolate(), descriptor, index, constness, - lookup->representation()); + return MaybeObjectHandle(StoreHandler::StoreField( + isolate(), descriptor, index, constness, lookup->representation())); } // -------------- Constant properties -------------- DCHECK_EQ(kDescriptor, lookup->property_details().location()); set_slow_stub_reason("constant property"); TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); - return slow_stub(); + return MaybeObjectHandle(slow_stub()); } case LookupIterator::JSPROXY: { Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(lookup->GetReceiver()); Handle<JSProxy> holder = lookup->GetHolder<JSProxy>(); - return StoreHandler::StoreProxy(isolate(), receiver_map(), holder, - receiver); + return MaybeObjectHandle(StoreHandler::StoreProxy( + isolate(), receiver_map(), holder, receiver)); } case LookupIterator::INTEGER_INDEXED_EXOTIC: @@ -1643,7 +1681,7 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) { case LookupIterator::NOT_FOUND: UNREACHABLE(); } - return Handle<Code>::null(); + return MaybeObjectHandle(); } void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map, @@ -1761,7 +1799,7 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map, } } - ObjectHandles handlers; + MaybeObjectHandles handlers; handlers.reserve(target_receiver_maps.size()); StoreElementPolymorphicHandlers(&target_receiver_maps, &handlers, store_mode); if (target_receiver_maps.size() == 0) { @@ -1853,7 +1891,7 @@ Handle<Object> KeyedStoreIC::StoreElementHandler( } void KeyedStoreIC::StoreElementPolymorphicHandlers( - MapHandles* receiver_maps, ObjectHandles* handlers, + MapHandles* receiver_maps, MaybeObjectHandles* handlers, KeyedAccessStoreMode store_mode) { DCHECK(store_mode == STANDARD_STORE || store_mode == STORE_AND_GROW_NO_TRANSITION_HANDLE_COW || @@ -1905,7 +1943,7 @@ void KeyedStoreIC::StoreElementPolymorphicHandlers( } } DCHECK(!handler.is_null()); - handlers->push_back(handler); + handlers->push_back(MaybeObjectHandle(handler)); } } diff --git a/deps/v8/src/ic/ic.h b/deps/v8/src/ic/ic.h index 020b8dcd26..22f3cb9c26 100644 --- a/deps/v8/src/ic/ic.h +++ b/deps/v8/src/ic/ic.h @@ -14,6 +14,7 @@ #include "src/macro-assembler.h" #include "src/messages.h" #include "src/objects/map.h" +#include "src/objects/maybe-object.h" namespace v8 { namespace internal { @@ -26,10 +27,6 @@ class IC { // Alias the inline cache state type to make the IC code more readable. typedef InlineCacheState State; - // The IC code is either invoked with no extra frames on the stack - // or with a single extra frame for supporting calls. - enum FrameDepth { NO_EXTRA_FRAME = 0, EXTRA_CALL_FRAME = 1 }; - static constexpr int kMaxKeyedPolymorphism = 4; // A polymorphic IC can handle at most 4 distinct maps before transitioning @@ -38,8 +35,7 @@ class IC { // Construct the IC structure with the given number of extra // JavaScript frames on the stack. - IC(FrameDepth depth, Isolate* isolate, Handle<FeedbackVector> vector, - FeedbackSlot slot); + IC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot); virtual ~IC() {} State state() const { return state_; } @@ -63,7 +59,8 @@ class IC { IsKeyedStoreIC() || IsStoreInArrayLiteralICKind(kind()); } - static inline bool IsHandler(Object* object); + static inline bool IsHandler(MaybeObject* object, + bool from_stub_cache = false); // Nofity the IC system that a feedback has changed. static void OnFeedbackChanged(Isolate* isolate, FeedbackVector* vector, @@ -92,7 +89,7 @@ class IC { bool vector_needs_update() { return (!vector_set_ && (state() != MEGAMORPHIC || - Smi::ToInt(nexus()->GetFeedbackExtra()) != ELEMENT)); + Smi::ToInt(nexus()->GetFeedbackExtra()->ToSmi()) != ELEMENT)); } // Configure for most states. @@ -100,9 +97,11 @@ class IC { // Configure the vector for MONOMORPHIC. void ConfigureVectorState(Handle<Name> name, Handle<Map> map, Handle<Object> handler); + void ConfigureVectorState(Handle<Name> name, Handle<Map> map, + const MaybeObjectHandle& handler); // Configure the vector for POLYMORPHIC. void ConfigureVectorState(Handle<Name> name, MapHandles const& maps, - ObjectHandles* handlers); + MaybeObjectHandles* handlers); char TransitionMarkFromState(IC::State state); void TraceIC(const char* type, Handle<Object> name); @@ -115,15 +114,17 @@ class IC { void TraceHandlerCacheHitStats(LookupIterator* lookup); - void UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name); - bool UpdatePolymorphicIC(Handle<Name> name, Handle<Object> code); - void UpdateMegamorphicCache(Map* map, Name* name, Object* code); + void UpdateMonomorphicIC(const MaybeObjectHandle& handler, Handle<Name> name); + bool UpdatePolymorphicIC(Handle<Name> name, const MaybeObjectHandle& handler); + void UpdateMegamorphicCache(Handle<Map> map, Handle<Name> name, + const MaybeObjectHandle& handler); StubCache* stub_cache(); void CopyICToMegamorphicCache(Handle<Name> name); bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map); - void PatchCache(Handle<Name> name, Handle<Object> code); + void PatchCache(Handle<Name> name, Handle<Object> handler); + void PatchCache(Handle<Name> name, const MaybeObjectHandle& handler); FeedbackSlotKind kind() const { return kind_; } bool IsGlobalIC() const { return IsLoadGlobalIC() || IsStoreGlobalIC(); } bool IsLoadIC() const { return IsLoadICKind(kind_); } @@ -197,7 +198,7 @@ class IC { State state_; FeedbackSlotKind kind_; Handle<Map> receiver_map_; - MaybeHandle<Object> maybe_handler_; + MaybeObjectHandle maybe_handler_; MapHandles target_maps_; bool target_maps_set_; @@ -210,17 +211,10 @@ class IC { }; -class CallIC : public IC { - public: - CallIC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot) - : IC(EXTRA_CALL_FRAME, isolate, vector, slot) {} -}; - - class LoadIC : public IC { public: LoadIC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot) - : IC(NO_EXTRA_FRAME, isolate, vector, slot) { + : IC(isolate, vector, slot) { DCHECK(IsAnyLoad()); } @@ -286,7 +280,7 @@ class KeyedLoadIC : public LoadIC { KeyedAccessLoadMode load_mode); void LoadElementPolymorphicHandlers(MapHandles* receiver_maps, - ObjectHandles* handlers, + MaybeObjectHandles* handlers, KeyedAccessLoadMode load_mode); // Returns true if the receiver_map has a kElement or kIndexedString @@ -299,7 +293,7 @@ class KeyedLoadIC : public LoadIC { class StoreIC : public IC { public: StoreIC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot) - : IC(NO_EXTRA_FRAME, isolate, vector, slot) { + : IC(isolate, vector, slot) { DCHECK(IsAnyStore()); } @@ -326,7 +320,7 @@ class StoreIC : public IC { JSReceiver::StoreFromKeyed store_mode); private: - Handle<Object> ComputeHandler(LookupIterator* lookup); + MaybeObjectHandle ComputeHandler(LookupIterator* lookup); friend class IC; }; @@ -383,7 +377,7 @@ class KeyedStoreIC : public StoreIC { KeyedAccessStoreMode store_mode); void StoreElementPolymorphicHandlers(MapHandles* receiver_maps, - ObjectHandles* handlers, + MaybeObjectHandles* handlers, KeyedAccessStoreMode store_mode); friend class IC; diff --git a/deps/v8/src/ic/keyed-store-generic.cc b/deps/v8/src/ic/keyed-store-generic.cc index f2f161f3b6..13eaee8e2b 100644 --- a/deps/v8/src/ic/keyed-store-generic.cc +++ b/deps/v8/src/ic/keyed-store-generic.cc @@ -16,7 +16,9 @@ namespace v8 { namespace internal { -using compiler::Node; +using Node = compiler::Node; +template <class T> +using TNode = compiler::TNode<T>; class KeyedStoreGenericAssembler : public AccessorAssembler { public: @@ -27,6 +29,12 @@ class KeyedStoreGenericAssembler : public AccessorAssembler { void StoreIC_Uninitialized(); + // Generates code for [[Set]] operation, the |unique_name| is supposed to be + // unique otherwise this code will always go to runtime. + void SetProperty(TNode<Context> context, TNode<JSReceiver> receiver, + TNode<BoolT> is_simple_receiver, TNode<Name> unique_name, + TNode<Object> value, LanguageMode language_mode); + private: enum UpdateLength { kDontChangeLength, @@ -40,15 +48,20 @@ class KeyedStoreGenericAssembler : public AccessorAssembler { Node* instance_type, Node* intptr_index, Node* value, Node* context, Label* slow); - void EmitGenericPropertyStore(Node* receiver, Node* receiver_map, + // If language mode is not provided it is deduced from the feedback slot's + // kind. + void EmitGenericPropertyStore(TNode<JSReceiver> receiver, + TNode<Map> receiver_map, const StoreICParameters* p, ExitPoint* exit_point, Label* slow, - bool assume_strict_language_mode = false); + Maybe<LanguageMode> maybe_language_mode); - void EmitGenericPropertyStore(Node* receiver, Node* receiver_map, + void EmitGenericPropertyStore(SloppyTNode<JSReceiver> receiver, + SloppyTNode<Map> receiver_map, const StoreICParameters* p, Label* slow) { ExitPoint direct_exit(this); - EmitGenericPropertyStore(receiver, receiver_map, p, &direct_exit, slow); + EmitGenericPropertyStore(receiver, receiver_map, p, &direct_exit, slow, + Nothing<LanguageMode>()); } void BranchIfPrototypesHaveNonFastElements(Node* receiver_map, @@ -97,6 +110,15 @@ void StoreICUninitializedGenerator::Generate( assembler.StoreIC_Uninitialized(); } +void KeyedStoreGenericGenerator::SetProperty( + compiler::CodeAssemblerState* state, TNode<Context> context, + TNode<JSReceiver> receiver, TNode<BoolT> is_simple_receiver, + TNode<Name> name, TNode<Object> value, LanguageMode language_mode) { + KeyedStoreGenericAssembler assembler(state); + assembler.SetProperty(context, receiver, is_simple_receiver, name, value, + language_mode); +} + void KeyedStoreGenericAssembler::BranchIfPrototypesHaveNonFastElements( Node* receiver_map, Label* non_fast_elements, Label* only_fast_elements) { VARIABLE(var_map, MachineRepresentation::kTagged); @@ -111,14 +133,10 @@ void KeyedStoreGenericAssembler::BranchIfPrototypesHaveNonFastElements( GotoIf(IsNull(prototype), only_fast_elements); Node* prototype_map = LoadMap(prototype); var_map.Bind(prototype_map); - Node* instance_type = LoadMapInstanceType(prototype_map); - STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE); - STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE); - GotoIf(Int32LessThanOrEqual(instance_type, - Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), + TNode<Int32T> instance_type = LoadMapInstanceType(prototype_map); + GotoIf(IsCustomElementsReceiverInstanceType(instance_type), non_fast_elements); Node* elements_kind = LoadMapElementsKind(prototype_map); - STATIC_ASSERT(FIRST_ELEMENTS_KIND == FIRST_FAST_ELEMENTS_KIND); GotoIf(IsFastElementsKind(elements_kind), &loop_body); GotoIf(Word32Equal(elements_kind, Int32Constant(NO_ELEMENTS)), &loop_body); Goto(non_fast_elements); @@ -618,8 +636,10 @@ void KeyedStoreGenericAssembler::LookupPropertyOnPrototypeChain( } void KeyedStoreGenericAssembler::EmitGenericPropertyStore( - Node* receiver, Node* receiver_map, const StoreICParameters* p, - ExitPoint* exit_point, Label* slow, bool assume_strict_language_mode) { + TNode<JSReceiver> receiver, TNode<Map> receiver_map, + const StoreICParameters* p, ExitPoint* exit_point, Label* slow, + Maybe<LanguageMode> maybe_language_mode) { + CSA_ASSERT(this, IsSimpleObjectMap(receiver_map)); VARIABLE(var_accessor_pair, MachineRepresentation::kTagged); VARIABLE(var_accessor_holder, MachineRepresentation::kTagged); Label stub_cache(this), fast_properties(this), dictionary_properties(this), @@ -668,14 +688,14 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( TVARIABLE(Map, var_transition_map); Label simple_transition(this), transition_array(this), found_handler_candidate(this); - TNode<Object> maybe_handler = - LoadObjectField(receiver_map, Map::kTransitionsOrPrototypeInfoOffset); + TNode<MaybeObject> maybe_handler = LoadMaybeWeakObjectField( + receiver_map, Map::kTransitionsOrPrototypeInfoOffset); // SMI -> slow // cleared weak reference -> slow // weak reference -> simple_transition // strong reference -> transition_array - VARIABLE(var_transition_map_or_array, MachineRepresentation::kTagged); + TVARIABLE(Object, var_transition_map_or_array); DispatchMaybeObject(maybe_handler, slow, slow, &simple_transition, &transition_array, &var_transition_map_or_array); @@ -716,10 +736,9 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( const int kKeyToTargetOffset = (TransitionArray::kEntryTargetIndex - TransitionArray::kEntryKeyIndex) * kPointerSize; - TNode<WeakCell> transition_map_weak_cell = CAST(LoadFixedArrayElement( - transitions, var_name_index.value(), kKeyToTargetOffset)); - var_transition_map = - CAST(LoadWeakCellValue(transition_map_weak_cell, slow)); + var_transition_map = CAST(ToWeakHeapObject( + LoadArrayElement(transitions, WeakFixedArray::kHeaderSize, + var_name_index.value(), kKeyToTargetOffset))); Goto(&found_handler_candidate); } } @@ -740,15 +759,16 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( // We checked for LAST_CUSTOM_ELEMENTS_RECEIVER before, which rules out // seeing global objects here (which would need special handling). - VARIABLE(var_name_index, MachineType::PointerRepresentation()); + TVARIABLE(IntPtrT, var_name_index); Label dictionary_found(this, &var_name_index), not_found(this); - Node* properties = LoadSlowProperties(receiver); - NameDictionaryLookup<NameDictionary>(properties, p->name, &dictionary_found, - &var_name_index, ¬_found); + TNode<NameDictionary> properties = CAST(LoadSlowProperties(CAST(receiver))); + NameDictionaryLookup<NameDictionary>(properties, CAST(p->name), + &dictionary_found, &var_name_index, + ¬_found); BIND(&dictionary_found); { Label overwrite(this); - Node* details = LoadDetailsByKeyIndex<NameDictionary>( + TNode<Uint32T> details = LoadDetailsByKeyIndex<NameDictionary>( properties, var_name_index.value()); JumpIfDataProperty(details, &overwrite, &readonly); @@ -781,7 +801,7 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( &readonly, slow); Label add_dictionary_property_slow(this); InvalidateValidityCellIfPrototype(receiver_map, bitfield2); - Add<NameDictionary>(properties, p->name, p->value, + Add<NameDictionary>(properties, CAST(p->name), p->value, &add_dictionary_property_slow); exit_point->Return(p->value); @@ -809,36 +829,54 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( BIND(¬_callable); { + bool handle_strict = true; Label strict(this); - if (assume_strict_language_mode) { - Goto(&strict); + LanguageMode language_mode; + if (maybe_language_mode.To(&language_mode)) { + if (language_mode == LanguageMode::kStrict) { + Goto(&strict); + } else { + handle_strict = false; + exit_point->Return(p->value); + } } else { BranchIfStrictMode(p->vector, p->slot, &strict); exit_point->Return(p->value); } - BIND(&strict); - { - ThrowTypeError(p->context, MessageTemplate::kNoSetterInCallback, - p->name, var_accessor_holder.value()); + if (handle_strict) { + BIND(&strict); + { + ThrowTypeError(p->context, MessageTemplate::kNoSetterInCallback, + p->name, var_accessor_holder.value()); + } } } } BIND(&readonly); { + bool handle_strict = true; Label strict(this); - if (assume_strict_language_mode) { - Goto(&strict); + LanguageMode language_mode; + if (maybe_language_mode.To(&language_mode)) { + if (language_mode == LanguageMode::kStrict) { + Goto(&strict); + } else { + handle_strict = false; + exit_point->Return(p->value); + } } else { BranchIfStrictMode(p->vector, p->slot, &strict); exit_point->Return(p->value); } - BIND(&strict); - { - Node* type = Typeof(p->receiver); - ThrowTypeError(p->context, MessageTemplate::kStrictReadOnlyProperty, - p->name, type, p->receiver); + if (handle_strict) { + BIND(&strict); + { + Node* type = Typeof(p->receiver); + ThrowTypeError(p->context, MessageTemplate::kStrictReadOnlyProperty, + p->name, type, p->receiver); + } } } } @@ -861,12 +899,10 @@ void KeyedStoreGenericAssembler::KeyedStoreGeneric() { GotoIf(TaggedIsSmi(receiver), &slow); Node* receiver_map = LoadMap(receiver); - Node* instance_type = LoadMapInstanceType(receiver_map); + TNode<Int32T> instance_type = LoadMapInstanceType(receiver_map); // Receivers requiring non-standard element accesses (interceptors, access // checks, strings and string wrappers, proxies) are handled in the runtime. - GotoIf(Int32LessThanOrEqual(instance_type, - Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), - &slow); + GotoIf(IsCustomElementsReceiverInstanceType(instance_type), &slow); TryToName(name, &if_index, &var_index, &if_unique_name, &var_unique, &slow, ¬_internalized); @@ -925,7 +961,7 @@ void KeyedStoreGenericAssembler::StoreIC_Uninitialized() { GotoIf(TaggedIsSmi(receiver), &miss); Node* receiver_map = LoadMap(receiver); - Node* instance_type = LoadMapInstanceType(receiver_map); + TNode<Int32T> instance_type = LoadMapInstanceType(receiver_map); // Receivers requiring non-standard element accesses (interceptors, access // checks, strings and string wrappers, proxies) are handled in the runtime. GotoIf(IsSpecialReceiverInstanceType(instance_type), &miss); @@ -949,5 +985,33 @@ void KeyedStoreGenericAssembler::StoreIC_Uninitialized() { } } +void KeyedStoreGenericAssembler::SetProperty(TNode<Context> context, + TNode<JSReceiver> receiver, + TNode<BoolT> is_simple_receiver, + TNode<Name> unique_name, + TNode<Object> value, + LanguageMode language_mode) { + StoreICParameters p(context, receiver, unique_name, value, nullptr, nullptr); + + Label done(this), slow(this, Label::kDeferred); + ExitPoint exit_point(this, [&](Node* result) { Goto(&done); }); + + CSA_ASSERT(this, Word32Equal(is_simple_receiver, + IsSimpleObjectMap(LoadMap(receiver)))); + GotoIfNot(is_simple_receiver, &slow); + + EmitGenericPropertyStore(receiver, LoadMap(receiver), &p, &exit_point, &slow, + Just(language_mode)); + + BIND(&slow); + { + CallRuntime(Runtime::kSetProperty, context, receiver, unique_name, value, + SmiConstant(language_mode)); + Goto(&done); + } + + BIND(&done); +} + } // namespace internal } // namespace v8 diff --git a/deps/v8/src/ic/keyed-store-generic.h b/deps/v8/src/ic/keyed-store-generic.h index 1a0de3b2b4..9cda8ef2e2 100644 --- a/deps/v8/src/ic/keyed-store-generic.h +++ b/deps/v8/src/ic/keyed-store-generic.h @@ -5,18 +5,24 @@ #ifndef V8_IC_KEYED_STORE_GENERIC_H_ #define V8_IC_KEYED_STORE_GENERIC_H_ +#include "src/compiler/code-assembler.h" #include "src/globals.h" namespace v8 { namespace internal { -namespace compiler { -class CodeAssemblerState; -} - class KeyedStoreGenericGenerator { public: + template <class T> + using TNode = compiler::TNode<T>; + static void Generate(compiler::CodeAssemblerState* state); + + // Building block for fast path of Object.assign implementation. + static void SetProperty(compiler::CodeAssemblerState* state, + TNode<Context> context, TNode<JSReceiver> receiver, + TNode<BoolT> is_simple_receiver, TNode<Name> name, + TNode<Object> value, LanguageMode language_mode); }; class StoreICUninitializedGenerator { diff --git a/deps/v8/src/ic/stub-cache.cc b/deps/v8/src/ic/stub-cache.cc index 927c7c6f27..a9cafd6648 100644 --- a/deps/v8/src/ic/stub-cache.cc +++ b/deps/v8/src/ic/stub-cache.cc @@ -65,7 +65,7 @@ bool CommonStubCacheChecks(StubCache* stub_cache, Name* name, Map* map, DCHECK(!name->GetHeap()->InNewSpace(handler)); DCHECK(name->IsUniqueName()); DCHECK(name->HasHashCode()); - if (handler) DCHECK(IC::IsHandler(handler)); + if (handler) DCHECK(IC::IsHandler(MaybeObject::FromObject(handler), true)); return true; } |