aboutsummaryrefslogtreecommitdiff
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.cc383
1 files changed, 266 insertions, 117 deletions
diff --git a/deps/v8/src/ic/accessor-assembler.cc b/deps/v8/src/ic/accessor-assembler.cc
index 0b5e58b92e..f730c50555 100644
--- a/deps/v8/src/ic/accessor-assembler.cc
+++ b/deps/v8/src/ic/accessor-assembler.cc
@@ -4,11 +4,13 @@
#include "src/ic/accessor-assembler.h"
+#include "src/ast/ast.h"
#include "src/code-factory.h"
#include "src/code-stubs.h"
#include "src/counters.h"
#include "src/ic/handler-configuration.h"
#include "src/ic/ic.h"
+#include "src/ic/keyed-store-generic.h"
#include "src/ic/stub-cache.h"
#include "src/objects-inl.h"
#include "src/objects/module.h"
@@ -127,7 +129,7 @@ void AccessorAssembler::HandlePolymorphicCase(
Label next_entry(this);
TNode<MaybeObject> maybe_cached_map =
LoadWeakFixedArrayElement(feedback, map_index);
- CSA_ASSERT(this, IsWeakOrClearedHeapObject(maybe_cached_map));
+ CSA_ASSERT(this, IsWeakOrCleared(maybe_cached_map));
GotoIf(IsNotWeakReferenceTo(maybe_cached_map, CAST(receiver_map)),
&next_entry);
@@ -151,7 +153,7 @@ void AccessorAssembler::HandlePolymorphicCase(
Label next_entry(this);
TNode<MaybeObject> maybe_cached_map =
LoadWeakFixedArrayElement(feedback, index);
- CSA_ASSERT(this, IsWeakOrClearedHeapObject(maybe_cached_map));
+ CSA_ASSERT(this, IsWeakOrCleared(maybe_cached_map));
GotoIf(IsNotWeakReferenceTo(maybe_cached_map, CAST(receiver_map)),
&next_entry);
@@ -241,9 +243,9 @@ void AccessorAssembler::HandleLoadAccessor(
[=] { return LoadHandlerDataField(handler, 3); },
[=] { return LoadHandlerDataField(handler, 2); });
- CSA_ASSERT(this, IsWeakOrClearedHeapObject(maybe_context));
- CSA_CHECK(this, IsNotClearedWeakHeapObject(maybe_context));
- TNode<Object> context = ToWeakHeapObject(maybe_context);
+ CSA_ASSERT(this, IsWeakOrCleared(maybe_context));
+ CSA_CHECK(this, IsNotCleared(maybe_context));
+ TNode<Object> context = GetHeapObjectAssumeWeak(maybe_context);
GotoIf(IsRuntimeCallStatsEnabled(), &runtime);
{
@@ -700,8 +702,9 @@ Node* AccessorAssembler::HandleProtoHandler(
BIND(&if_do_access_check);
{
TNode<MaybeObject> data2 = LoadHandlerDataField(handler, 2);
- CSA_ASSERT(this, IsWeakOrClearedHeapObject(data2));
- TNode<Object> expected_native_context = ToWeakHeapObject(data2, miss);
+ CSA_ASSERT(this, IsWeakOrCleared(data2));
+ TNode<Object> expected_native_context =
+ GetHeapObjectAssumeWeak(data2, miss);
EmitAccessCheck(expected_native_context, p->context, p->receiver, &done,
miss);
}
@@ -773,8 +776,8 @@ void AccessorAssembler::HandleLoadICProtoHandler(
// For regular holders, having passed the receiver map check and the
// validity cell check implies that |holder| is alive. However, for global
// object receivers, |maybe_holder| may be cleared.
- CSA_ASSERT(this, IsWeakOrClearedHeapObject(maybe_holder));
- Node* holder = ToWeakHeapObject(maybe_holder, miss);
+ CSA_ASSERT(this, IsWeakOrCleared(maybe_holder));
+ Node* holder = GetHeapObjectAssumeWeak(maybe_holder, miss);
var_holder->Bind(holder);
Goto(&done);
@@ -807,9 +810,14 @@ void AccessorAssembler::EmitAccessCheck(Node* expected_native_context,
void AccessorAssembler::JumpIfDataProperty(Node* details, Label* writable,
Label* readonly) {
- // Accessor properties never have the READ_ONLY attribute set.
- GotoIf(IsSetWord32(details, PropertyDetails::kAttributesReadOnlyMask),
- readonly);
+ if (readonly) {
+ // Accessor properties never have the READ_ONLY attribute set.
+ GotoIf(IsSetWord32(details, PropertyDetails::kAttributesReadOnlyMask),
+ readonly);
+ } else {
+ CSA_ASSERT(this, IsNotSetWord32(details,
+ PropertyDetails::kAttributesReadOnlyMask));
+ }
Node* kind = DecodeWord32<PropertyDetails::KindField>(details);
GotoIf(Word32Equal(kind, Int32Constant(kData)), writable);
// Fall through if it's an accessor property.
@@ -907,7 +915,7 @@ void AccessorAssembler::HandleStoreICHandlerCase(
BIND(&if_nonsmi_handler);
{
- GotoIf(IsWeakOrClearedHeapObject(handler), &store_transition_or_global);
+ GotoIf(IsWeakOrCleared(handler), &store_transition_or_global);
TNode<HeapObject> strong_handler = CAST(handler);
TNode<Map> handler_map = LoadMap(strong_handler);
Branch(IsCodeMap(handler_map), &call_handler, &if_proto_handler);
@@ -930,8 +938,9 @@ void AccessorAssembler::HandleStoreICHandlerCase(
BIND(&store_transition_or_global);
{
// Load value or miss if the {handler} weak cell is cleared.
- CSA_ASSERT(this, IsWeakOrClearedHeapObject(handler));
- TNode<HeapObject> map_or_property_cell = ToWeakHeapObject(handler, miss);
+ CSA_ASSERT(this, IsWeakOrCleared(handler));
+ TNode<HeapObject> map_or_property_cell =
+ GetHeapObjectAssumeWeak(handler, miss);
Label store_global(this), store_transition(this);
Branch(IsMap(map_or_property_cell), &store_transition, &store_global);
@@ -946,7 +955,8 @@ void AccessorAssembler::HandleStoreICHandlerCase(
BIND(&store_transition);
{
TNode<Map> map = CAST(map_or_property_cell);
- HandleStoreICTransitionMapHandlerCase(p, map, miss, false);
+ HandleStoreICTransitionMapHandlerCase(p, map, miss,
+ kCheckPrototypeValidity);
Return(p->value);
}
}
@@ -954,10 +964,13 @@ void AccessorAssembler::HandleStoreICHandlerCase(
void AccessorAssembler::HandleStoreICTransitionMapHandlerCase(
const StoreICParameters* p, TNode<Map> transition_map, Label* miss,
- bool validate_transition_handler) {
- Node* maybe_validity_cell =
- LoadObjectField(transition_map, Map::kPrototypeValidityCellOffset);
- CheckPrototypeValidityCell(maybe_validity_cell, miss);
+ StoreTransitionMapFlags flags) {
+ DCHECK_EQ(0, flags & ~kStoreTransitionMapFlagsMask);
+ if (flags & kCheckPrototypeValidity) {
+ Node* maybe_validity_cell =
+ LoadObjectField(transition_map, Map::kPrototypeValidityCellOffset);
+ CheckPrototypeValidityCell(maybe_validity_cell, miss);
+ }
TNode<Uint32T> bitfield3 = LoadMapBitField3(transition_map);
CSA_ASSERT(this, IsClearWord32<Map::IsDictionaryMapBit>(bitfield3));
@@ -971,7 +984,7 @@ void AccessorAssembler::HandleStoreICTransitionMapHandlerCase(
Node* factor = IntPtrConstant(DescriptorArray::kEntrySize);
TNode<IntPtrT> last_key_index = UncheckedCast<IntPtrT>(IntPtrAdd(
IntPtrConstant(DescriptorArray::ToKeyIndex(-1)), IntPtrMul(nof, factor)));
- if (validate_transition_handler) {
+ if (flags & kValidateTransitionHandler) {
Node* key = LoadWeakFixedArrayElement(descriptors, last_key_index);
GotoIf(WordNotEqual(key, p->name), miss);
} else {
@@ -981,16 +994,20 @@ void AccessorAssembler::HandleStoreICTransitionMapHandlerCase(
p->name));
}
Node* details = LoadDetailsByKeyIndex(descriptors, last_key_index);
- if (validate_transition_handler) {
+ if (flags & kValidateTransitionHandler) {
// Follow transitions only in the following cases:
// 1) name is a non-private symbol and attributes equal to NONE,
// 2) name is a private symbol and attributes equal to DONT_ENUM.
Label attributes_ok(this);
- const int kAttributesDontDeleteReadOnlyMask =
+ const int kKindAndAttributesDontDeleteReadOnlyMask =
+ PropertyDetails::KindField::kMask |
PropertyDetails::kAttributesDontDeleteMask |
PropertyDetails::kAttributesReadOnlyMask;
- // Both DontDelete and ReadOnly attributes must not be set.
- GotoIf(IsSetWord32(details, kAttributesDontDeleteReadOnlyMask), miss);
+ STATIC_ASSERT(kData == 0);
+ // Both DontDelete and ReadOnly attributes must not be set and it has to be
+ // a kData property.
+ GotoIf(IsSetWord32(details, kKindAndAttributesDontDeleteReadOnlyMask),
+ miss);
// DontEnum attribute is allowed only for private symbols and vice versa.
Branch(Word32Equal(
@@ -1035,9 +1052,8 @@ void AccessorAssembler::CheckFieldType(TNode<DescriptorArray> descriptors,
Node* value_map = LoadMap(value);
// While supporting mutable HeapNumbers would be straightforward, such
// objects should not end up here anyway.
- CSA_ASSERT(this,
- WordNotEqual(value_map,
- LoadRoot(Heap::kMutableHeapNumberMapRootIndex)));
+ CSA_ASSERT(this, WordNotEqual(value_map,
+ LoadRoot(RootIndex::kMutableHeapNumberMap)));
Branch(IsHeapNumberMap(value_map), &all_fine, bailout);
}
@@ -1060,7 +1076,8 @@ void AccessorAssembler::CheckFieldType(TNode<DescriptorArray> descriptors,
&all_fine);
// Cleared weak references count as FieldType::None, which can't hold any
// value.
- TNode<Map> field_type_map = CAST(ToWeakHeapObject(field_type, bailout));
+ TNode<Map> field_type_map =
+ CAST(GetHeapObjectAssumeWeak(field_type, bailout));
// FieldType::Class(...) performs a map check.
Branch(WordEqual(LoadMap(value), field_type_map), &all_fine, bailout);
}
@@ -1270,7 +1287,7 @@ void AccessorAssembler::HandleStoreICProtoHandler(
TNode<MaybeObject> maybe_transition_map =
LoadHandlerDataField(handler, 1);
TNode<Map> transition_map =
- CAST(ToWeakHeapObject(maybe_transition_map, miss));
+ CAST(GetHeapObjectAssumeWeak(maybe_transition_map, miss));
GotoIf(IsDeprecatedMap(transition_map), miss);
@@ -1312,8 +1329,8 @@ void AccessorAssembler::HandleStoreICProtoHandler(
&if_add_normal);
TNode<MaybeObject> maybe_holder = LoadHandlerDataField(handler, 1);
- CSA_ASSERT(this, IsWeakOrClearedHeapObject(maybe_holder));
- TNode<Object> holder = ToWeakHeapObject(maybe_holder, miss);
+ CSA_ASSERT(this, IsWeakOrCleared(maybe_holder));
+ TNode<Object> holder = GetHeapObjectAssumeWeak(maybe_holder, miss);
GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kGlobalProxy)),
&if_store_global_proxy);
@@ -1374,11 +1391,10 @@ void AccessorAssembler::HandleStoreICProtoHandler(
[=] { return LoadHandlerDataField(handler, 3); },
[=] { return LoadHandlerDataField(handler, 2); });
- CSA_ASSERT(this, IsWeakOrClearedHeapObject(maybe_context));
- TNode<Object> context =
- Select<Object>(IsClearedWeakHeapObject(maybe_context),
- [=] { return SmiConstant(0); },
- [=] { return ToWeakHeapObject(maybe_context); });
+ CSA_ASSERT(this, IsWeakOrCleared(maybe_context));
+ TNode<Object> context = Select<Object>(
+ IsCleared(maybe_context), [=] { return SmiConstant(0); },
+ [=] { return GetHeapObjectAssumeWeak(maybe_context); });
Node* foreign = LoadObjectField(call_handler_info,
CallHandlerInfo::kJsCallbackOffset);
@@ -1455,7 +1471,7 @@ void AccessorAssembler::HandleStoreToProxy(const StoreICParameters* p,
TailCallRuntime(Runtime::kSetPropertyWithReceiver, p->context, proxy,
p->name, p->value, p->receiver, language_mode);
} else {
- Node* name = ToName(p->context, p->name);
+ Node* name = CallBuiltin(Builtins::kToName, p->context, p->name);
TailCallBuiltin(Builtins::kProxySetProperty, p->context, proxy, name,
p->value, p->receiver, language_mode);
}
@@ -1575,7 +1591,7 @@ Node* AccessorAssembler::PrepareValueForStore(Node* handler_word, Node* holder,
GotoIf(TaggedIsSmi(maybe_field_type), &done);
// Check that value type matches the field type.
{
- Node* field_type = ToWeakHeapObject(maybe_field_type, bailout);
+ Node* field_type = GetHeapObjectAssumeWeak(maybe_field_type, bailout);
Branch(WordEqual(LoadMap(value), field_type), &done, bailout);
}
BIND(&done);
@@ -1855,7 +1871,7 @@ void AccessorAssembler::EmitElementLoad(
GotoIf(IsDetachedBuffer(buffer), miss);
// Bounds check.
- Node* length = SmiUntag(LoadTypedArrayLength(CAST(object)));
+ Node* length = SmiUntag(LoadJSTypedArrayLength(CAST(object)));
GotoIfNot(UintPtrLessThan(intptr_index, length), out_of_bounds);
Node* backing_store = LoadFixedTypedArrayBackingStore(CAST(elements));
@@ -2082,7 +2098,7 @@ void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map,
Comment("check if string");
GotoIfNot(IsStringInstanceType(instance_type), slow);
Comment("load string character");
- Node* length = LoadAndUntagObjectField(receiver, String::kLengthOffset);
+ TNode<IntPtrT> length = LoadStringLengthAsWord(receiver);
GotoIfNot(UintPtrLessThan(index, length), slow);
IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1);
TailCallBuiltin(Builtins::kStringCharAt, NoContextConstant(), receiver,
@@ -2395,7 +2411,8 @@ void AccessorAssembler::LoadIC_BytecodeHandler(const LoadICParameters* p,
BIND(&try_polymorphic);
{
- TNode<HeapObject> strong_feedback = ToStrongHeapObject(feedback, &miss);
+ TNode<HeapObject> strong_feedback =
+ GetHeapObjectIfStrong(feedback, &miss);
GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &stub_call);
HandlePolymorphicCase(recv_map, CAST(strong_feedback), &if_handler,
&var_handler, &miss, 2);
@@ -2443,7 +2460,7 @@ void AccessorAssembler::LoadIC(const LoadICParameters* p) {
HandleLoadICHandlerCase(p, CAST(var_handler.value()), &miss, &direct_exit);
BIND(&try_polymorphic);
- TNode<HeapObject> strong_feedback = ToStrongHeapObject(feedback, &miss);
+ TNode<HeapObject> strong_feedback = GetHeapObjectIfStrong(feedback, &miss);
{
// Check polymorphic case.
Comment("LoadIC_try_polymorphic");
@@ -2480,7 +2497,7 @@ void AccessorAssembler::LoadIC_Noninlined(const LoadICParameters* p,
{
// Check megamorphic case.
- GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)),
+ GotoIfNot(WordEqual(feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
&try_uninitialized);
TryProbeStubCache(isolate()->load_stub_cache(), p->receiver, p->name,
@@ -2490,9 +2507,8 @@ void AccessorAssembler::LoadIC_Noninlined(const LoadICParameters* p,
BIND(&try_uninitialized);
{
// Check uninitialized case.
- GotoIfNot(
- WordEqual(feedback, LoadRoot(Heap::kuninitialized_symbolRootIndex)),
- miss);
+ GotoIfNot(WordEqual(feedback, LoadRoot(RootIndex::kuninitialized_symbol)),
+ miss);
exit_point->ReturnCallStub(
Builtins::CallableFor(isolate(), Builtins::kLoadIC_Uninitialized),
p->context, p->receiver, p->name, p->slot, p->vector);
@@ -2508,7 +2524,7 @@ void AccessorAssembler::LoadIC_Uninitialized(const LoadICParameters* p) {
// Optimistically write the state transition to the vector.
StoreFeedbackVectorSlot(p->vector, p->slot,
- LoadRoot(Heap::kpremonomorphic_symbolRootIndex),
+ LoadRoot(RootIndex::kpremonomorphic_symbol),
SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS);
StoreWeakReferenceInFeedbackVector(p->vector, p->slot, receiver_map,
kPointerSize, SMI_PARAMETERS);
@@ -2534,7 +2550,7 @@ void AccessorAssembler::LoadIC_Uninitialized(const LoadICParameters* p) {
{
// Undo the optimistic state transition.
StoreFeedbackVectorSlot(p->vector, p->slot,
- LoadRoot(Heap::kuninitialized_symbolRootIndex),
+ LoadRoot(RootIndex::kuninitialized_symbol),
SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS);
TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name,
@@ -2580,9 +2596,9 @@ void AccessorAssembler::LoadGlobalIC_TryPropertyCellCase(
BIND(&if_property_cell);
{
// Load value or try handler case if the weak reference is cleared.
- CSA_ASSERT(this, IsWeakOrClearedHeapObject(maybe_weak_ref));
+ CSA_ASSERT(this, IsWeakOrCleared(maybe_weak_ref));
TNode<PropertyCell> property_cell =
- CAST(ToWeakHeapObject(maybe_weak_ref, try_handler));
+ CAST(GetHeapObjectAssumeWeak(maybe_weak_ref, try_handler));
TNode<Object> value =
LoadObjectField(property_cell, PropertyCell::kValueOffset);
GotoIf(WordEqual(value, TheHoleConstant()), miss);
@@ -2616,8 +2632,7 @@ void AccessorAssembler::LoadGlobalIC_TryHandlerCase(
TNode<MaybeObject> feedback_element =
LoadFeedbackVectorSlot(vector, slot, kPointerSize, slot_mode);
TNode<Object> handler = CAST(feedback_element);
- GotoIf(WordEqual(handler, LoadRoot(Heap::kuninitialized_symbolRootIndex)),
- miss);
+ GotoIf(WordEqual(handler, LoadRoot(RootIndex::kuninitialized_symbol)), miss);
OnNonExistent on_nonexistent = typeof_mode == NOT_INSIDE_TYPEOF
? OnNonExistent::kThrowReferenceError
@@ -2660,7 +2675,7 @@ void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) {
}
BIND(&try_polymorphic);
- TNode<HeapObject> strong_feedback = ToStrongHeapObject(feedback, &miss);
+ TNode<HeapObject> strong_feedback = GetHeapObjectIfStrong(feedback, &miss);
{
// Check polymorphic case.
Comment("KeyedLoadIC_try_polymorphic");
@@ -2673,9 +2688,9 @@ void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) {
{
// Check megamorphic case.
Comment("KeyedLoadIC_try_megamorphic");
- GotoIfNot(WordEqual(strong_feedback,
- LoadRoot(Heap::kmegamorphic_symbolRootIndex)),
- &try_polymorphic_name);
+ GotoIfNot(
+ WordEqual(strong_feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
+ &try_polymorphic_name);
// TODO(jkummerow): Inline this? Or some of it?
TailCallBuiltin(Builtins::kKeyedLoadIC_Megamorphic, p->context, p->receiver,
p->name, p->slot, p->vector);
@@ -2738,29 +2753,40 @@ void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) {
void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) {
VARIABLE(var_index, MachineType::PointerRepresentation());
- VARIABLE(var_unique, MachineRepresentation::kTagged);
- var_unique.Bind(p->name); // Dummy initialization.
- Label if_index(this), if_unique_name(this), if_notunique(this), slow(this);
+ VARIABLE(var_unique, MachineRepresentation::kTagged, p->name);
+ Label if_index(this), if_unique_name(this), if_notunique(this),
+ if_other(this, Label::kDeferred), if_runtime(this, Label::kDeferred);
Node* receiver = p->receiver;
- GotoIf(TaggedIsSmi(receiver), &slow);
- Node* receiver_map = LoadMap(receiver);
- Node* instance_type = LoadMapInstanceType(receiver_map);
+ GotoIf(TaggedIsSmi(receiver), &if_runtime);
+
+ TryToName(p->name, &if_index, &var_index, &if_unique_name, &var_unique,
+ &if_other, &if_notunique);
- TryToName(p->name, &if_index, &var_index, &if_unique_name, &var_unique, &slow,
- &if_notunique);
+ BIND(&if_other);
+ {
+ Node* name = CallBuiltin(Builtins::kToName, p->context, p->name);
+ var_unique.Bind(name);
+ TryToName(name, &if_index, &var_index, &if_unique_name, &var_unique,
+ &if_runtime, &if_notunique);
+ }
BIND(&if_index);
{
+ Node* receiver_map = LoadMap(receiver);
+ Node* instance_type = LoadMapInstanceType(receiver_map);
GenericElementLoad(receiver, receiver_map, instance_type, var_index.value(),
- &slow);
+ &if_runtime);
}
BIND(&if_unique_name);
{
LoadICParameters pp = *p;
pp.name = var_unique.value();
- GenericPropertyLoad(receiver, receiver_map, instance_type, &pp, &slow);
+ Node* receiver_map = LoadMap(receiver);
+ Node* instance_type = LoadMapInstanceType(receiver_map);
+ GenericPropertyLoad(receiver, receiver_map, instance_type, &pp,
+ &if_runtime);
}
BIND(&if_notunique);
@@ -2769,10 +2795,11 @@ void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) {
// Ideally we could return undefined directly here if the name is not
// found in the string table, i.e. it was never internalized, but that
// invariant doesn't hold with named property interceptors (at this
- // point), so we take the {slow} path instead.
+ // point), so we take the {if_runtime} path instead.
Label if_in_string_table(this);
- TryInternalizeString(p->name, &if_index, &var_index, &if_in_string_table,
- &var_unique, &slow, &slow);
+ TryInternalizeString(var_unique.value(), &if_index, &var_index,
+ &if_in_string_table, &var_unique, &if_runtime,
+ &if_runtime);
BIND(&if_in_string_table);
{
@@ -2783,21 +2810,23 @@ void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) {
// cache. We may want to re-evaluate that in the future.
LoadICParameters pp = *p;
pp.name = var_unique.value();
- GenericPropertyLoad(receiver, receiver_map, instance_type, &pp, &slow,
- kDontUseStubCache);
+ Node* receiver_map = LoadMap(receiver);
+ Node* instance_type = LoadMapInstanceType(receiver_map);
+ GenericPropertyLoad(receiver, receiver_map, instance_type, &pp,
+ &if_runtime, kDontUseStubCache);
}
} else {
- Goto(&slow);
+ Goto(&if_runtime);
}
}
- BIND(&slow);
+ BIND(&if_runtime);
{
Comment("KeyedLoadGeneric_slow");
IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1);
// TODO(jkummerow): Should we use the GetProperty TF stub instead?
- TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver,
- p->name);
+ TailCallRuntime(Runtime::kGetProperty, p->context, p->receiver,
+ var_unique.value());
}
}
@@ -2868,7 +2897,7 @@ void AccessorAssembler::StoreIC(const StoreICParameters* p) {
}
BIND(&try_polymorphic);
- TNode<HeapObject> strong_feedback = ToStrongHeapObject(feedback, &miss);
+ TNode<HeapObject> strong_feedback = GetHeapObjectIfStrong(feedback, &miss);
{
// Check polymorphic case.
Comment("StoreIC_try_polymorphic");
@@ -2880,9 +2909,9 @@ void AccessorAssembler::StoreIC(const StoreICParameters* p) {
BIND(&try_megamorphic);
{
// Check megamorphic case.
- GotoIfNot(WordEqual(strong_feedback,
- LoadRoot(Heap::kmegamorphic_symbolRootIndex)),
- &try_uninitialized);
+ GotoIfNot(
+ WordEqual(strong_feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
+ &try_uninitialized);
TryProbeStubCache(isolate()->store_stub_cache(), p->receiver, p->name,
&if_handler, &var_handler, &miss);
@@ -2890,9 +2919,9 @@ void AccessorAssembler::StoreIC(const StoreICParameters* p) {
BIND(&try_uninitialized);
{
// Check uninitialized case.
- GotoIfNot(WordEqual(strong_feedback,
- LoadRoot(Heap::kuninitialized_symbolRootIndex)),
- &miss);
+ GotoIfNot(
+ WordEqual(strong_feedback, LoadRoot(RootIndex::kuninitialized_symbol)),
+ &miss);
TailCallBuiltin(Builtins::kStoreIC_Uninitialized, p->context, p->receiver,
p->name, p->value, p->slot, p->vector);
}
@@ -2912,9 +2941,9 @@ void AccessorAssembler::StoreGlobalIC(const StoreICParameters* pp) {
BIND(&if_property_cell);
{
Label try_handler(this), miss(this, Label::kDeferred);
- CSA_ASSERT(this, IsWeakOrClearedHeapObject(maybe_weak_ref));
+ CSA_ASSERT(this, IsWeakOrCleared(maybe_weak_ref));
TNode<PropertyCell> property_cell =
- CAST(ToWeakHeapObject(maybe_weak_ref, &try_handler));
+ CAST(GetHeapObjectAssumeWeak(maybe_weak_ref, &try_handler));
ExitPoint direct_exit(this);
StoreGlobalIC_PropertyCellCase(property_cell, pp->value, &direct_exit,
@@ -2926,7 +2955,7 @@ void AccessorAssembler::StoreGlobalIC(const StoreICParameters* pp) {
TNode<MaybeObject> handler = LoadFeedbackVectorSlot(
pp->vector, pp->slot, kPointerSize, SMI_PARAMETERS);
- GotoIf(WordEqual(handler, LoadRoot(Heap::kuninitialized_symbolRootIndex)),
+ GotoIf(WordEqual(handler, LoadRoot(RootIndex::kuninitialized_symbol)),
&miss);
StoreICParameters p = *pp;
@@ -3049,7 +3078,7 @@ void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p) {
}
BIND(&try_polymorphic);
- TNode<HeapObject> strong_feedback = ToStrongHeapObject(feedback, &miss);
+ TNode<HeapObject> strong_feedback = GetHeapObjectIfStrong(feedback, &miss);
{
// CheckPolymorphic case.
Comment("KeyedStoreIC_try_polymorphic");
@@ -3063,9 +3092,9 @@ void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p) {
{
// Check megamorphic case.
Comment("KeyedStoreIC_try_megamorphic");
- GotoIfNot(WordEqual(strong_feedback,
- LoadRoot(Heap::kmegamorphic_symbolRootIndex)),
- &try_polymorphic_name);
+ GotoIfNot(
+ WordEqual(strong_feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
+ &try_polymorphic_name);
TailCallBuiltin(Builtins::kKeyedStoreIC_Megamorphic, p->context,
p->receiver, p->name, p->value, p->slot, p->vector);
}
@@ -3123,7 +3152,7 @@ void AccessorAssembler::StoreInArrayLiteralIC(const StoreICParameters* p) {
TNode<MaybeObject> maybe_transition_map =
LoadHandlerDataField(CAST(handler), 1);
TNode<Map> transition_map =
- CAST(ToWeakHeapObject(maybe_transition_map, &miss));
+ CAST(GetHeapObjectAssumeWeak(maybe_transition_map, &miss));
GotoIf(IsDeprecatedMap(transition_map), &miss);
Node* code = LoadObjectField(handler, StoreHandler::kSmiHandlerOffset);
CSA_ASSERT(this, IsCode(code));
@@ -3133,7 +3162,7 @@ void AccessorAssembler::StoreInArrayLiteralIC(const StoreICParameters* p) {
}
BIND(&try_polymorphic);
- TNode<HeapObject> strong_feedback = ToStrongHeapObject(feedback, &miss);
+ TNode<HeapObject> strong_feedback = GetHeapObjectIfStrong(feedback, &miss);
{
Comment("StoreInArrayLiteralIC_try_polymorphic");
GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)),
@@ -3145,15 +3174,14 @@ void AccessorAssembler::StoreInArrayLiteralIC(const StoreICParameters* p) {
BIND(&try_megamorphic);
{
Comment("StoreInArrayLiteralIC_try_megamorphic");
- CSA_ASSERT(
- this,
- Word32Or(WordEqual(strong_feedback,
- LoadRoot(Heap::kuninitialized_symbolRootIndex)),
- WordEqual(strong_feedback,
- LoadRoot(Heap::kmegamorphic_symbolRootIndex))));
- GotoIfNot(WordEqual(strong_feedback,
- LoadRoot(Heap::kmegamorphic_symbolRootIndex)),
- &miss);
+ CSA_ASSERT(this,
+ Word32Or(WordEqual(strong_feedback,
+ LoadRoot(RootIndex::kuninitialized_symbol)),
+ WordEqual(strong_feedback,
+ LoadRoot(RootIndex::kmegamorphic_symbol))));
+ GotoIfNot(
+ WordEqual(strong_feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
+ &miss);
TailCallRuntime(Runtime::kStoreInArrayLiteralIC_Slow, p->context,
p->value, p->receiver, p->name);
}
@@ -3183,6 +3211,31 @@ void AccessorAssembler::GenerateLoadIC() {
LoadIC(&p);
}
+void AccessorAssembler::GenerateLoadIC_Megamorphic() {
+ typedef LoadWithVectorDescriptor Descriptor;
+
+ Node* receiver = Parameter(Descriptor::kReceiver);
+ Node* name = Parameter(Descriptor::kName);
+ Node* slot = Parameter(Descriptor::kSlot);
+ Node* vector = Parameter(Descriptor::kVector);
+ Node* context = Parameter(Descriptor::kContext);
+
+ ExitPoint direct_exit(this);
+ TVARIABLE(MaybeObject, var_handler);
+ Label if_handler(this, &var_handler), miss(this, Label::kDeferred);
+
+ TryProbeStubCache(isolate()->load_stub_cache(), receiver, name, &if_handler,
+ &var_handler, &miss);
+
+ BIND(&if_handler);
+ LoadICParameters p(context, receiver, name, slot, vector);
+ HandleLoadICHandlerCase(&p, CAST(var_handler.value()), &miss, &direct_exit);
+
+ BIND(&miss);
+ direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name,
+ slot, vector);
+}
+
void AccessorAssembler::GenerateLoadIC_Noninlined() {
typedef LoadWithVectorDescriptor Descriptor;
@@ -3238,6 +3291,19 @@ void AccessorAssembler::GenerateLoadICTrampoline() {
TailCallBuiltin(Builtins::kLoadIC, context, receiver, name, slot, vector);
}
+void AccessorAssembler::GenerateLoadICTrampoline_Megamorphic() {
+ typedef LoadDescriptor Descriptor;
+
+ Node* receiver = Parameter(Descriptor::kReceiver);
+ Node* name = Parameter(Descriptor::kName);
+ Node* slot = Parameter(Descriptor::kSlot);
+ Node* context = Parameter(Descriptor::kContext);
+ Node* vector = LoadFeedbackVectorForStub();
+
+ TailCallBuiltin(Builtins::kLoadIC_Megamorphic, context, receiver, name, slot,
+ vector);
+}
+
void AccessorAssembler::GenerateLoadGlobalIC(TypeofMode typeof_mode) {
typedef LoadGlobalWithVectorDescriptor Descriptor;
@@ -3280,6 +3346,19 @@ void AccessorAssembler::GenerateKeyedLoadIC() {
KeyedLoadIC(&p);
}
+void AccessorAssembler::GenerateKeyedLoadIC_Megamorphic() {
+ typedef LoadWithVectorDescriptor Descriptor;
+
+ Node* receiver = Parameter(Descriptor::kReceiver);
+ Node* name = Parameter(Descriptor::kName);
+ Node* slot = Parameter(Descriptor::kSlot);
+ Node* vector = Parameter(Descriptor::kVector);
+ Node* context = Parameter(Descriptor::kContext);
+
+ LoadICParameters p(context, receiver, name, slot, vector);
+ KeyedLoadICGeneric(&p);
+}
+
void AccessorAssembler::GenerateKeyedLoadICTrampoline() {
typedef LoadDescriptor Descriptor;
@@ -3293,17 +3372,17 @@ void AccessorAssembler::GenerateKeyedLoadICTrampoline() {
vector);
}
-void AccessorAssembler::GenerateKeyedLoadIC_Megamorphic() {
- typedef LoadWithVectorDescriptor Descriptor;
+void AccessorAssembler::GenerateKeyedLoadICTrampoline_Megamorphic() {
+ typedef LoadDescriptor Descriptor;
Node* receiver = Parameter(Descriptor::kReceiver);
Node* name = Parameter(Descriptor::kName);
Node* slot = Parameter(Descriptor::kSlot);
- Node* vector = Parameter(Descriptor::kVector);
Node* context = Parameter(Descriptor::kContext);
+ Node* vector = LoadFeedbackVectorForStub();
- LoadICParameters p(context, receiver, name, slot, vector);
- KeyedLoadICGeneric(&p);
+ TailCallBuiltin(Builtins::kKeyedLoadIC_Megamorphic, context, receiver, name,
+ slot, vector);
}
void AccessorAssembler::GenerateKeyedLoadIC_PolymorphicName() {
@@ -3414,6 +3493,76 @@ void AccessorAssembler::GenerateStoreInArrayLiteralIC() {
StoreInArrayLiteralIC(&p);
}
+void AccessorAssembler::GenerateCloneObjectIC_Slow() {
+ typedef CloneObjectWithVectorDescriptor Descriptor;
+ TNode<HeapObject> source = CAST(Parameter(Descriptor::kSource));
+ TNode<Smi> flags = CAST(Parameter(Descriptor::kFlags));
+ TNode<Context> context = CAST(Parameter(Descriptor::kContext));
+
+ // The Slow case uses the same call interface as CloneObjectIC, so that it
+ // can be tail called from it. However, the feedback slot and vector are not
+ // used.
+
+ TNode<Context> native_context = LoadNativeContext(context);
+ TNode<JSFunction> object_fn =
+ CAST(LoadContextElement(native_context, Context::OBJECT_FUNCTION_INDEX));
+ TNode<Map> initial_map = CAST(
+ LoadObjectField(object_fn, JSFunction::kPrototypeOrInitialMapOffset));
+ CSA_ASSERT(this, IsMap(initial_map));
+
+ TNode<JSObject> result = CAST(AllocateJSObjectFromMap(initial_map));
+
+ {
+ Label did_set_proto_if_needed(this);
+ TNode<BoolT> is_null_proto = SmiNotEqual(
+ SmiAnd(flags, SmiConstant(ObjectLiteral::kHasNullPrototype)),
+ SmiConstant(Smi::kZero));
+ GotoIfNot(is_null_proto, &did_set_proto_if_needed);
+
+ CallRuntime(Runtime::kInternalSetPrototype, context, result,
+ NullConstant());
+
+ Goto(&did_set_proto_if_needed);
+ BIND(&did_set_proto_if_needed);
+ }
+
+ ReturnIf(IsNullOrUndefined(source), result);
+
+ CSA_ASSERT(this, IsJSReceiver(source));
+
+ Label call_runtime(this, Label::kDeferred);
+ Label done(this);
+
+ TNode<Map> map = LoadMap(source);
+ TNode<Int32T> type = LoadMapInstanceType(map);
+ {
+ Label cont(this);
+ GotoIf(IsJSObjectInstanceType(type), &cont);
+ GotoIfNot(IsStringInstanceType(type), &done);
+ Branch(SmiEqual(LoadStringLengthAsSmi(CAST(source)), SmiConstant(0)), &done,
+ &call_runtime);
+ BIND(&cont);
+ }
+
+ GotoIfNot(IsEmptyFixedArray(LoadElements(CAST(source))), &call_runtime);
+
+ ForEachEnumerableOwnProperty(
+ context, map, CAST(source),
+ [=](TNode<Name> key, TNode<Object> value) {
+ KeyedStoreGenericGenerator::SetPropertyInLiteral(state(), context,
+ result, key, value);
+ },
+ &call_runtime);
+ Goto(&done);
+
+ BIND(&call_runtime);
+ CallRuntime(Runtime::kCopyDataProperties, context, result, source);
+
+ Goto(&done);
+ BIND(&done);
+ Return(result);
+}
+
void AccessorAssembler::GenerateCloneObjectIC() {
typedef CloneObjectWithVectorDescriptor Descriptor;
Node* source = Parameter(Descriptor::kSource);
@@ -3502,7 +3651,7 @@ void AccessorAssembler::GenerateCloneObjectIC() {
}
BIND(&try_polymorphic);
- TNode<HeapObject> strong_feedback = ToStrongHeapObject(feedback, &miss);
+ TNode<HeapObject> strong_feedback = GetHeapObjectIfStrong(feedback, &miss);
{
Comment("CloneObjectIC_try_polymorphic");
GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &try_megamorphic);
@@ -3513,16 +3662,16 @@ void AccessorAssembler::GenerateCloneObjectIC() {
BIND(&try_megamorphic);
{
Comment("CloneObjectIC_try_megamorphic");
- CSA_ASSERT(
- this,
- Word32Or(WordEqual(strong_feedback,
- LoadRoot(Heap::kuninitialized_symbolRootIndex)),
- WordEqual(strong_feedback,
- LoadRoot(Heap::kmegamorphic_symbolRootIndex))));
- GotoIfNot(WordEqual(strong_feedback,
- LoadRoot(Heap::kmegamorphic_symbolRootIndex)),
- &miss);
- TailCallRuntime(Runtime::kCloneObjectIC_Slow, context, source, flags);
+ CSA_ASSERT(this,
+ Word32Or(WordEqual(strong_feedback,
+ LoadRoot(RootIndex::kuninitialized_symbol)),
+ WordEqual(strong_feedback,
+ LoadRoot(RootIndex::kmegamorphic_symbol))));
+ GotoIfNot(
+ WordEqual(strong_feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
+ &miss);
+ TailCallBuiltin(Builtins::kCloneObjectIC_Slow, context, source, flags, slot,
+ vector);
}
BIND(&miss);