summaryrefslogtreecommitdiff
path: root/deps/v8/src/ic
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2018-07-25 19:30:07 +0200
committerMichaël Zasso <targos@protonmail.com>2018-07-26 08:31:50 +0200
commit6a31d05340b22fc413ee83eaacd0a5565bbbe799 (patch)
tree78f9e1c2f417244842f6422f17e1816e70317100 /deps/v8/src/ic
parent4d94bb2b1f72b6b612983a517a39c5545724a3ad (diff)
downloadandroid-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.cc383
-rw-r--r--deps/v8/src/ic/accessor-assembler.h45
-rw-r--r--deps/v8/src/ic/binary-op-assembler.cc56
-rw-r--r--deps/v8/src/ic/handler-configuration-inl.h8
-rw-r--r--deps/v8/src/ic/handler-configuration.cc49
-rw-r--r--deps/v8/src/ic/handler-configuration.h14
-rw-r--r--deps/v8/src/ic/ic-inl.h20
-rw-r--r--deps/v8/src/ic/ic.cc210
-rw-r--r--deps/v8/src/ic/ic.h46
-rw-r--r--deps/v8/src/ic/keyed-store-generic.cc152
-rw-r--r--deps/v8/src/ic/keyed-store-generic.h14
-rw-r--r--deps/v8/src/ic/stub-cache.cc2
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, &not_found);
+ TNode<NameDictionary> properties = CAST(LoadSlowProperties(CAST(receiver)));
+ NameDictionaryLookup<NameDictionary>(properties, CAST(p->name),
+ &dictionary_found, &var_name_index,
+ &not_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(&not_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,
&not_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;
}