| Index: src/ic/accessor-assembler.cc
|
| diff --git a/src/ic/accessor-assembler.cc b/src/ic/accessor-assembler.cc
|
| index 6a27045f1228311a235692e01b87386898a36c09..22ecec2bb1462880d49c473d098a8c2b08f4e417 100644
|
| --- a/src/ic/accessor-assembler.cc
|
| +++ b/src/ic/accessor-assembler.cc
|
| @@ -670,25 +670,9 @@ void AccessorAssemblerImpl::HandleStoreICSmiHandlerCase(Node* handler_word,
|
| Bind(&if_heap_object_field);
|
| {
|
| Comment("store heap object field");
|
| - // Generate full field type check here and then store value as Tagged.
|
| - Node* prepared_value =
|
| - PrepareValueForWrite(value, Representation::HeapObject(), miss);
|
| - Node* value_index_in_descriptor =
|
| - DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word);
|
| - Node* descriptors =
|
| - LoadMapDescriptors(transition ? transition : LoadMap(holder));
|
| - Node* maybe_field_type =
|
| - LoadFixedArrayElement(descriptors, value_index_in_descriptor);
|
| - Label do_store(this);
|
| - GotoIf(TaggedIsSmi(maybe_field_type), &do_store);
|
| - // Check that value type matches the field type.
|
| - {
|
| - Node* field_type = LoadWeakCellValue(maybe_field_type, miss);
|
| - Branch(WordEqual(LoadMap(prepared_value), field_type), &do_store, miss);
|
| - }
|
| - Bind(&do_store);
|
| - HandleStoreFieldAndReturn(handler_word, holder, Representation::Tagged(),
|
| - prepared_value, transition, miss);
|
| + HandleStoreFieldAndReturn(handler_word, holder,
|
| + Representation::HeapObject(), value, transition,
|
| + miss);
|
| }
|
|
|
| Bind(&if_smi_field);
|
| @@ -703,19 +687,8 @@ void AccessorAssemblerImpl::HandleStoreFieldAndReturn(
|
| Node* handler_word, Node* holder, Representation representation,
|
| Node* value, Node* transition, Label* miss) {
|
| bool transition_to_field = transition != nullptr;
|
| - Node* prepared_value = PrepareValueForWrite(value, representation, miss);
|
| -
|
| - if (transition_to_field) {
|
| - Label storage_extended(this);
|
| - GotoUnless(IsSetWord<StoreHandler::ExtendStorageBits>(handler_word),
|
| - &storage_extended);
|
| - Comment("[ Extend storage");
|
| - ExtendPropertiesBackingStore(holder);
|
| - Comment("] Extend storage");
|
| - Goto(&storage_extended);
|
| -
|
| - Bind(&storage_extended);
|
| - }
|
| + Node* prepared_value = PrepareValueForStore(
|
| + handler_word, holder, representation, transition, value, miss);
|
|
|
| Node* offset = DecodeWord<StoreHandler::FieldOffsetBits>(handler_word);
|
| Label if_inobject(this), if_out_of_object(this);
|
| @@ -734,6 +707,18 @@ void AccessorAssemblerImpl::HandleStoreFieldAndReturn(
|
|
|
| Bind(&if_out_of_object);
|
| {
|
| + if (transition_to_field) {
|
| + Label storage_extended(this);
|
| + GotoUnless(IsSetWord<StoreHandler::ExtendStorageBits>(handler_word),
|
| + &storage_extended);
|
| + Comment("[ Extend storage");
|
| + ExtendPropertiesBackingStore(holder);
|
| + Comment("] Extend storage");
|
| + Goto(&storage_extended);
|
| +
|
| + Bind(&storage_extended);
|
| + }
|
| +
|
| StoreNamedField(holder, offset, false, representation, prepared_value,
|
| transition_to_field);
|
| if (transition_to_field) {
|
| @@ -743,6 +728,114 @@ void AccessorAssemblerImpl::HandleStoreFieldAndReturn(
|
| }
|
| }
|
|
|
| +Node* AccessorAssemblerImpl::PrepareValueForStore(Node* handler_word,
|
| + Node* holder,
|
| + Representation representation,
|
| + Node* transition, Node* value,
|
| + Label* bailout) {
|
| + if (representation.IsDouble()) {
|
| + value = TryTaggedToFloat64(value, bailout);
|
| +
|
| + } else if (representation.IsHeapObject()) {
|
| + GotoIf(TaggedIsSmi(value), bailout);
|
| + Node* value_index_in_descriptor =
|
| + DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word);
|
| + Node* descriptors =
|
| + LoadMapDescriptors(transition ? transition : LoadMap(holder));
|
| + Node* maybe_field_type =
|
| + LoadFixedArrayElement(descriptors, value_index_in_descriptor);
|
| +
|
| + Label done(this);
|
| + GotoIf(TaggedIsSmi(maybe_field_type), &done);
|
| + // Check that value type matches the field type.
|
| + {
|
| + Node* field_type = LoadWeakCellValue(maybe_field_type, bailout);
|
| + Branch(WordEqual(LoadMap(value), field_type), &done, bailout);
|
| + }
|
| + Bind(&done);
|
| +
|
| + } else if (representation.IsSmi()) {
|
| + GotoUnless(TaggedIsSmi(value), bailout);
|
| +
|
| + } else {
|
| + DCHECK(representation.IsTagged());
|
| + }
|
| + return value;
|
| +}
|
| +
|
| +void AccessorAssemblerImpl::ExtendPropertiesBackingStore(Node* object) {
|
| + Node* properties = LoadProperties(object);
|
| + Node* length = LoadFixedArrayBaseLength(properties);
|
| +
|
| + ParameterMode mode = OptimalParameterMode();
|
| + length = TaggedToParameter(length, mode);
|
| +
|
| + Node* delta = IntPtrOrSmiConstant(JSObject::kFieldsAdded, mode);
|
| + Node* new_capacity = IntPtrOrSmiAdd(length, delta, mode);
|
| +
|
| + // Grow properties array.
|
| + ElementsKind kind = FAST_ELEMENTS;
|
| + DCHECK(kMaxNumberOfDescriptors + JSObject::kFieldsAdded <
|
| + FixedArrayBase::GetMaxLengthForNewSpaceAllocation(kind));
|
| + // The size of a new properties backing store is guaranteed to be small
|
| + // enough that the new backing store will be allocated in new space.
|
| + CSA_ASSERT(this,
|
| + UintPtrOrSmiLessThan(
|
| + new_capacity,
|
| + IntPtrOrSmiConstant(
|
| + kMaxNumberOfDescriptors + JSObject::kFieldsAdded, mode),
|
| + mode));
|
| +
|
| + Node* new_properties = AllocateFixedArray(kind, new_capacity, mode);
|
| +
|
| + FillFixedArrayWithValue(kind, new_properties, length, new_capacity,
|
| + Heap::kUndefinedValueRootIndex, mode);
|
| +
|
| + // |new_properties| is guaranteed to be in new space, so we can skip
|
| + // the write barrier.
|
| + CopyFixedArrayElements(kind, properties, new_properties, length,
|
| + SKIP_WRITE_BARRIER, mode);
|
| +
|
| + StoreObjectField(object, JSObject::kPropertiesOffset, new_properties);
|
| +}
|
| +
|
| +void AccessorAssemblerImpl::StoreNamedField(Node* object, Node* offset,
|
| + bool is_inobject,
|
| + Representation representation,
|
| + Node* value,
|
| + bool transition_to_field) {
|
| + bool store_value_as_double = representation.IsDouble();
|
| + Node* property_storage = object;
|
| + if (!is_inobject) {
|
| + property_storage = LoadProperties(object);
|
| + }
|
| +
|
| + if (representation.IsDouble()) {
|
| + if (!FLAG_unbox_double_fields || !is_inobject) {
|
| + if (transition_to_field) {
|
| + Node* heap_number = AllocateHeapNumberWithValue(value, MUTABLE);
|
| + // Store the new mutable heap number into the object.
|
| + value = heap_number;
|
| + store_value_as_double = false;
|
| + } else {
|
| + // Load the heap number.
|
| + property_storage = LoadObjectField(property_storage, offset);
|
| + // Store the double value into it.
|
| + offset = IntPtrConstant(HeapNumber::kValueOffset);
|
| + }
|
| + }
|
| + }
|
| +
|
| + if (store_value_as_double) {
|
| + StoreObjectFieldNoWriteBarrier(property_storage, offset, value,
|
| + MachineRepresentation::kFloat64);
|
| + } else if (representation.IsSmi()) {
|
| + StoreObjectFieldNoWriteBarrier(property_storage, offset, value);
|
| + } else {
|
| + StoreObjectField(property_storage, offset, value);
|
| + }
|
| +}
|
| +
|
| void AccessorAssemblerImpl::EmitFastElementsBoundsCheck(
|
| Node* object, Node* elements, Node* intptr_index,
|
| Node* is_jsarray_condition, Label* miss) {
|
|
|