summaryrefslogtreecommitdiff
path: root/deps/v8/src/ic/accessor-assembler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/ic/accessor-assembler.cc')
-rw-r--r--deps/v8/src/ic/accessor-assembler.cc410
1 files changed, 299 insertions, 111 deletions
diff --git a/deps/v8/src/ic/accessor-assembler.cc b/deps/v8/src/ic/accessor-assembler.cc
index c631ab400e..2531a3dea8 100644
--- a/deps/v8/src/ic/accessor-assembler.cc
+++ b/deps/v8/src/ic/accessor-assembler.cc
@@ -71,7 +71,7 @@ TNode<MaybeObject> AccessorAssembler::LoadHandlerDataField(
TNode<HeapObjectReference> AccessorAssembler::TryMonomorphicCase(
TNode<TaggedIndex> slot, TNode<FeedbackVector> vector,
- TNode<Map> lookup_start_object_map, Label* if_handler,
+ TNode<HeapObjectReference> weak_lookup_start_object_map, Label* if_handler,
TVariable<MaybeObject>* var_handler, Label* if_miss) {
Comment("TryMonomorphicCase");
DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
@@ -89,7 +89,9 @@ TNode<HeapObjectReference> AccessorAssembler::TryMonomorphicCase(
// Try to quickly handle the monomorphic case without knowing for sure
// if we have a weak reference in feedback.
- GotoIfNot(IsWeakReferenceTo(feedback, lookup_start_object_map), if_miss);
+ CSA_DCHECK(this,
+ IsMap(GetHeapObjectAssumeWeak(weak_lookup_start_object_map)));
+ GotoIfNot(TaggedEqual(feedback, weak_lookup_start_object_map), if_miss);
TNode<MaybeObject> handler = UncheckedCast<MaybeObject>(
Load(MachineType::AnyTagged(), vector,
@@ -101,8 +103,9 @@ TNode<HeapObjectReference> AccessorAssembler::TryMonomorphicCase(
}
void AccessorAssembler::HandlePolymorphicCase(
- TNode<Map> lookup_start_object_map, TNode<WeakFixedArray> feedback,
- Label* if_handler, TVariable<MaybeObject>* var_handler, Label* if_miss) {
+ TNode<HeapObjectReference> weak_lookup_start_object_map,
+ TNode<WeakFixedArray> feedback, Label* if_handler,
+ TVariable<MaybeObject>* var_handler, Label* if_miss) {
Comment("HandlePolymorphicCase");
DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
@@ -123,8 +126,9 @@ void AccessorAssembler::HandlePolymorphicCase(
{
TNode<MaybeObject> maybe_cached_map =
LoadWeakFixedArrayElement(feedback, var_index.value());
- CSA_DCHECK(this, IsWeakOrCleared(maybe_cached_map));
- GotoIfNot(IsWeakReferenceTo(maybe_cached_map, lookup_start_object_map),
+ CSA_DCHECK(this,
+ IsMap(GetHeapObjectAssumeWeak(weak_lookup_start_object_map)));
+ GotoIfNot(TaggedEqual(maybe_cached_map, weak_lookup_start_object_map),
&loop_next);
// Found, now call handler.
@@ -187,7 +191,7 @@ void AccessorAssembler::TryMegaDOMCase(TNode<Object> lookup_start_object,
// we should miss to the runtime.
exit_point->Return(
CallBuiltin(Builtin::kCallFunctionTemplate_CheckCompatibleReceiver,
- context, getter, IntPtrConstant(0), lookup_start_object));
+ context, getter, IntPtrConstant(1), lookup_start_object));
}
void AccessorAssembler::HandleLoadICHandlerCase(
@@ -209,7 +213,7 @@ void AccessorAssembler::HandleLoadICHandlerCase(
BIND(&try_proto_handler);
{
GotoIf(IsWeakOrCleared(handler), &call_getter);
- GotoIf(IsCodeT(CAST(handler)), &call_code_handler);
+ GotoIf(IsCode(CAST(handler)), &call_code_handler);
HandleLoadICProtoHandler(p, CAST(handler), &var_holder, &var_smi_handler,
&if_smi_handler, miss, exit_point, ic_mode,
access_mode);
@@ -237,7 +241,7 @@ void AccessorAssembler::HandleLoadICHandlerCase(
BIND(&call_code_handler);
{
- TNode<CodeT> code_handler = CAST(handler);
+ TNode<Code> code_handler = CAST(handler);
exit_point->ReturnCallStub(LoadWithVectorDescriptor{}, code_handler,
p->context(), p->lookup_start_object(),
p->name(), p->slot(), p->vector());
@@ -291,7 +295,7 @@ void AccessorAssembler::HandleLoadAccessor(
Goto(&load);
BIND(&load);
- TNode<IntPtrT> argc = IntPtrConstant(0);
+ TNode<Int32T> argc = Int32Constant(0);
exit_point->Return(CallApiCallback(context, callback, argc, data,
api_holder.value(), p->receiver()));
}
@@ -1015,7 +1019,7 @@ TNode<Object> AccessorAssembler::HandleProtoHandler(
if (on_code_handler) {
Label if_smi_handler(this);
GotoIf(TaggedIsSmi(smi_or_code_handler), &if_smi_handler);
- TNode<CodeT> code = CAST(smi_or_code_handler);
+ TNode<Code> code = CAST(smi_or_code_handler);
on_code_handler(code);
BIND(&if_smi_handler);
@@ -1304,25 +1308,12 @@ void AccessorAssembler::HandleStoreICHandlerCase(
GotoIf(IsSetWord32(details, kTypeAndReadOnlyMask), miss);
if (V8_DICT_PROPERTY_CONST_TRACKING_BOOL) {
- GotoIf(IsPropertyDetailsConst(details), &if_constant);
+ GotoIf(IsPropertyDetailsConst(details), miss);
}
StoreValueByKeyIndex<PropertyDictionary>(
properties, var_name_index.value(), p->value());
Return(p->value());
-
- if (V8_DICT_PROPERTY_CONST_TRACKING_BOOL) {
- BIND(&if_constant);
- {
- TNode<Object> prev_value =
- LoadValueByKeyIndex(properties, var_name_index.value());
- BranchIfSameValue(prev_value, p->value(), &done, miss,
- SameValueMode::kNumbersOnly);
- }
-
- BIND(&done);
- Return(p->value());
- }
}
}
BIND(&if_fast_smi);
@@ -1351,7 +1342,10 @@ void AccessorAssembler::HandleStoreICHandlerCase(
}
BIND(&if_proxy);
- HandleStoreToProxy(p, CAST(holder), miss, support_elements);
+ {
+ CSA_DCHECK(this, BoolConstant(!p->IsDefineKeyedOwn()));
+ HandleStoreToProxy(p, CAST(holder), miss, support_elements);
+ }
BIND(&if_interceptor);
{
@@ -1389,7 +1383,7 @@ void AccessorAssembler::HandleStoreICHandlerCase(
GotoIf(IsWeakOrCleared(ref_handler), &store_transition_or_global);
TNode<HeapObject> strong_handler = CAST(handler);
TNode<Map> handler_map = LoadMap(strong_handler);
- Branch(IsCodeTMap(handler_map), &call_handler, &if_proto_handler);
+ Branch(IsCodeMap(handler_map), &call_handler, &if_proto_handler);
BIND(&if_proto_handler);
{
@@ -1400,7 +1394,7 @@ void AccessorAssembler::HandleStoreICHandlerCase(
// |handler| is a heap object. Must be code, call it.
BIND(&call_handler);
{
- TNode<CodeT> code_handler = CAST(strong_handler);
+ TNode<Code> code_handler = CAST(strong_handler);
TailCallStub(StoreWithVectorDescriptor{}, code_handler, p->context(),
p->receiver(), p->name(), p->value(), p->slot(),
p->vector());
@@ -1499,6 +1493,29 @@ void AccessorAssembler::HandleStoreICTransitionMapHandlerCase(
p->value(), miss, true);
}
+void AccessorAssembler::UpdateMayHaveInterestingSymbol(
+ TNode<PropertyDictionary> dict, TNode<Name> name) {
+ Comment("UpdateMayHaveInterestingSymbol");
+ Label done(this);
+
+ if constexpr (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
+ // TODO(pthier): Add flags to swiss dictionaries.
+ Goto(&done);
+ } else {
+ GotoIfNot(IsSymbol(name), &done);
+ TNode<Uint32T> symbol_flags =
+ LoadObjectField<Uint32T>(name, Symbol::kFlagsOffset);
+ GotoIfNot(IsSetWord32<Symbol::IsInterestingSymbolBit>(symbol_flags), &done);
+ TNode<Smi> flags = GetNameDictionaryFlags(dict);
+ flags = SmiOr(
+ flags, SmiConstant(
+ NameDictionary::MayHaveInterestingSymbolsBit::encode(true)));
+ SetNameDictionaryFlags(dict, flags);
+ Goto(&done);
+ }
+ BIND(&done);
+}
+
void AccessorAssembler::CheckFieldType(TNode<DescriptorArray> descriptors,
TNode<IntPtrT> name_index,
TNode<Word32T> representation,
@@ -1613,14 +1630,9 @@ void AccessorAssembler::OverwriteExistingFastDataProperty(
StoreMap(object, object_map);
StoreObjectField(object, field_offset, heap_number);
} else {
+ GotoIf(IsPropertyDetailsConst(details), slow);
TNode<HeapNumber> heap_number =
CAST(LoadObjectField(object, field_offset));
- Label store_value(this);
- GotoIfNot(IsPropertyDetailsConst(details), &store_value);
- TNode<Float64T> current_value = LoadHeapNumberValue(heap_number);
- BranchIfSameNumberValue(current_value, double_value, &store_value,
- slow);
- BIND(&store_value);
StoreHeapNumberValue(heap_number, double_value);
}
Goto(&done);
@@ -1631,12 +1643,7 @@ void AccessorAssembler::OverwriteExistingFastDataProperty(
if (do_transitioning_store) {
StoreMap(object, object_map);
} else {
- Label if_mutable(this);
- GotoIfNot(IsPropertyDetailsConst(details), &if_mutable);
- TNode<Object> current_value = LoadObjectField(object, field_offset);
- BranchIfSameValue(current_value, value, &done, slow,
- SameValueMode::kNumbersOnly);
- BIND(&if_mutable);
+ GotoIf(IsPropertyDetailsConst(details), slow);
}
StoreObjectField(object, field_offset, value);
Goto(&done);
@@ -1684,29 +1691,16 @@ void AccessorAssembler::OverwriteExistingFastDataProperty(
&double_rep, &tagged_rep);
BIND(&double_rep);
{
+ GotoIf(IsPropertyDetailsConst(details), slow);
TNode<HeapNumber> heap_number =
CAST(LoadPropertyArrayElement(properties, backing_store_index));
TNode<Float64T> double_value = ChangeNumberToFloat64(CAST(value));
-
- Label if_mutable(this);
- GotoIfNot(IsPropertyDetailsConst(details), &if_mutable);
- TNode<Float64T> current_value = LoadHeapNumberValue(heap_number);
- BranchIfSameNumberValue(current_value, double_value, &done, slow);
-
- BIND(&if_mutable);
StoreHeapNumberValue(heap_number, double_value);
Goto(&done);
}
BIND(&tagged_rep);
{
- Label if_mutable(this);
- GotoIfNot(IsPropertyDetailsConst(details), &if_mutable);
- TNode<Object> current_value =
- LoadPropertyArrayElement(properties, backing_store_index);
- BranchIfSameValue(current_value, value, &done, slow,
- SameValueMode::kNumbersOnly);
-
- BIND(&if_mutable);
+ GotoIf(IsPropertyDetailsConst(details), slow);
StorePropertyArrayElement(properties, backing_store_index, value);
Goto(&done);
}
@@ -1820,7 +1814,7 @@ void AccessorAssembler::HandleStoreICProtoHandler(
OnCodeHandler on_code_handler;
if (support_elements == kSupportElements) {
// Code sub-handlers are expected only in KeyedStoreICs.
- on_code_handler = [=](TNode<CodeT> code_handler) {
+ on_code_handler = [=](TNode<Code> code_handler) {
// This is either element store or transitioning element store.
Label if_element_store(this), if_transitioning_element_store(this);
Branch(IsStoreHandler0Map(LoadMap(handler)), &if_element_store,
@@ -1931,7 +1925,9 @@ void AccessorAssembler::HandleStoreICProtoHandler(
TNode<PropertyDictionary> properties =
CAST(LoadSlowProperties(CAST(p->receiver())));
- Add<PropertyDictionary>(properties, CAST(p->name()), p->value(), &slow);
+ TNode<Name> name = CAST(p->name());
+ Add<PropertyDictionary>(properties, name, p->value(), &slow);
+ UpdateMayHaveInterestingSymbol(properties, name);
Return(p->value());
BIND(&slow);
@@ -1982,7 +1978,7 @@ void AccessorAssembler::HandleStoreICProtoHandler(
BIND(&store);
{
GotoIf(IsSideEffectFreeDebuggingActive(), &if_slow);
- TNode<IntPtrT> argc = IntPtrConstant(1);
+ TNode<Int32T> argc = Int32Constant(1);
Return(CallApiCallback(context, callback, argc, data,
api_holder.value(), p->receiver(), p->value()));
}
@@ -2149,6 +2145,18 @@ void AccessorAssembler::CheckDescriptorConsidersNumbersMutable(
bailout);
}
+void AccessorAssembler::GotoIfNotSameNumberBitPattern(TNode<Float64T> left,
+ TNode<Float64T> right,
+ Label* miss) {
+ // TODO(verwaest): Use a single compare on 64bit archs.
+ const TNode<Uint32T> lhs_hi = Float64ExtractHighWord32(left);
+ const TNode<Uint32T> rhs_hi = Float64ExtractHighWord32(right);
+ GotoIfNot(Word32Equal(lhs_hi, rhs_hi), miss);
+ const TNode<Uint32T> lhs_lo = Float64ExtractLowWord32(left);
+ const TNode<Uint32T> rhs_lo = Float64ExtractLowWord32(right);
+ GotoIfNot(Word32Equal(lhs_lo, rhs_lo), miss);
+}
+
void AccessorAssembler::HandleStoreFieldAndReturn(
TNode<Word32T> handler_word, TNode<JSObject> holder, TNode<Object> value,
base::Optional<TNode<Float64T>> double_value, Representation representation,
@@ -2192,11 +2200,9 @@ void AccessorAssembler::HandleStoreFieldAndReturn(
&do_store);
{
if (store_value_as_double) {
- Label done(this);
TNode<Float64T> current_value =
LoadObjectField<Float64T>(property_storage, offset);
- BranchIfSameNumberValue(current_value, *double_value, &done, miss);
- BIND(&done);
+ GotoIfNotSameNumberBitPattern(current_value, *double_value, miss);
Return(value);
} else {
TNode<Object> current_value = LoadObjectField(property_storage, offset);
@@ -2904,7 +2910,7 @@ TNode<IntPtrT> AccessorAssembler::StubCachePrimaryOffset(TNode<Name> name,
TNode<IntPtrT> map_word = BitcastTaggedToWord(map);
TNode<Int32T> map32 = TruncateIntPtrToInt32(UncheckedCast<IntPtrT>(
- WordXor(map_word, WordShr(map_word, StubCache::kMapKeyShift))));
+ WordXor(map_word, WordShr(map_word, StubCache::kPrimaryTableBits))));
// Base the offset on a simple combination of name and map.
TNode<Word32T> hash = Int32Add(raw_hash_field, map32);
uint32_t mask = (StubCache::kPrimaryTableSize - 1)
@@ -2923,7 +2929,7 @@ TNode<IntPtrT> AccessorAssembler::StubCacheSecondaryOffset(TNode<Name> name,
TNode<Int32T> map32 = TruncateIntPtrToInt32(BitcastTaggedToWord(map));
// Base the offset on a simple combination of name and map.
TNode<Word32T> hash_a = Int32Add(map32, name32);
- TNode<Word32T> hash_b = Word32Shr(hash_a, StubCache::kSecondaryKeyShift);
+ TNode<Word32T> hash_b = Word32Shr(hash_a, StubCache::kSecondaryTableBits);
TNode<Word32T> hash = Int32Add(hash_a, hash_b);
int32_t mask = (StubCache::kSecondaryTableSize - 1)
<< StubCache::kCacheIndexShift;
@@ -3052,8 +3058,10 @@ void AccessorAssembler::LoadIC_BytecodeHandler(const LazyLoadICParameters* p,
TVARIABLE(MaybeObject, var_handler);
Label try_polymorphic(this), if_handler(this, &var_handler);
+ TNode<HeapObjectReference> weak_lookup_start_object_map =
+ MakeWeak(lookup_start_object_map);
TNode<HeapObjectReference> feedback = TryMonomorphicCase(
- p->slot(), CAST(p->vector()), lookup_start_object_map, &if_handler,
+ p->slot(), CAST(p->vector()), weak_lookup_start_object_map, &if_handler,
&var_handler, &try_polymorphic);
BIND(&if_handler);
@@ -3064,7 +3072,7 @@ void AccessorAssembler::LoadIC_BytecodeHandler(const LazyLoadICParameters* p,
TNode<HeapObject> strong_feedback =
GetHeapObjectIfStrong(feedback, &miss);
GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &stub_call);
- HandlePolymorphicCase(lookup_start_object_map, CAST(strong_feedback),
+ HandlePolymorphicCase(weak_lookup_start_object_map, CAST(strong_feedback),
&if_handler, &var_handler, &miss);
}
}
@@ -3075,7 +3083,7 @@ void AccessorAssembler::LoadIC_BytecodeHandler(const LazyLoadICParameters* p,
// Call into the stub that implements the non-inlined parts of LoadIC.
Callable ic = Builtins::CallableFor(isolate(), Builtin::kLoadIC_Noninlined);
- TNode<CodeT> code_target = HeapConstant(ic.code());
+ TNode<Code> code_target = HeapConstant(ic.code());
exit_point->ReturnCallStub(ic.descriptor(), code_target, p->context(),
p->receiver_and_lookup_start_object(), p->name(),
p->slot(), p->vector());
@@ -3118,9 +3126,11 @@ void AccessorAssembler::LoadIC(const LoadICParameters* p) {
GotoIf(IsUndefined(p->vector()), &no_feedback);
// Check monomorphic case.
- TNode<HeapObjectReference> feedback =
- TryMonomorphicCase(p->slot(), CAST(p->vector()), lookup_start_object_map,
- &if_handler, &var_handler, &try_polymorphic);
+ TNode<HeapObjectReference> weak_lookup_start_object_map =
+ MakeWeak(lookup_start_object_map);
+ TNode<HeapObjectReference> feedback = TryMonomorphicCase(
+ p->slot(), CAST(p->vector()), weak_lookup_start_object_map, &if_handler,
+ &var_handler, &try_polymorphic);
BIND(&if_handler);
{
LazyLoadICParameters lazy_p(p);
@@ -3133,7 +3143,7 @@ void AccessorAssembler::LoadIC(const LoadICParameters* p) {
// Check polymorphic case.
Comment("LoadIC_try_polymorphic");
GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &non_inlined);
- HandlePolymorphicCase(lookup_start_object_map, CAST(strong_feedback),
+ HandlePolymorphicCase(weak_lookup_start_object_map, CAST(strong_feedback),
&if_handler, &var_handler, &miss);
}
@@ -3174,9 +3184,11 @@ void AccessorAssembler::LoadSuperIC(const LoadICParameters* p) {
TNode<Map> lookup_start_object_map = LoadMap(CAST(p->lookup_start_object()));
GotoIf(IsDeprecatedMap(lookup_start_object_map), &miss);
- TNode<HeapObjectReference> feedback =
- TryMonomorphicCase(p->slot(), CAST(p->vector()), lookup_start_object_map,
- &if_handler, &var_handler, &try_polymorphic);
+ TNode<HeapObjectReference> weak_lookup_start_object_map =
+ MakeWeak(lookup_start_object_map);
+ TNode<HeapObjectReference> feedback = TryMonomorphicCase(
+ p->slot(), CAST(p->vector()), weak_lookup_start_object_map, &if_handler,
+ &var_handler, &try_polymorphic);
BIND(&if_handler);
{
@@ -3192,7 +3204,7 @@ void AccessorAssembler::LoadSuperIC(const LoadICParameters* p) {
{
Comment("LoadSuperIC_try_polymorphic");
GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &non_inlined);
- HandlePolymorphicCase(lookup_start_object_map, CAST(strong_feedback),
+ HandlePolymorphicCase(weak_lookup_start_object_map, CAST(strong_feedback),
&if_handler, &var_handler, &miss);
}
@@ -3357,7 +3369,9 @@ void AccessorAssembler::LoadGlobalIC_TryPropertyCellCase(
BIND(&if_property_cell);
{
- // Load value or try handler case if the weak reference is cleared.
+ // This branch also handles the "handler mode": the weak reference is
+ // cleared, the feedback extra is the handler. In that case we jump to
+ // try_handler. (See FeedbackNexus::ConfigureHandlerMode.)
CSA_DCHECK(this, IsWeakOrCleared(maybe_weak_ref));
TNode<PropertyCell> property_cell =
CAST(GetHeapObjectAssumeWeak(maybe_weak_ref, try_handler));
@@ -3369,6 +3383,9 @@ void AccessorAssembler::LoadGlobalIC_TryPropertyCellCase(
BIND(&if_lexical_var);
{
+ // This branch handles the "lexical variable mode": the feedback is a SMI
+ // encoding the variable location. (See
+ // FeedbackNexus::ConfigureLexicalVarMode.)
Comment("Load lexical variable");
TNode<IntPtrT> lexical_handler = SmiUntag(CAST(maybe_weak_ref));
TNode<IntPtrT> context_index =
@@ -3485,9 +3502,11 @@ void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p,
GotoIf(IsUndefined(p->vector()), &generic);
// Check monomorphic case.
- TNode<HeapObjectReference> feedback =
- TryMonomorphicCase(p->slot(), CAST(p->vector()), lookup_start_object_map,
- &if_handler, &var_handler, &try_polymorphic);
+ TNode<HeapObjectReference> weak_lookup_start_object_map =
+ MakeWeak(lookup_start_object_map);
+ TNode<HeapObjectReference> feedback = TryMonomorphicCase(
+ p->slot(), CAST(p->vector()), weak_lookup_start_object_map, &if_handler,
+ &var_handler, &try_polymorphic);
BIND(&if_handler);
{
LazyLoadICParameters lazy_p(p);
@@ -3502,7 +3521,7 @@ void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p,
// Check polymorphic case.
Comment("KeyedLoadIC_try_polymorphic");
GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &try_megamorphic);
- HandlePolymorphicCase(lookup_start_object_map, CAST(strong_feedback),
+ HandlePolymorphicCase(weak_lookup_start_object_map, CAST(strong_feedback),
&if_handler, &var_handler, &miss);
}
@@ -3675,6 +3694,100 @@ void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) {
}
}
+void AccessorAssembler::KeyedLoadICGeneric_StringKey(
+ const LoadICParameters* p) {
+ TNode<String> key = CAST(p->name());
+
+ Label if_runtime(this, Label::kDeferred);
+ TNode<Object> lookup_start_object = p->lookup_start_object();
+ GotoIf(TaggedIsSmi(lookup_start_object), &if_runtime);
+ GotoIf(IsNullOrUndefined(lookup_start_object), &if_runtime);
+
+ {
+ TNode<Int32T> instance_type = LoadInstanceType(key);
+ CSA_DCHECK(this, IsStringInstanceType(instance_type));
+
+ // Check |key| is not an index string.
+ CSA_DCHECK(this, IsSetWord32(LoadNameRawHashField(key),
+ Name::kDoesNotContainCachedArrayIndexMask));
+ CSA_DCHECK(this, IsNotEqualInWord32<Name::HashFieldTypeBits>(
+ LoadNameRawHashField(key),
+ Name::HashFieldType::kIntegerIndex));
+
+ TVARIABLE(Name, var_unique);
+ Label if_thinstring(this), if_unique_name(this), if_notunique(this);
+ GotoIf(InstanceTypeEqual(instance_type, THIN_STRING_TYPE), &if_thinstring);
+
+ // Check |key| does not contain forwarding index.
+ CSA_DCHECK(this,
+ Word32BinaryNot(
+ IsBothEqualInWord32<Name::HashFieldTypeBits,
+ Name::IsInternalizedForwardingIndexBit>(
+ LoadNameRawHashField(key),
+ Name::HashFieldType::kForwardingIndex, true)));
+
+ // Check if |key| is internalized.
+ static_assert(kNotInternalizedTag != 0);
+ GotoIf(IsSetWord32(instance_type, kIsNotInternalizedMask), &if_notunique);
+
+ var_unique = key;
+ Goto(&if_unique_name);
+
+ BIND(&if_thinstring);
+ {
+ var_unique = LoadObjectField<String>(key, ThinString::kActualOffset);
+ Goto(&if_unique_name);
+ }
+
+ BIND(&if_unique_name);
+ {
+ LoadICParameters pp(p, var_unique.value());
+ TNode<Map> lookup_start_object_map = LoadMap(CAST(lookup_start_object));
+ GenericPropertyLoad(CAST(lookup_start_object), lookup_start_object_map,
+ LoadMapInstanceType(lookup_start_object_map), &pp,
+ &if_runtime);
+ }
+
+ BIND(&if_notunique);
+ {
+ if (v8_flags.internalize_on_the_fly) {
+ // We expect only string type keys can be used here, so we take all
+ // otherwise to the {if_runtime} path.
+ Label if_in_string_table(this);
+ TVARIABLE(IntPtrT, var_index);
+ TryInternalizeString(key, &if_runtime, &var_index, &if_in_string_table,
+ &var_unique, &if_runtime, &if_runtime);
+
+ BIND(&if_in_string_table);
+ {
+ // TODO(bmeurer): We currently use a version of GenericPropertyLoad
+ // here, where we don't try to probe the megamorphic stub cache
+ // after successfully internalizing the incoming string. Past
+ // experiments with this have shown that it causes too much traffic
+ // on the stub cache. We may want to re-evaluate that in the future.
+ LoadICParameters pp(p, var_unique.value());
+ TNode<Map> lookup_start_object_map =
+ LoadMap(CAST(lookup_start_object));
+ GenericPropertyLoad(CAST(lookup_start_object),
+ lookup_start_object_map,
+ LoadMapInstanceType(lookup_start_object_map), &pp,
+ &if_runtime, kDontUseStubCache);
+ }
+ } else {
+ Goto(&if_runtime);
+ }
+ }
+ }
+
+ BIND(&if_runtime);
+ {
+ Comment("KeyedLoadGeneric_slow");
+ // TODO(jkummerow): Should we use the GetProperty TF stub instead?
+ TailCallRuntime(Runtime::kGetProperty, p->context(),
+ p->receiver_and_lookup_start_object(), key);
+ }
+}
+
void AccessorAssembler::KeyedLoadICPolymorphicName(const LoadICParameters* p,
LoadAccessMode access_mode) {
TVARIABLE(MaybeObject, var_handler);
@@ -3698,7 +3811,7 @@ void AccessorAssembler::KeyedLoadICPolymorphicName(const LoadICParameters* p,
TNode<MaybeObject> feedback_element =
LoadFeedbackVectorSlot(vector, slot, kTaggedSize);
TNode<WeakFixedArray> array = CAST(feedback_element);
- HandlePolymorphicCase(lookup_start_object_map, array, &if_handler,
+ HandlePolymorphicCase(MakeWeak(lookup_start_object_map), array, &if_handler,
&var_handler, &miss);
BIND(&if_handler);
@@ -3736,8 +3849,9 @@ void AccessorAssembler::StoreIC(const StoreICParameters* p) {
GotoIf(IsUndefined(p->vector()), &no_feedback);
// Check monomorphic case.
+ TNode<HeapObjectReference> weak_receiver_map = MakeWeak(receiver_map);
TNode<HeapObjectReference> feedback =
- TryMonomorphicCase(p->slot(), CAST(p->vector()), receiver_map,
+ TryMonomorphicCase(p->slot(), CAST(p->vector()), weak_receiver_map,
&if_handler, &var_handler, &try_polymorphic);
BIND(&if_handler);
{
@@ -3752,7 +3866,7 @@ void AccessorAssembler::StoreIC(const StoreICParameters* p) {
// Check polymorphic case.
Comment("StoreIC_try_polymorphic");
GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &try_megamorphic);
- HandlePolymorphicCase(receiver_map, CAST(strong_feedback), &if_handler,
+ HandlePolymorphicCase(weak_receiver_map, CAST(strong_feedback), &if_handler,
&var_handler, &miss);
}
@@ -3797,6 +3911,9 @@ void AccessorAssembler::StoreGlobalIC(const StoreICParameters* pp) {
{
Label try_handler(this), miss(this, Label::kDeferred);
+ // This branch also handles the "handler mode": the weak reference is
+ // cleared, the feedback extra is the handler. In that case we jump to
+ // try_handler. (See FeedbackNexus::ConfigureHandlerMode.)
CSA_DCHECK(this, IsWeakOrCleared(maybe_weak_ref));
TNode<PropertyCell> property_cell =
CAST(GetHeapObjectAssumeWeak(maybe_weak_ref, &try_handler));
@@ -3814,11 +3931,12 @@ void AccessorAssembler::StoreGlobalIC(const StoreICParameters* pp) {
GotoIf(TaggedEqual(handler, UninitializedSymbolConstant()), &miss);
DCHECK(pp->receiver_is_null());
+ DCHECK(pp->flags_is_null());
TNode<NativeContext> native_context = LoadNativeContext(pp->context());
StoreICParameters p(
pp->context(),
LoadContextElement(native_context, Context::GLOBAL_PROXY_INDEX),
- pp->name(), pp->value(), pp->slot(), pp->vector(),
+ pp->name(), pp->value(), base::nullopt, pp->slot(), pp->vector(),
StoreICMode::kDefault);
HandleStoreICHandlerCase(&p, handler, &miss, ICMode::kGlobalIC);
@@ -3833,6 +3951,9 @@ void AccessorAssembler::StoreGlobalIC(const StoreICParameters* pp) {
BIND(&if_lexical_var);
{
+ // This branch handles the "lexical variable mode": the feedback is a SMI
+ // encoding the variable location. (See
+ // FeedbackNexus::ConfigureLexicalVarMode.)
Comment("Store lexical variable");
TNode<IntPtrT> lexical_handler = SmiUntag(CAST(maybe_weak_ref));
TNode<IntPtrT> context_index =
@@ -3934,8 +4055,9 @@ void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p) {
GotoIf(IsUndefined(p->vector()), &no_feedback);
// Check monomorphic case.
+ TNode<HeapObjectReference> weak_receiver_map = MakeWeak(receiver_map);
TNode<HeapObjectReference> feedback =
- TryMonomorphicCase(p->slot(), CAST(p->vector()), receiver_map,
+ TryMonomorphicCase(p->slot(), CAST(p->vector()), weak_receiver_map,
&if_handler, &var_handler, &try_polymorphic);
BIND(&if_handler);
{
@@ -3951,8 +4073,8 @@ void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p) {
Comment("KeyedStoreIC_try_polymorphic");
GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)),
&try_megamorphic);
- HandlePolymorphicCase(receiver_map, CAST(strong_feedback), &if_handler,
- &var_handler, &miss);
+ HandlePolymorphicCase(weak_receiver_map, CAST(strong_feedback),
+ &if_handler, &var_handler, &miss);
}
BIND(&try_megamorphic);
@@ -3979,7 +4101,7 @@ void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p) {
TNode<MaybeObject> feedback_element =
LoadFeedbackVectorSlot(CAST(p->vector()), p->slot(), kTaggedSize);
TNode<WeakFixedArray> array = CAST(feedback_element);
- HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler,
+ HandlePolymorphicCase(weak_receiver_map, array, &if_handler, &var_handler,
&miss);
}
}
@@ -3994,6 +4116,25 @@ void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p) {
void AccessorAssembler::DefineKeyedOwnIC(const StoreICParameters* p) {
Label miss(this, Label::kDeferred);
{
+ {
+ // TODO(v8:13451): Port SetFunctionName to an ic so that we can remove
+ // the runtime call here. Potentially we may also remove the
+ // StoreICParameters flags and have builtins:kDefineKeyedOwnIC reusing
+ // StoreWithVectorDescriptor again.
+ Label did_set_function_name_if_needed(this);
+ TNode<Int32T> needs_set_function_name = Word32And(
+ SmiToInt32(p->flags()),
+ Int32Constant(
+ static_cast<int>(DefineKeyedOwnPropertyFlag::kSetFunctionName)));
+ GotoIfNot(needs_set_function_name, &did_set_function_name_if_needed);
+
+ Comment("DefineKeyedOwnIC_set_function_name");
+ CallRuntime(Runtime::kSetFunctionName, p->context(), p->value(),
+ p->name());
+
+ Goto(&did_set_function_name_if_needed);
+ BIND(&did_set_function_name_if_needed);
+ }
TVARIABLE(MaybeObject, var_handler);
Label if_handler(this, &var_handler),
@@ -4008,8 +4149,9 @@ void AccessorAssembler::DefineKeyedOwnIC(const StoreICParameters* p) {
GotoIf(IsUndefined(p->vector()), &no_feedback);
// Check monomorphic case.
+ TNode<HeapObjectReference> weak_receiver_map = MakeWeak(receiver_map);
TNode<HeapObjectReference> feedback =
- TryMonomorphicCase(p->slot(), CAST(p->vector()), receiver_map,
+ TryMonomorphicCase(p->slot(), CAST(p->vector()), weak_receiver_map,
&if_handler, &var_handler, &try_polymorphic);
BIND(&if_handler);
{
@@ -4025,8 +4167,8 @@ void AccessorAssembler::DefineKeyedOwnIC(const StoreICParameters* p) {
Comment("DefineKeyedOwnIC_try_polymorphic");
GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)),
&try_megamorphic);
- HandlePolymorphicCase(receiver_map, CAST(strong_feedback), &if_handler,
- &var_handler, &miss);
+ HandlePolymorphicCase(weak_receiver_map, CAST(strong_feedback),
+ &if_handler, &var_handler, &miss);
}
BIND(&try_megamorphic);
@@ -4053,7 +4195,7 @@ void AccessorAssembler::DefineKeyedOwnIC(const StoreICParameters* p) {
TNode<MaybeObject> feedback_element =
LoadFeedbackVectorSlot(CAST(p->vector()), p->slot(), kTaggedSize);
TNode<WeakFixedArray> array = CAST(feedback_element);
- HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler,
+ HandlePolymorphicCase(weak_receiver_map, array, &if_handler, &var_handler,
&miss);
}
}
@@ -4079,9 +4221,10 @@ void AccessorAssembler::StoreInArrayLiteralIC(const StoreICParameters* p) {
GotoIf(IsUndefined(p->vector()), &no_feedback);
+ TNode<HeapObjectReference> weak_array_map = MakeWeak(array_map);
TNode<HeapObjectReference> feedback =
- TryMonomorphicCase(p->slot(), CAST(p->vector()), array_map, &if_handler,
- &var_handler, &try_polymorphic);
+ TryMonomorphicCase(p->slot(), CAST(p->vector()), weak_array_map,
+ &if_handler, &var_handler, &try_polymorphic);
BIND(&if_handler);
{
@@ -4094,11 +4237,11 @@ void AccessorAssembler::StoreInArrayLiteralIC(const StoreICParameters* p) {
GotoIf(TaggedIsSmi(var_handler.value()), &if_smi_handler);
TNode<HeapObject> handler = CAST(var_handler.value());
- GotoIfNot(IsCodeT(handler), &if_transitioning_element_store);
+ GotoIfNot(IsCode(handler), &if_transitioning_element_store);
{
// Call the handler.
- TNode<CodeT> code_handler = CAST(handler);
+ TNode<Code> code_handler = CAST(handler);
TailCallStub(StoreWithVectorDescriptor{}, code_handler, p->context(),
p->receiver(), p->name(), p->value(), p->slot(),
p->vector());
@@ -4111,7 +4254,7 @@ void AccessorAssembler::StoreInArrayLiteralIC(const StoreICParameters* p) {
TNode<Map> transition_map =
CAST(GetHeapObjectAssumeWeak(maybe_transition_map, &miss));
GotoIf(IsDeprecatedMap(transition_map), &miss);
- TNode<CodeT> code =
+ TNode<Code> code =
CAST(LoadObjectField(handler, StoreHandler::kSmiHandlerOffset));
TailCallStub(StoreTransitionDescriptor{}, code, p->context(),
p->receiver(), p->name(), transition_map, p->value(),
@@ -4140,7 +4283,7 @@ void AccessorAssembler::StoreInArrayLiteralIC(const StoreICParameters* p) {
Comment("StoreInArrayLiteralIC_try_polymorphic");
GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)),
&try_megamorphic);
- HandlePolymorphicCase(array_map, CAST(strong_feedback), &if_handler,
+ HandlePolymorphicCase(weak_array_map, CAST(strong_feedback), &if_handler,
&var_handler, &miss);
}
@@ -4463,6 +4606,16 @@ void AccessorAssembler::LookupGlobalIC(
TailCallRuntime(function_id, context, lazy_name());
}
+void AccessorAssembler::GenerateLookupGlobalIC(TypeofMode typeof_mode) {
+ using Descriptor = LookupWithVectorDescriptor;
+ LookupGlobalIC([&] { return Parameter<Object>(Descriptor::kName); },
+ Parameter<TaggedIndex>(Descriptor::kDepth),
+ [&] { return Parameter<TaggedIndex>(Descriptor::kSlot); },
+ Parameter<Context>(Descriptor::kContext),
+ [&] { return Parameter<FeedbackVector>(Descriptor::kVector); },
+ typeof_mode);
+}
+
void AccessorAssembler::GenerateLookupGlobalICTrampoline(
TypeofMode typeof_mode) {
using Descriptor = LookupTrampolineDescriptor;
@@ -4508,6 +4661,19 @@ void AccessorAssembler::GenerateKeyedLoadIC_Megamorphic() {
KeyedLoadICGeneric(&p);
}
+void AccessorAssembler::GenerateKeyedLoadIC_MegamorphicStringKey() {
+ using Descriptor = LoadWithVectorDescriptor;
+
+ auto receiver = Parameter<Object>(Descriptor::kReceiver);
+ auto name = Parameter<Object>(Descriptor::kName);
+ auto slot = Parameter<TaggedIndex>(Descriptor::kSlot);
+ auto vector = Parameter<HeapObject>(Descriptor::kVector);
+ auto context = Parameter<Context>(Descriptor::kContext);
+
+ LoadICParameters p(context, receiver, name, slot, vector);
+ KeyedLoadICGeneric_StringKey(&p);
+}
+
void AccessorAssembler::GenerateKeyedLoadICTrampoline() {
using Descriptor = LoadDescriptor;
@@ -4545,6 +4711,19 @@ void AccessorAssembler::GenerateKeyedLoadICTrampoline_Megamorphic() {
slot, vector);
}
+void AccessorAssembler::GenerateKeyedLoadICTrampoline_MegamorphicStringKey() {
+ using Descriptor = LoadDescriptor;
+
+ auto receiver = Parameter<Object>(Descriptor::kReceiver);
+ auto name = Parameter<Object>(Descriptor::kName);
+ auto slot = Parameter<TaggedIndex>(Descriptor::kSlot);
+ auto context = Parameter<Context>(Descriptor::kContext);
+ TNode<FeedbackVector> vector = LoadFeedbackVectorForStub();
+
+ TailCallBuiltin(Builtin::kKeyedLoadIC_MegamorphicStringKey, context, receiver,
+ name, slot, vector);
+}
+
void AccessorAssembler::GenerateKeyedLoadIC_PolymorphicName() {
using Descriptor = LoadWithVectorDescriptor;
@@ -4564,10 +4743,11 @@ void AccessorAssembler::GenerateStoreGlobalIC() {
auto name = Parameter<Object>(Descriptor::kName);
auto value = Parameter<Object>(Descriptor::kValue);
auto slot = Parameter<TaggedIndex>(Descriptor::kSlot);
+ auto flags = base::nullopt;
auto vector = Parameter<HeapObject>(Descriptor::kVector);
auto context = Parameter<Context>(Descriptor::kContext);
- StoreICParameters p(context, base::nullopt, name, value, slot, vector,
+ StoreICParameters p(context, base::nullopt, name, value, flags, slot, vector,
StoreICMode::kDefault);
StoreGlobalIC(&p);
}
@@ -4602,11 +4782,12 @@ void AccessorAssembler::GenerateStoreIC() {
auto receiver = Parameter<Object>(Descriptor::kReceiver);
auto name = Parameter<Object>(Descriptor::kName);
auto value = Parameter<Object>(Descriptor::kValue);
+ auto flags = base::nullopt;
auto slot = Parameter<TaggedIndex>(Descriptor::kSlot);
auto vector = Parameter<HeapObject>(Descriptor::kVector);
auto context = Parameter<Context>(Descriptor::kContext);
- StoreICParameters p(context, receiver, name, value, slot, vector,
+ StoreICParameters p(context, receiver, name, value, flags, slot, vector,
StoreICMode::kDefault);
StoreIC(&p);
}
@@ -4645,11 +4826,12 @@ void AccessorAssembler::GenerateDefineNamedOwnIC() {
auto receiver = Parameter<Object>(Descriptor::kReceiver);
auto name = Parameter<Object>(Descriptor::kName);
auto value = Parameter<Object>(Descriptor::kValue);
+ auto flags = base::nullopt;
auto slot = Parameter<TaggedIndex>(Descriptor::kSlot);
auto vector = Parameter<HeapObject>(Descriptor::kVector);
auto context = Parameter<Context>(Descriptor::kContext);
- StoreICParameters p(context, receiver, name, value, slot, vector,
+ StoreICParameters p(context, receiver, name, value, flags, slot, vector,
StoreICMode::kDefineNamedOwn);
// StoreIC is a generic helper than handle both set and define own
// named stores.
@@ -4690,11 +4872,12 @@ void AccessorAssembler::GenerateKeyedStoreIC() {
auto receiver = Parameter<Object>(Descriptor::kReceiver);
auto name = Parameter<Object>(Descriptor::kName);
auto value = Parameter<Object>(Descriptor::kValue);
+ auto flags = base::nullopt;
auto slot = Parameter<TaggedIndex>(Descriptor::kSlot);
auto vector = Parameter<HeapObject>(Descriptor::kVector);
auto context = Parameter<Context>(Descriptor::kContext);
- StoreICParameters p(context, receiver, name, value, slot, vector,
+ StoreICParameters p(context, receiver, name, value, flags, slot, vector,
StoreICMode::kDefault);
KeyedStoreIC(&p);
}
@@ -4728,46 +4911,49 @@ void AccessorAssembler::GenerateKeyedStoreICBaseline() {
}
void AccessorAssembler::GenerateDefineKeyedOwnIC() {
- using Descriptor = StoreWithVectorDescriptor;
+ using Descriptor = DefineKeyedOwnWithVectorDescriptor;
auto receiver = Parameter<Object>(Descriptor::kReceiver);
auto name = Parameter<Object>(Descriptor::kName);
auto value = Parameter<Object>(Descriptor::kValue);
+ auto flags = Parameter<Smi>(Descriptor::kFlags);
auto slot = Parameter<TaggedIndex>(Descriptor::kSlot);
auto vector = Parameter<HeapObject>(Descriptor::kVector);
auto context = Parameter<Context>(Descriptor::kContext);
- StoreICParameters p(context, receiver, name, value, slot, vector,
+ StoreICParameters p(context, receiver, name, value, flags, slot, vector,
StoreICMode::kDefineKeyedOwn);
DefineKeyedOwnIC(&p);
}
void AccessorAssembler::GenerateDefineKeyedOwnICTrampoline() {
- using Descriptor = StoreDescriptor;
+ using Descriptor = DefineKeyedOwnDescriptor;
auto receiver = Parameter<Object>(Descriptor::kReceiver);
auto name = Parameter<Object>(Descriptor::kName);
auto value = Parameter<Object>(Descriptor::kValue);
+ auto flags = Parameter<Smi>(Descriptor::kFlags);
auto slot = Parameter<TaggedIndex>(Descriptor::kSlot);
auto context = Parameter<Context>(Descriptor::kContext);
TNode<FeedbackVector> vector = LoadFeedbackVectorForStub();
TailCallBuiltin(Builtin::kDefineKeyedOwnIC, context, receiver, name, value,
- slot, vector);
+ flags, slot, vector);
}
void AccessorAssembler::GenerateDefineKeyedOwnICBaseline() {
- using Descriptor = StoreBaselineDescriptor;
+ using Descriptor = DefineKeyedOwnBaselineDescriptor;
auto receiver = Parameter<Object>(Descriptor::kReceiver);
auto name = Parameter<Object>(Descriptor::kName);
auto value = Parameter<Object>(Descriptor::kValue);
+ auto flags = Parameter<Smi>(Descriptor::kFlags);
auto slot = Parameter<TaggedIndex>(Descriptor::kSlot);
TNode<FeedbackVector> vector = LoadFeedbackVectorFromBaseline();
TNode<Context> context = LoadContextFromBaseline();
TailCallBuiltin(Builtin::kDefineKeyedOwnIC, context, receiver, name, value,
- slot, vector);
+ flags, slot, vector);
}
void AccessorAssembler::GenerateStoreInArrayLiteralIC() {
@@ -4776,11 +4962,12 @@ void AccessorAssembler::GenerateStoreInArrayLiteralIC() {
auto array = Parameter<Object>(Descriptor::kReceiver);
auto index = Parameter<Object>(Descriptor::kName);
auto value = Parameter<Object>(Descriptor::kValue);
+ auto flags = base::nullopt;
auto slot = Parameter<TaggedIndex>(Descriptor::kSlot);
auto vector = Parameter<HeapObject>(Descriptor::kVector);
auto context = Parameter<Context>(Descriptor::kContext);
- StoreICParameters p(context, array, index, value, slot, vector,
+ StoreICParameters p(context, array, index, value, flags, slot, vector,
StoreICMode::kDefault);
StoreInArrayLiteralIC(&p);
}
@@ -4884,8 +5071,9 @@ void AccessorAssembler::GenerateCloneObjectIC() {
GotoIf(IsUndefined(maybe_vector), &slow);
+ TNode<HeapObjectReference> weak_source_map = MakeWeak(source_map);
TNode<HeapObjectReference> feedback =
- TryMonomorphicCase(slot, CAST(maybe_vector), source_map, &if_handler,
+ TryMonomorphicCase(slot, CAST(maybe_vector), weak_source_map, &if_handler,
&var_handler, &try_polymorphic);
BIND(&if_handler);
@@ -4959,7 +5147,7 @@ void AccessorAssembler::GenerateCloneObjectIC() {
IntPtrAdd(field_offset, field_offset_difference);
StoreObjectFieldNoWriteBarrier(object, result_offset, field);
},
- 1, IndexAdvanceMode::kPost);
+ 1, LoopUnrollingMode::kYes, IndexAdvanceMode::kPost);
// We need to go through the {object} again here and properly clone them. We
// use a second loop here to ensure that the GC (and heap verifier) always
@@ -4979,7 +5167,7 @@ void AccessorAssembler::GenerateCloneObjectIC() {
{
Comment("CloneObjectIC_try_polymorphic");
GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &try_megamorphic);
- HandlePolymorphicCase(source_map, CAST(strong_feedback), &if_handler,
+ HandlePolymorphicCase(weak_source_map, CAST(strong_feedback), &if_handler,
&var_handler, &miss);
}