summaryrefslogtreecommitdiff
path: root/deps/v8/src/ic
diff options
context:
space:
mode:
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.h14
-rw-r--r--deps/v8/src/ic/binary-op-assembler.cc5
-rw-r--r--deps/v8/src/ic/call-optimization.h2
-rw-r--r--deps/v8/src/ic/handler-configuration.cc4
-rw-r--r--deps/v8/src/ic/handler-configuration.h2
-rw-r--r--deps/v8/src/ic/ic-inl.h7
-rw-r--r--deps/v8/src/ic/ic-stats.cc2
-rw-r--r--deps/v8/src/ic/ic.cc60
-rw-r--r--deps/v8/src/ic/ic.h11
-rw-r--r--deps/v8/src/ic/keyed-store-generic.cc306
-rw-r--r--deps/v8/src/ic/keyed-store-generic.h5
12 files changed, 562 insertions, 239 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);
diff --git a/deps/v8/src/ic/accessor-assembler.h b/deps/v8/src/ic/accessor-assembler.h
index 0de48e021a..3d92ab26c3 100644
--- a/deps/v8/src/ic/accessor-assembler.h
+++ b/deps/v8/src/ic/accessor-assembler.h
@@ -28,18 +28,22 @@ class AccessorAssembler : public CodeStubAssembler {
: CodeStubAssembler(state) {}
void GenerateLoadIC();
+ void GenerateLoadIC_Megamorphic();
void GenerateLoadIC_Noninlined();
void GenerateLoadIC_Uninitialized();
void GenerateLoadICTrampoline();
+ void GenerateLoadICTrampoline_Megamorphic();
void GenerateKeyedLoadIC();
- void GenerateKeyedLoadICTrampoline();
void GenerateKeyedLoadIC_Megamorphic();
void GenerateKeyedLoadIC_PolymorphicName();
+ void GenerateKeyedLoadICTrampoline();
+ void GenerateKeyedLoadICTrampoline_Megamorphic();
void GenerateStoreIC();
void GenerateStoreICTrampoline();
void GenerateStoreGlobalIC();
void GenerateStoreGlobalICTrampoline();
void GenerateCloneObjectIC();
+ void GenerateCloneObjectIC_Slow();
void GenerateLoadGlobalIC(TypeofMode typeof_mode);
void GenerateLoadGlobalICTrampoline(TypeofMode typeof_mode);
@@ -106,10 +110,16 @@ class AccessorAssembler : public CodeStubAssembler {
void HandleStoreICHandlerCase(
const StoreICParameters* p, TNode<MaybeObject> handler, Label* miss,
ICMode ic_mode, ElementSupport support_elements = kOnlyProperties);
+ enum StoreTransitionMapFlags {
+ kCheckPrototypeValidity = 1 << 0,
+ kValidateTransitionHandler = 1 << 1,
+ kStoreTransitionMapFlagsMask =
+ kCheckPrototypeValidity | kValidateTransitionHandler,
+ };
void HandleStoreICTransitionMapHandlerCase(const StoreICParameters* p,
TNode<Map> transition_map,
Label* miss,
- bool validate_transition_handler);
+ StoreTransitionMapFlags flags);
void JumpIfDataProperty(Node* details, Label* writable, Label* readonly);
diff --git a/deps/v8/src/ic/binary-op-assembler.cc b/deps/v8/src/ic/binary-op-assembler.cc
index 9016e9ba18..ebe64437c6 100644
--- a/deps/v8/src/ic/binary-op-assembler.cc
+++ b/deps/v8/src/ic/binary-op-assembler.cc
@@ -162,9 +162,8 @@ Node* BinaryOpAssembler::Generate_AddWithFeedback(Node* context, Node* lhs,
&call_with_any_feedback);
var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kString));
- Callable callable =
- CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED);
- var_result.Bind(CallStub(callable, context, lhs, rhs));
+ var_result.Bind(
+ CallBuiltin(Builtins::kStringAdd_CheckNone, context, lhs, rhs));
Goto(&end);
}
diff --git a/deps/v8/src/ic/call-optimization.h b/deps/v8/src/ic/call-optimization.h
index d87ec4fdb1..e3115bdbcd 100644
--- a/deps/v8/src/ic/call-optimization.h
+++ b/deps/v8/src/ic/call-optimization.h
@@ -12,7 +12,7 @@
namespace v8 {
namespace internal {
// Holds information about possible function call optimizations.
-class CallOptimization BASE_EMBEDDED {
+class CallOptimization {
public:
CallOptimization(Isolate* isolate, Handle<Object> function);
diff --git a/deps/v8/src/ic/handler-configuration.cc b/deps/v8/src/ic/handler-configuration.cc
index 86ea4f9d3b..73ab0de645 100644
--- a/deps/v8/src/ic/handler-configuration.cc
+++ b/deps/v8/src/ic/handler-configuration.cc
@@ -140,7 +140,7 @@ Handle<Object> LoadHandler::LoadFromPrototype(Isolate* isolate,
// static
Handle<Object> LoadHandler::LoadFullChain(Isolate* isolate,
Handle<Map> receiver_map,
- MaybeObjectHandle holder,
+ const MaybeObjectHandle& holder,
Handle<Smi> smi_handler) {
Handle<JSReceiver> end; // null handle, means full prototype chain lookup.
MaybeObjectHandle data1 = holder;
@@ -168,7 +168,7 @@ Handle<Object> LoadHandler::LoadFullChain(Isolate* isolate,
KeyedAccessLoadMode LoadHandler::GetKeyedAccessLoadMode(MaybeObject* handler) {
DisallowHeapAllocation no_gc;
if (handler->IsSmi()) {
- int const raw_handler = Smi::cast(handler->ToSmi())->value();
+ int const raw_handler = handler->cast<Smi>()->value();
Kind const kind = KindBits::decode(raw_handler);
if ((kind == kElement || kind == kIndexedString) &&
AllowOutOfBoundsBits::decode(raw_handler)) {
diff --git a/deps/v8/src/ic/handler-configuration.h b/deps/v8/src/ic/handler-configuration.h
index 305577a2df..72ab68140e 100644
--- a/deps/v8/src/ic/handler-configuration.h
+++ b/deps/v8/src/ic/handler-configuration.h
@@ -150,7 +150,7 @@ class LoadHandler final : public DataHandler {
// needed (e.g., for "nonexistent"), null_value() may be passed in.
static Handle<Object> LoadFullChain(Isolate* isolate,
Handle<Map> receiver_map,
- MaybeObjectHandle holder,
+ const MaybeObjectHandle& holder,
Handle<Smi> smi_handler);
// Creates a data handler that represents a prototype chain check followed
diff --git a/deps/v8/src/ic/ic-inl.h b/deps/v8/src/ic/ic-inl.h
index 640bf7250c..101703dc28 100644
--- a/deps/v8/src/ic/ic-inl.h
+++ b/deps/v8/src/ic/ic-inl.h
@@ -50,11 +50,10 @@ void IC::update_receiver_map(Handle<Object> receiver) {
bool IC::IsHandler(MaybeObject* object) {
HeapObject* heap_object;
return (object->IsSmi() && (object != nullptr)) ||
- (object->ToWeakHeapObject(&heap_object) &&
+ (object->GetHeapObjectIfWeak(&heap_object) &&
(heap_object->IsMap() || heap_object->IsPropertyCell())) ||
- (object->ToStrongHeapObject(&heap_object) &&
- (heap_object->IsDataHandler() ||
- heap_object->IsCode()));
+ (object->GetHeapObjectIfStrong(&heap_object) &&
+ (heap_object->IsDataHandler() || heap_object->IsCode()));
}
bool IC::AddressIsDeoptimizedCode() const {
diff --git a/deps/v8/src/ic/ic-stats.cc b/deps/v8/src/ic/ic-stats.cc
index c305209d48..0c33863d3d 100644
--- a/deps/v8/src/ic/ic-stats.cc
+++ b/deps/v8/src/ic/ic-stats.cc
@@ -95,7 +95,7 @@ ICInfo::ICInfo()
is_constructor(false),
is_optimized(false),
map(nullptr),
- is_dictionary_map(0),
+ is_dictionary_map(false),
number_of_own_descriptors(0) {}
void ICInfo::Reset() {
diff --git a/deps/v8/src/ic/ic.cc b/deps/v8/src/ic/ic.cc
index 9237441ac9..3ca62d0bb4 100644
--- a/deps/v8/src/ic/ic.cc
+++ b/deps/v8/src/ic/ic.cc
@@ -1260,9 +1260,8 @@ MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
return result;
}
-
bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
- JSReceiver::StoreFromKeyed store_mode) {
+ StoreOrigin store_origin) {
// Disable ICs for non-JSObjects for now.
Handle<Object> object = it->GetReceiver();
if (object->IsJSProxy()) return true;
@@ -1319,7 +1318,7 @@ bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
if (it->ExtendingNonExtensible(receiver)) return false;
it->PrepareTransitionToDataProperty(receiver, value, NONE,
- store_mode);
+ store_origin);
return it->IsCacheableTransition();
}
}
@@ -1328,7 +1327,7 @@ bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
receiver = it->GetStoreTarget<JSObject>();
if (it->ExtendingNonExtensible(receiver)) return false;
- it->PrepareTransitionToDataProperty(receiver, value, NONE, store_mode);
+ it->PrepareTransitionToDataProperty(receiver, value, NONE, store_origin);
return it->IsCacheableTransition();
}
@@ -1381,7 +1380,7 @@ MaybeHandle<Object> StoreGlobalIC::Store(Handle<Name> name,
MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
Handle<Object> value,
- JSReceiver::StoreFromKeyed store_mode) {
+ StoreOrigin store_origin) {
// TODO(verwaest): Let SetProperty do the migration, since storing a property
// might deprecate the current map again, if value does not fit.
if (MigrateDeprecated(object)) {
@@ -1424,15 +1423,15 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
use_ic = false;
}
}
- if (use_ic) UpdateCaches(&it, value, store_mode);
+ if (use_ic) UpdateCaches(&it, value, store_origin);
MAYBE_RETURN_NULL(
- Object::SetProperty(&it, value, language_mode(), store_mode));
+ Object::SetProperty(&it, value, language_mode(), store_origin));
return value;
}
void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
- JSReceiver::StoreFromKeyed store_mode) {
+ StoreOrigin store_origin) {
if (state() == UNINITIALIZED && !IsStoreGlobalIC()) {
// This is the first time we execute this inline cache. Transition
// to premonomorphic state to delay setting the monomorphic state.
@@ -1443,7 +1442,7 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
}
MaybeObjectHandle handler;
- if (LookupForWrite(lookup, value, store_mode)) {
+ if (LookupForWrite(lookup, value, store_origin)) {
if (IsStoreGlobalIC()) {
if (lookup->state() == LookupIterator::DATA &&
lookup->GetReceiver().is_identical_to(lookup->GetHolder<Object>())) {
@@ -1988,8 +1987,9 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
if (MigrateDeprecated(object)) {
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION(
- isolate(), result, Runtime::SetObjectProperty(isolate(), object, key,
- value, language_mode()),
+ isolate(), result,
+ Runtime::SetObjectProperty(isolate(), object, key, value,
+ language_mode(), StoreOrigin::kMaybeKeyed),
Object);
return result;
}
@@ -2004,11 +2004,10 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
if ((key->IsInternalizedString() &&
!String::cast(*key)->AsArrayIndex(&index)) ||
key->IsSymbol()) {
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate(), store_handle,
- StoreIC::Store(object, Handle<Name>::cast(key), value,
- JSReceiver::MAY_BE_STORE_FROM_KEYED),
- Object);
+ ASSIGN_RETURN_ON_EXCEPTION(isolate(), store_handle,
+ StoreIC::Store(object, Handle<Name>::cast(key),
+ value, StoreOrigin::kMaybeKeyed),
+ Object);
if (vector_needs_update()) {
if (ConfigureVectorState(MEGAMORPHIC, key)) {
set_slow_stub_reason("unhandled internalized string key");
@@ -2062,10 +2061,11 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
bool receiver_was_cow =
object->IsJSArray() &&
Handle<JSArray>::cast(object)->elements()->IsCowArray();
- ASSIGN_RETURN_ON_EXCEPTION(isolate(), store_handle,
- Runtime::SetObjectProperty(isolate(), object, key,
- value, language_mode()),
- Object);
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate(), store_handle,
+ Runtime::SetObjectProperty(isolate(), object, key, value, language_mode(),
+ StoreOrigin::kMaybeKeyed),
+ Object);
if (use_ic) {
if (!old_receiver_map.is_null()) {
@@ -2359,7 +2359,8 @@ RUNTIME_FUNCTION(Runtime_StoreGlobalIC_Slow) {
LanguageMode language_mode = vector->GetLanguageMode(vector_slot);
RETURN_RESULT_OR_FAILURE(
isolate,
- Runtime::SetObjectProperty(isolate, global, name, value, language_mode));
+ Runtime::SetObjectProperty(isolate, global, name, value, language_mode,
+ StoreOrigin::kMaybeKeyed));
}
RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) {
@@ -2406,7 +2407,8 @@ RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) {
LanguageMode language_mode = GetLanguageModeFromSlotKind(kind);
RETURN_RESULT_OR_FAILURE(
isolate,
- Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
+ Runtime::SetObjectProperty(isolate, object, key, value, language_mode,
+ StoreOrigin::kMaybeKeyed));
}
RUNTIME_FUNCTION(Runtime_StoreInArrayLiteralIC_Slow) {
@@ -2446,7 +2448,8 @@ RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) {
LanguageMode language_mode = GetLanguageModeFromSlotKind(kind);
RETURN_RESULT_OR_FAILURE(
isolate,
- Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
+ Runtime::SetObjectProperty(isolate, object, key, value, language_mode,
+ StoreOrigin::kMaybeKeyed));
}
}
@@ -2595,8 +2598,9 @@ RUNTIME_FUNCTION(Runtime_StoreCallbackProperty) {
if (V8_UNLIKELY(FLAG_runtime_stats)) {
RETURN_RESULT_OR_FAILURE(
- isolate, Runtime::SetObjectProperty(isolate, receiver, name, value,
- language_mode));
+ isolate,
+ Runtime::SetObjectProperty(isolate, receiver, name, value,
+ language_mode, StoreOrigin::kMaybeKeyed));
}
DCHECK(info->IsCompatibleReceiver(*receiver));
@@ -2747,9 +2751,9 @@ RUNTIME_FUNCTION(Runtime_StorePropertyWithInterceptor) {
DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
it.Next();
- MAYBE_RETURN(Object::SetProperty(&it, value, language_mode,
- JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED),
- ReadOnlyRoots(isolate).exception());
+ MAYBE_RETURN(
+ Object::SetProperty(&it, value, language_mode, StoreOrigin::kNamed),
+ ReadOnlyRoots(isolate).exception());
return *value;
}
diff --git a/deps/v8/src/ic/ic.h b/deps/v8/src/ic/ic.h
index 0a831b757f..05bde1ff61 100644
--- a/deps/v8/src/ic/ic.h
+++ b/deps/v8/src/ic/ic.h
@@ -36,7 +36,7 @@ class IC {
// Construct the IC structure with the given number of extra
// JavaScript frames on the stack.
IC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot);
- virtual ~IC() {}
+ virtual ~IC() = default;
State state() const { return state_; }
inline Address address() const;
@@ -88,7 +88,7 @@ class IC {
bool vector_needs_update() {
return (!vector_set_ &&
(state() != MEGAMORPHIC ||
- Smi::ToInt(nexus()->GetFeedbackExtra()->ToSmi()) != ELEMENT));
+ Smi::ToInt(nexus()->GetFeedbackExtra()->cast<Smi>()) != ELEMENT));
}
// Configure for most states.
@@ -296,11 +296,10 @@ class StoreIC : public IC {
V8_WARN_UNUSED_RESULT MaybeHandle<Object> Store(
Handle<Object> object, Handle<Name> name, Handle<Object> value,
- JSReceiver::StoreFromKeyed store_mode =
- JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED);
+ StoreOrigin store_origin = StoreOrigin::kNamed);
bool LookupForWrite(LookupIterator* it, Handle<Object> value,
- JSReceiver::StoreFromKeyed store_mode);
+ StoreOrigin store_origin);
protected:
// Stub accessors.
@@ -312,7 +311,7 @@ class StoreIC : public IC {
// Update the inline cache and the global stub cache based on the
// lookup result.
void UpdateCaches(LookupIterator* lookup, Handle<Object> value,
- JSReceiver::StoreFromKeyed store_mode);
+ StoreOrigin store_origin);
private:
MaybeObjectHandle ComputeHandler(LookupIterator* lookup);
diff --git a/deps/v8/src/ic/keyed-store-generic.cc b/deps/v8/src/ic/keyed-store-generic.cc
index 23c49c8d73..2b2f15bb82 100644
--- a/deps/v8/src/ic/keyed-store-generic.cc
+++ b/deps/v8/src/ic/keyed-store-generic.cc
@@ -43,6 +43,18 @@ class KeyedStoreGenericAssembler : public AccessorAssembler {
TNode<Object> key, TNode<Object> value,
LanguageMode language_mode);
+ // Set an own property
+ void SetPropertyInLiteral(TNode<Context> context, TNode<JSObject> receiver,
+ TNode<Map> map, TNode<Name> key,
+ TNode<Object> value) {
+ Label done(this);
+ ExitPoint exit_point(this,
+ [this, &done](Node* result) { this->Goto(&done); });
+ EmitGenericPropertyStoreInLiteral(context, receiver, map, key, value,
+ &exit_point);
+ BIND(&done);
+ }
+
private:
enum UpdateLength {
kDontChangeLength,
@@ -78,6 +90,12 @@ class KeyedStoreGenericAssembler : public AccessorAssembler {
Nothing<LanguageMode>());
}
+ void EmitGenericPropertyStoreInLiteral(TNode<Context> context,
+ TNode<JSObject> receiver,
+ TNode<Map> map, TNode<Name> key,
+ TNode<Object> value,
+ ExitPoint* exit_point);
+
void BranchIfPrototypesHaveNonFastElements(Node* receiver_map,
Label* non_fast_elements,
Label* only_fast_elements);
@@ -111,6 +129,10 @@ class KeyedStoreGenericAssembler : public AccessorAssembler {
Variable* var_accessor_pair,
Variable* var_accessor_holder,
Label* readonly, Label* bailout);
+
+ TNode<Map> FindCandidateStoreICTransitionMapHandler(TNode<Map> map,
+ TNode<Name> name,
+ Label* slow);
};
void KeyedStoreGenericGenerator::Generate(compiler::CodeAssemblerState* state) {
@@ -141,6 +163,14 @@ void KeyedStoreGenericGenerator::SetProperty(
assembler.SetProperty(context, receiver, key, value, language_mode);
}
+void KeyedStoreGenericGenerator::SetPropertyInLiteral(
+ compiler::CodeAssemblerState* state, TNode<Context> context,
+ TNode<JSObject> receiver, TNode<Name> key, TNode<Object> value) {
+ KeyedStoreGenericAssembler assembler(state);
+ TNode<Map> map = assembler.LoadMap(receiver);
+ assembler.SetPropertyInLiteral(context, receiver, map, key, value);
+}
+
void KeyedStoreGenericAssembler::BranchIfPrototypesHaveNonFastElements(
Node* receiver_map, Label* non_fast_elements, Label* only_fast_elements) {
VARIABLE(var_map, MachineRepresentation::kTagged);
@@ -294,7 +324,7 @@ void KeyedStoreGenericAssembler::StoreElementWithCapacity(
Label check_double_elements(this), check_cow_elements(this);
Node* elements_map = LoadMap(elements);
- GotoIf(WordNotEqual(elements_map, LoadRoot(Heap::kFixedArrayMapRootIndex)),
+ GotoIf(WordNotEqual(elements_map, LoadRoot(RootIndex::kFixedArrayMap)),
&check_double_elements);
// FixedArray backing store -> Smi or object elements.
@@ -355,7 +385,7 @@ void KeyedStoreGenericAssembler::StoreElementWithCapacity(
{
Label transition_to_double(this), transition_to_object(this);
Node* native_context = LoadNativeContext(context);
- Branch(WordEqual(LoadMap(value), LoadRoot(Heap::kHeapNumberMapRootIndex)),
+ Branch(WordEqual(LoadMap(value), LoadRoot(RootIndex::kHeapNumberMap)),
&transition_to_double, &transition_to_object);
BIND(&transition_to_double);
{
@@ -398,7 +428,7 @@ void KeyedStoreGenericAssembler::StoreElementWithCapacity(
}
BIND(&check_double_elements);
- Node* fixed_double_array_map = LoadRoot(Heap::kFixedDoubleArrayMapRootIndex);
+ Node* fixed_double_array_map = LoadRoot(RootIndex::kFixedDoubleArrayMap);
GotoIf(WordNotEqual(elements_map, fixed_double_array_map),
&check_cow_elements);
// FixedDoubleArray backing store -> double elements.
@@ -656,6 +686,71 @@ void KeyedStoreGenericAssembler::LookupPropertyOnPrototypeChain(
BIND(&ok_to_write);
}
+TNode<Map> KeyedStoreGenericAssembler::FindCandidateStoreICTransitionMapHandler(
+ TNode<Map> map, TNode<Name> name, Label* slow) {
+ TVARIABLE(Map, var_transition_map);
+ Label simple_transition(this), transition_array(this),
+ found_handler_candidate(this);
+
+ TNode<MaybeObject> maybe_handler =
+ LoadMaybeWeakObjectField(map, Map::kTransitionsOrPrototypeInfoOffset);
+
+ // Smi -> slow,
+ // Cleared weak reference -> slow
+ // weak reference -> simple_transition
+ // strong reference -> transition_array
+ TVARIABLE(Object, var_transition_map_or_array);
+ DispatchMaybeObject(maybe_handler, slow, slow, &simple_transition,
+ &transition_array, &var_transition_map_or_array);
+
+ BIND(&simple_transition);
+ {
+ var_transition_map = CAST(var_transition_map_or_array.value());
+ Goto(&found_handler_candidate);
+ }
+
+ BIND(&transition_array);
+ {
+ TNode<Map> maybe_handler_map =
+ LoadMap(CAST(var_transition_map_or_array.value()));
+ GotoIfNot(IsTransitionArrayMap(maybe_handler_map), slow);
+
+ TVARIABLE(IntPtrT, var_name_index);
+ Label if_found_candidate(this);
+ TNode<TransitionArray> transitions =
+ CAST(var_transition_map_or_array.value());
+ TransitionLookup(name, transitions, &if_found_candidate, &var_name_index,
+ slow);
+
+ BIND(&if_found_candidate);
+ {
+ // Given that
+ // 1) transitions with the same name are ordered in the transition
+ // array by PropertyKind and then by PropertyAttributes values,
+ // 2) kData < kAccessor,
+ // 3) NONE == 0,
+ // 4) properties with private symbol names are guaranteed to be
+ // non-enumerable (so DONT_ENUM bit in attributes is always set),
+ // the resulting map of transitioning store if it exists in the
+ // transition array is expected to be the first among the transitions
+ // with the same name.
+ // See TransitionArray::CompareDetails() for details.
+ STATIC_ASSERT(kData == 0);
+ STATIC_ASSERT(NONE == 0);
+ const int kKeyToTargetOffset = (TransitionArray::kEntryTargetIndex -
+ TransitionArray::kEntryKeyIndex) *
+ kPointerSize;
+ var_transition_map = CAST(GetHeapObjectAssumeWeak(
+ LoadArrayElement(transitions, WeakFixedArray::kHeaderSize,
+ var_name_index.value(), kKeyToTargetOffset)));
+ Goto(&found_handler_candidate);
+ }
+ }
+
+ BIND(&found_handler_candidate);
+ return var_transition_map.value();
+}
+
void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
TNode<JSReceiver> receiver, TNode<Map> receiver_map,
const StoreICParameters* p, ExitPoint* exit_point, Label* slow,
@@ -705,71 +800,15 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
BIND(&lookup_transition);
{
Comment("lookup transition");
- TVARIABLE(Map, var_transition_map);
- Label simple_transition(this), transition_array(this),
- found_handler_candidate(this);
- TNode<MaybeObject> maybe_handler = LoadMaybeWeakObjectField(
- receiver_map, Map::kTransitionsOrPrototypeInfoOffset);
-
- // SMI -> slow
- // cleared weak reference -> slow
- // weak reference -> simple_transition
- // strong reference -> transition_array
- TVARIABLE(Object, var_transition_map_or_array);
- DispatchMaybeObject(maybe_handler, slow, slow, &simple_transition,
- &transition_array, &var_transition_map_or_array);
-
- BIND(&simple_transition);
- {
- var_transition_map = CAST(var_transition_map_or_array.value());
- Goto(&found_handler_candidate);
- }
-
- BIND(&transition_array);
- {
- TNode<Map> maybe_handler_map =
- LoadMap(CAST(var_transition_map_or_array.value()));
- GotoIfNot(IsTransitionArrayMap(maybe_handler_map), slow);
-
- TVARIABLE(IntPtrT, var_name_index);
- Label if_found_candidate(this);
- TNode<TransitionArray> transitions =
- CAST(var_transition_map_or_array.value());
- TransitionLookup(p->name, transitions, &if_found_candidate,
- &var_name_index, slow);
-
- BIND(&if_found_candidate);
- {
- // Given that
- // 1) transitions with the same name are ordered in the transition
- // array by PropertyKind and then by PropertyAttributes values,
- // 2) kData < kAccessor,
- // 3) NONE == 0,
- // 4) properties with private symbol names are guaranteed to be
- // non-enumerable (so DONT_ENUM bit in attributes is always set),
- // the resulting map of transitioning store if it exists in the
- // transition array is expected to be the first among the transitions
- // with the same name.
- // See TransitionArray::CompareDetails() for details.
- STATIC_ASSERT(kData == 0);
- STATIC_ASSERT(NONE == 0);
- const int kKeyToTargetOffset = (TransitionArray::kEntryTargetIndex -
- TransitionArray::kEntryKeyIndex) *
- kPointerSize;
- var_transition_map = CAST(ToWeakHeapObject(
- LoadArrayElement(transitions, WeakFixedArray::kHeaderSize,
- var_name_index.value(), kKeyToTargetOffset)));
- Goto(&found_handler_candidate);
- }
- }
-
- BIND(&found_handler_candidate);
- {
- // Validate the transition handler candidate and apply the transition.
- HandleStoreICTransitionMapHandlerCase(p, var_transition_map.value(),
- slow, true);
- exit_point->Return(p->value);
- }
+ TNode<Map> transition_map = FindCandidateStoreICTransitionMapHandler(
+ receiver_map, CAST(p->name), slow);
+
+ // Validate the transition handler candidate and apply the transition.
+ HandleStoreICTransitionMapHandlerCase(
+ p, transition_map, slow,
+ StoreTransitionMapFlags(kCheckPrototypeValidity |
+ kValidateTransitionHandler));
+ exit_point->Return(p->value);
}
}
@@ -952,7 +991,7 @@ void KeyedStoreGenericAssembler::KeyedStoreGeneric(
{
Comment("KeyedStoreGeneric_slow");
if (language_mode.IsJust()) {
- TailCallRuntime(Runtime::kSetProperty, context, receiver, key, value,
+ TailCallRuntime(Runtime::kSetKeyedProperty, context, receiver, key, value,
SmiConstant(language_mode.FromJust()));
} else {
TVARIABLE(Smi, var_language_mode, SmiConstant(LanguageMode::kStrict));
@@ -961,7 +1000,7 @@ void KeyedStoreGenericAssembler::KeyedStoreGeneric(
var_language_mode = SmiConstant(LanguageMode::kSloppy);
Goto(&call_runtime);
BIND(&call_runtime);
- TailCallRuntime(Runtime::kSetProperty, context, receiver, key, value,
+ TailCallRuntime(Runtime::kSetKeyedProperty, context, receiver, key, value,
var_language_mode.value());
}
}
@@ -1011,7 +1050,7 @@ void KeyedStoreGenericAssembler::StoreIC_Uninitialized() {
// Optimistically write the state transition to the vector.
StoreFeedbackVectorSlot(vector, slot,
- LoadRoot(Heap::kpremonomorphic_symbolRootIndex),
+ LoadRoot(RootIndex::kpremonomorphic_symbol),
SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS);
StoreICParameters p(context, receiver, name, value, slot, vector);
@@ -1021,7 +1060,7 @@ void KeyedStoreGenericAssembler::StoreIC_Uninitialized() {
{
// Undo the optimistic state transition.
StoreFeedbackVectorSlot(vector, slot,
- LoadRoot(Heap::kuninitialized_symbolRootIndex),
+ LoadRoot(RootIndex::kuninitialized_symbol),
SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS);
TailCallRuntime(Runtime::kStoreIC_Miss, context, value, slot, vector,
receiver, name);
@@ -1048,13 +1087,132 @@ void KeyedStoreGenericAssembler::SetProperty(TNode<Context> context,
BIND(&slow);
{
- CallRuntime(Runtime::kSetProperty, context, receiver, unique_name, value,
- SmiConstant(language_mode));
+ CallRuntime(Runtime::kSetKeyedProperty, context, receiver, unique_name,
+ value, SmiConstant(language_mode));
Goto(&done);
}
BIND(&done);
}
+// Sets data properties as in PropertyDefinitionEvaluation --- Does not invoke
+// own setters or traverse the prototype chain.
+void KeyedStoreGenericAssembler::EmitGenericPropertyStoreInLiteral(
+ TNode<Context> context, TNode<JSObject> receiver, TNode<Map> map,
+ TNode<Name> key, TNode<Object> value, ExitPoint* exit_point) {
+ CSA_ASSERT(this, IsSimpleObjectMap(map));
+
+ // This should only be used for storing data properties in object literals.
+ CSA_ASSERT(this, HasInstanceType(receiver, JS_OBJECT_TYPE));
+
+ Label stub_cache(this), fast_properties(this), dictionary_properties(this),
+ accessor(this), call_runtime(this, Label::kDeferred), done(this);
+ TNode<Uint32T> bit_field3 = LoadMapBitField3(map);
+ Branch(IsSetWord32<Map::IsDictionaryMapBit>(bit_field3),
+ &dictionary_properties, &fast_properties);
+
+ BIND(&fast_properties);
+ {
+ Comment("fast property store");
+ TNode<DescriptorArray> descriptors = LoadMapDescriptors(map);
+ Label descriptor_found(this), lookup_transition(this);
+
+ TVARIABLE(IntPtrT, var_name_index);
+ DescriptorLookup(key, descriptors, bit_field3, &descriptor_found,
+ &var_name_index, &lookup_transition);
+
+ BIND(&descriptor_found);
+ {
+ TNode<IntPtrT> name_index = var_name_index.value();
+ TNode<Uint32T> details = LoadDetailsByKeyIndex(descriptors, name_index);
+ Label data_property(this);
+ JumpIfDataProperty(details, &data_property, nullptr);
+
+ // Reconfigure the accessor to a data property via runtime call.
+ // TODO(caitp): reconfigure the property details inlinr here.
+ Goto(&call_runtime);
+
+ BIND(&data_property);
+ {
+ // TODO(caitp): consider only checking for names associated with
+ // protectors that can apply to non-prototype JSObjects (currently, only
+ // [Symbol.isConcatSpreadable]), and request this behaviour with an
+ // enum parameter.
+ CheckForAssociatedProtector(key, &call_runtime);
+ OverwriteExistingFastDataProperty(receiver, map, descriptors,
+ name_index, details, value,
+ &call_runtime, false);
+ exit_point->Return(value);
+ }
+ }
+
+ BIND(&lookup_transition);
+ {
+ Comment("lookup transition");
+ TNode<Map> transition_map =
+ FindCandidateStoreICTransitionMapHandler(map, key, &call_runtime);
+
+ // Validate the transition handler candidate and apply the transition.
+ StoreICParameters p(context, receiver, key, value, nullptr, nullptr);
+ HandleStoreICTransitionMapHandlerCase(&p, transition_map, &call_runtime,
+ kValidateTransitionHandler);
+ exit_point->Return(value);
+ }
+ }
+
+ BIND(&dictionary_properties);
+ {
+ Comment("dictionary property store");
+ TVARIABLE(IntPtrT, var_name_index);
+ Label dictionary_found(this, &var_name_index), not_found(this);
+ TNode<NameDictionary> properties = CAST(LoadSlowProperties(receiver));
+ NameDictionaryLookup<NameDictionary>(properties, key, &dictionary_found,
+ &var_name_index, &not_found);
+ BIND(&dictionary_found);
+ {
+ Label overwrite(this);
+ TNode<Uint32T> details = LoadDetailsByKeyIndex<NameDictionary>(
+ properties, var_name_index.value());
+ JumpIfDataProperty(details, &overwrite, nullptr);
+
+ // Reconfigure the accessor to a data property via runtime call.
+ Goto(&call_runtime);
+
+ BIND(&overwrite);
+ {
+ // See above TODO regarding non-pertinent checks
+ CheckForAssociatedProtector(key, &call_runtime);
+ StoreValueByKeyIndex<NameDictionary>(properties, var_name_index.value(),
+ value);
+ exit_point->Return(value);
+ }
+ }
+
+ BIND(&not_found);
+ {
+ // See above TODO regarding non-pertinent checks
+ CheckForAssociatedProtector(key, &call_runtime);
+
+ // This method should always be invoked on a new JSObject literal ---
+ // it should be impossible for the object to be made non-extensible, or to
+ // be a prototype map/
+ CSA_ASSERT(this, IsExtensibleNonPrototypeMap(map));
+
+ Label add_dictionary_property_slow(this);
+ Add<NameDictionary>(properties, key, value,
+ &add_dictionary_property_slow);
+ exit_point->Return(value);
+
+ BIND(&add_dictionary_property_slow);
+ exit_point->ReturnCallRuntime(Runtime::kAddDictionaryProperty, context,
+ receiver, key, value);
+ }
+ }
+
+ BIND(&call_runtime);
+ exit_point->ReturnCallRuntime(Runtime::kStoreDataPropertyInLiteral, context,
+ receiver, key, value);
+}
+
} // 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 0934c96cc8..9442a54935 100644
--- a/deps/v8/src/ic/keyed-store-generic.h
+++ b/deps/v8/src/ic/keyed-store-generic.h
@@ -30,6 +30,11 @@ class KeyedStoreGenericGenerator {
TNode<Context> context, TNode<Object> receiver,
TNode<Object> key, TNode<Object> value,
LanguageMode language_mode);
+
+ static void SetPropertyInLiteral(compiler::CodeAssemblerState* state,
+ TNode<Context> context,
+ TNode<JSObject> receiver, TNode<Name> key,
+ TNode<Object> value);
};
class StoreICUninitializedGenerator {