aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/ic/keyed-store-generic.cc
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2017-05-02 10:50:00 +0200
committerMichaël Zasso <targos@protonmail.com>2017-05-06 20:02:35 +0200
commit60d1aac8d225e844e68ae48e8f3d58802e635fbe (patch)
tree922f347dd054db18d88666fad7181e5a777f4022 /deps/v8/src/ic/keyed-store-generic.cc
parent73d9c0f903ae371cd5011af64c3a6f69a1bda978 (diff)
downloadandroid-node-v8-60d1aac8d225e844e68ae48e8f3d58802e635fbe.tar.gz
android-node-v8-60d1aac8d225e844e68ae48e8f3d58802e635fbe.tar.bz2
android-node-v8-60d1aac8d225e844e68ae48e8f3d58802e635fbe.zip
deps: update V8 to 5.8.283.38
PR-URL: https://github.com/nodejs/node/pull/12784 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>
Diffstat (limited to 'deps/v8/src/ic/keyed-store-generic.cc')
-rw-r--r--deps/v8/src/ic/keyed-store-generic.cc255
1 files changed, 208 insertions, 47 deletions
diff --git a/deps/v8/src/ic/keyed-store-generic.cc b/deps/v8/src/ic/keyed-store-generic.cc
index 81ce3a6a1f..8962386c93 100644
--- a/deps/v8/src/ic/keyed-store-generic.cc
+++ b/deps/v8/src/ic/keyed-store-generic.cc
@@ -7,19 +7,20 @@
#include "src/code-factory.h"
#include "src/code-stub-assembler.h"
#include "src/contexts.h"
-#include "src/ic/accessor-assembler-impl.h"
+#include "src/ic/accessor-assembler.h"
#include "src/interface-descriptors.h"
#include "src/isolate.h"
+#include "src/objects-inl.h"
namespace v8 {
namespace internal {
using compiler::Node;
-class KeyedStoreGenericAssembler : public AccessorAssemblerImpl {
+class KeyedStoreGenericAssembler : public AccessorAssembler {
public:
explicit KeyedStoreGenericAssembler(compiler::CodeAssemblerState* state)
- : AccessorAssemblerImpl(state) {}
+ : AccessorAssembler(state) {}
void KeyedStoreGeneric(LanguageMode language_mode);
@@ -72,6 +73,13 @@ class KeyedStoreGenericAssembler : public AccessorAssemblerImpl {
Variable* var_accessor_pair,
Variable* var_accessor_holder,
Label* readonly, Label* bailout);
+
+ void CheckFieldType(Node* descriptors, Node* name_index, Node* representation,
+ Node* value, Label* bailout);
+ void OverwriteExistingFastProperty(Node* object, Node* object_map,
+ Node* properties, Node* descriptors,
+ Node* descriptor_name_index, Node* details,
+ Node* value, Label* slow);
};
void KeyedStoreGenericGenerator::Generate(compiler::CodeAssemblerState* state,
@@ -266,7 +274,7 @@ void KeyedStoreGenericAssembler::StoreElementWithCapacity(
// can always be stored.
{
Label non_smi_value(this);
- GotoUnless(TaggedIsSmi(value), &non_smi_value);
+ GotoIfNot(TaggedIsSmi(value), &non_smi_value);
// If we're about to introduce holes, ensure holey elements.
if (update_length == kBumpLengthWithGap) {
TryChangeToHoleyMapMulti(receiver, receiver_map, elements_kind, context,
@@ -461,6 +469,8 @@ void KeyedStoreGenericAssembler::EmitGenericElementStore(
// Out-of-capacity accesses (index >= capacity) jump here. Additionally,
// an ElementsKind transition might be necessary.
+ // The index can also be negative at this point! Jump to the runtime in that
+ // case to convert it to a named property.
Bind(&if_grow);
{
Comment("Grow backing store");
@@ -537,16 +547,12 @@ void KeyedStoreGenericAssembler::LookupPropertyOnPrototypeChain(
{
Node* descriptors = var_meta_storage.value();
Node* name_index = var_entry.value();
- // TODO(jkummerow): Add helper functions for accessing value and
- // details by entry.
- const int kNameToDetailsOffset = (DescriptorArray::kDescriptorDetails -
- DescriptorArray::kDescriptorKey) *
- kPointerSize;
- Node* details = LoadAndUntagToWord32FixedArrayElement(
- descriptors, name_index, kNameToDetailsOffset);
+ Node* details =
+ LoadDetailsByKeyIndex<DescriptorArray>(descriptors, name_index);
JumpIfDataProperty(details, &ok_to_write, readonly);
// Accessor case.
+ // TODO(jkummerow): Implement a trimmed-down LoadAccessorFromFastObject.
Variable var_details(this, MachineRepresentation::kWord32);
LoadPropertyFromFastObject(holder, holder_map, descriptors, name_index,
&var_details, var_accessor_pair);
@@ -558,19 +564,13 @@ void KeyedStoreGenericAssembler::LookupPropertyOnPrototypeChain(
{
Node* dictionary = var_meta_storage.value();
Node* entry = var_entry.value();
- const int kNameToDetailsOffset = (NameDictionary::kEntryDetailsIndex -
- NameDictionary::kEntryKeyIndex) *
- kPointerSize;
- Node* details = LoadAndUntagToWord32FixedArrayElement(
- dictionary, entry, kNameToDetailsOffset);
+ Node* details =
+ LoadDetailsByKeyIndex<NameDictionary>(dictionary, entry);
JumpIfDataProperty(details, &ok_to_write, readonly);
// Accessor case.
- const int kNameToValueOffset = (NameDictionary::kEntryValueIndex -
- NameDictionary::kEntryKeyIndex) *
- kPointerSize;
var_accessor_pair->Bind(
- LoadFixedArrayElement(dictionary, entry, kNameToValueOffset));
+ LoadValueByKeyIndex<NameDictionary>(dictionary, entry));
var_accessor_holder->Bind(holder);
Goto(accessor);
}
@@ -579,13 +579,8 @@ void KeyedStoreGenericAssembler::LookupPropertyOnPrototypeChain(
{
Node* dictionary = var_meta_storage.value();
Node* entry = var_entry.value();
- const int kNameToValueOffset = (GlobalDictionary::kEntryValueIndex -
- GlobalDictionary::kEntryKeyIndex) *
- kPointerSize;
-
Node* property_cell =
- LoadFixedArrayElement(dictionary, entry, kNameToValueOffset);
-
+ LoadValueByKeyIndex<GlobalDictionary>(dictionary, entry);
Node* value =
LoadObjectField(property_cell, PropertyCell::kValueOffset);
GotoIf(WordEqual(value, TheHoleConstant()), &next_proto);
@@ -613,6 +608,146 @@ void KeyedStoreGenericAssembler::LookupPropertyOnPrototypeChain(
Bind(&ok_to_write);
}
+void KeyedStoreGenericAssembler::CheckFieldType(Node* descriptors,
+ Node* name_index,
+ Node* representation,
+ Node* value, Label* bailout) {
+ Label r_smi(this), r_double(this), r_heapobject(this), all_fine(this);
+ // Ignore FLAG_track_fields etc. and always emit code for all checks,
+ // because this builtin is part of the snapshot and therefore should
+ // be flag independent.
+ GotoIf(Word32Equal(representation, Int32Constant(Representation::kSmi)),
+ &r_smi);
+ GotoIf(Word32Equal(representation, Int32Constant(Representation::kDouble)),
+ &r_double);
+ GotoIf(
+ Word32Equal(representation, Int32Constant(Representation::kHeapObject)),
+ &r_heapobject);
+ GotoIf(Word32Equal(representation, Int32Constant(Representation::kNone)),
+ bailout);
+ CSA_ASSERT(this, Word32Equal(representation,
+ Int32Constant(Representation::kTagged)));
+ Goto(&all_fine);
+
+ Bind(&r_smi);
+ { Branch(TaggedIsSmi(value), &all_fine, bailout); }
+
+ Bind(&r_double);
+ {
+ GotoIf(TaggedIsSmi(value), &all_fine);
+ 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)));
+ Branch(IsHeapNumberMap(value_map), &all_fine, bailout);
+ }
+
+ Bind(&r_heapobject);
+ {
+ GotoIf(TaggedIsSmi(value), bailout);
+ Node* field_type =
+ LoadValueByKeyIndex<DescriptorArray>(descriptors, name_index);
+ intptr_t kNoneType = reinterpret_cast<intptr_t>(FieldType::None());
+ intptr_t kAnyType = reinterpret_cast<intptr_t>(FieldType::Any());
+ // FieldType::None can't hold any value.
+ GotoIf(WordEqual(field_type, IntPtrConstant(kNoneType)), bailout);
+ // FieldType::Any can hold any value.
+ GotoIf(WordEqual(field_type, IntPtrConstant(kAnyType)), &all_fine);
+ CSA_ASSERT(this, IsWeakCell(field_type));
+ // Cleared WeakCells count as FieldType::None, which can't hold any value.
+ field_type = LoadWeakCellValue(field_type, bailout);
+ // FieldType::Class(...) performs a map check.
+ CSA_ASSERT(this, IsMap(field_type));
+ Branch(WordEqual(LoadMap(value), field_type), &all_fine, bailout);
+ }
+
+ Bind(&all_fine);
+}
+
+void KeyedStoreGenericAssembler::OverwriteExistingFastProperty(
+ Node* object, Node* object_map, Node* properties, Node* descriptors,
+ Node* descriptor_name_index, Node* details, Node* value, Label* slow) {
+ // Properties in descriptors can't be overwritten without map transition.
+ GotoIf(Word32NotEqual(DecodeWord32<PropertyDetails::LocationField>(details),
+ Int32Constant(kField)),
+ slow);
+
+ if (FLAG_track_constant_fields) {
+ // TODO(ishell): Taking the slow path is not necessary if new and old
+ // values are identical.
+ GotoIf(Word32Equal(DecodeWord32<PropertyDetails::ConstnessField>(details),
+ Int32Constant(kConst)),
+ slow);
+ }
+
+ Label done(this);
+ Node* representation =
+ DecodeWord32<PropertyDetails::RepresentationField>(details);
+
+ CheckFieldType(descriptors, descriptor_name_index, representation, value,
+ slow);
+ Node* field_index =
+ DecodeWordFromWord32<PropertyDetails::FieldIndexField>(details);
+ Node* inobject_properties = LoadMapInobjectProperties(object_map);
+
+ Label inobject(this), backing_store(this);
+ Branch(UintPtrLessThan(field_index, inobject_properties), &inobject,
+ &backing_store);
+
+ Bind(&inobject);
+ {
+ Node* field_offset =
+ IntPtrMul(IntPtrSub(LoadMapInstanceSize(object_map),
+ IntPtrSub(inobject_properties, field_index)),
+ IntPtrConstant(kPointerSize));
+ Label tagged_rep(this), double_rep(this);
+ Branch(Word32Equal(representation, Int32Constant(Representation::kDouble)),
+ &double_rep, &tagged_rep);
+ Bind(&double_rep);
+ {
+ Node* double_value = ChangeNumberToFloat64(value);
+ if (FLAG_unbox_double_fields) {
+ StoreObjectFieldNoWriteBarrier(object, field_offset, double_value,
+ MachineRepresentation::kFloat64);
+ } else {
+ Node* mutable_heap_number = LoadObjectField(object, field_offset);
+ StoreHeapNumberValue(mutable_heap_number, double_value);
+ }
+ Goto(&done);
+ }
+
+ Bind(&tagged_rep);
+ {
+ StoreObjectField(object, field_offset, value);
+ Goto(&done);
+ }
+ }
+
+ Bind(&backing_store);
+ {
+ Node* backing_store_index = IntPtrSub(field_index, inobject_properties);
+ Label tagged_rep(this), double_rep(this);
+ Branch(Word32Equal(representation, Int32Constant(Representation::kDouble)),
+ &double_rep, &tagged_rep);
+ Bind(&double_rep);
+ {
+ Node* double_value = ChangeNumberToFloat64(value);
+ Node* mutable_heap_number =
+ LoadFixedArrayElement(properties, backing_store_index);
+ StoreHeapNumberValue(mutable_heap_number, double_value);
+ Goto(&done);
+ }
+ Bind(&tagged_rep);
+ {
+ StoreFixedArrayElement(properties, backing_store_index, value);
+ Goto(&done);
+ }
+ }
+ Bind(&done);
+}
+
void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
Node* receiver, Node* receiver_map, const StoreICParameters* p, Label* slow,
LanguageMode language_mode) {
@@ -627,10 +762,40 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
Bind(&fast_properties);
{
- // TODO(jkummerow): Does it make sense to support some cases here inline?
- // Maybe overwrite existing writable properties?
- // Maybe support map transitions?
- Goto(&stub_cache);
+ Comment("fast property store");
+ Node* bitfield3 = LoadMapBitField3(receiver_map);
+ Node* descriptors = LoadMapDescriptors(receiver_map);
+ Label descriptor_found(this);
+ Variable var_name_index(this, MachineType::PointerRepresentation());
+ // TODO(jkummerow): Maybe look for existing map transitions?
+ Label* notfound = &stub_cache;
+ DescriptorLookup(p->name, descriptors, bitfield3, &descriptor_found,
+ &var_name_index, notfound);
+
+ Bind(&descriptor_found);
+ {
+ Node* name_index = var_name_index.value();
+ Node* details =
+ LoadDetailsByKeyIndex<DescriptorArray>(descriptors, name_index);
+ Label data_property(this);
+ JumpIfDataProperty(details, &data_property, &readonly);
+
+ // Accessor case.
+ // TODO(jkummerow): Implement a trimmed-down LoadAccessorFromFastObject.
+ Variable var_details(this, MachineRepresentation::kWord32);
+ LoadPropertyFromFastObject(receiver, receiver_map, descriptors,
+ name_index, &var_details, &var_accessor_pair);
+ var_accessor_holder.Bind(receiver);
+ Goto(&accessor);
+
+ Bind(&data_property);
+ {
+ OverwriteExistingFastProperty(receiver, receiver_map, properties,
+ descriptors, name_index, details,
+ p->value, slow);
+ Return(p->value);
+ }
+ }
}
Bind(&dictionary_properties);
@@ -646,26 +811,20 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
Bind(&dictionary_found);
{
Label overwrite(this);
- const int kNameToDetailsOffset = (NameDictionary::kEntryDetailsIndex -
- NameDictionary::kEntryKeyIndex) *
- kPointerSize;
- Node* details = LoadAndUntagToWord32FixedArrayElement(
- properties, var_name_index.value(), kNameToDetailsOffset);
+ Node* details = LoadDetailsByKeyIndex<NameDictionary>(
+ properties, var_name_index.value());
JumpIfDataProperty(details, &overwrite, &readonly);
// Accessor case.
- const int kNameToValueOffset =
- (NameDictionary::kEntryValueIndex - NameDictionary::kEntryKeyIndex) *
- kPointerSize;
- var_accessor_pair.Bind(LoadFixedArrayElement(
- properties, var_name_index.value(), kNameToValueOffset));
+ var_accessor_pair.Bind(LoadValueByKeyIndex<NameDictionary>(
+ properties, var_name_index.value()));
var_accessor_holder.Bind(receiver);
Goto(&accessor);
Bind(&overwrite);
{
- StoreFixedArrayElement(properties, var_name_index.value(), p->value,
- UPDATE_WRITE_BARRIER, kNameToValueOffset);
+ StoreValueByKeyIndex<NameDictionary>(properties, var_name_index.value(),
+ p->value);
Return(p->value);
}
}
@@ -690,7 +849,7 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
Node* setter_map = LoadMap(setter);
// FunctionTemplateInfo setters are not supported yet.
GotoIf(IsFunctionTemplateInfoMap(setter_map), slow);
- GotoUnless(IsCallableMap(setter_map), &not_callable);
+ GotoIfNot(IsCallableMap(setter_map), &not_callable);
Callable callable = CodeFactory::Call(isolate());
CallJS(callable, p->context, setter, receiver, p->value);
@@ -734,7 +893,7 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
Bind(&found_handler);
{
Comment("KeyedStoreGeneric found handler");
- HandleStoreICHandlerCase(p, var_handler.value(), slow);
+ HandleStoreICHandlerCase(p, var_handler.value(), &stub_cache_miss);
}
Bind(&stub_cache_miss);
{
@@ -756,6 +915,8 @@ void KeyedStoreGenericAssembler::KeyedStoreGeneric(LanguageMode language_mode) {
Node* context = Parameter(Descriptor::kContext);
Variable var_index(this, MachineType::PointerRepresentation());
+ Variable var_unique(this, MachineRepresentation::kTagged);
+ var_unique.Bind(name); // Dummy initialization.
Label if_index(this), if_unique_name(this), slow(this);
GotoIf(TaggedIsSmi(receiver), &slow);
@@ -767,7 +928,7 @@ void KeyedStoreGenericAssembler::KeyedStoreGeneric(LanguageMode language_mode) {
Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)),
&slow);
- TryToName(name, &if_index, &var_index, &if_unique_name, &slow);
+ TryToName(name, &if_index, &var_index, &if_unique_name, &var_unique, &slow);
Bind(&if_index);
{
@@ -779,8 +940,8 @@ void KeyedStoreGenericAssembler::KeyedStoreGeneric(LanguageMode language_mode) {
Bind(&if_unique_name);
{
Comment("key is unique name");
- KeyedStoreGenericAssembler::StoreICParameters p(context, receiver, name,
- value, slot, vector);
+ StoreICParameters p(context, receiver, var_unique.value(), value, slot,
+ vector);
EmitGenericPropertyStore(receiver, receiver_map, &p, &slow, language_mode);
}