Commit de242272 authored by ishell's avatar ishell Committed by Commit bot

[ic][stubs] Move more IC-related methods from CSA to AccessorAssembler.

... and reshuffle it a bit.

BUG=v8:5495

Review-Url: https://codereview.chromium.org/2619823005
Cr-Commit-Position: refs/heads/master@{#42185}
parent 8e9c90ba
......@@ -5507,104 +5507,6 @@ Node* CodeStubAssembler::TryToIntptr(Node* key, Label* miss) {
return var_intptr_key.value();
}
void CodeStubAssembler::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);
}
Node* CodeStubAssembler::PrepareValueForWrite(Node* value,
Representation representation,
Label* bailout) {
if (representation.IsDouble()) {
value = TryTaggedToFloat64(value, bailout);
} else if (representation.IsHeapObject()) {
// Field type is checked by the handler, here we only check if the value
// is a heap object.
GotoIf(TaggedIsSmi(value), bailout);
} else if (representation.IsSmi()) {
GotoUnless(TaggedIsSmi(value), bailout);
} else {
DCHECK(representation.IsTagged());
}
return value;
}
void CodeStubAssembler::StoreNamedField(Node* object, FieldIndex index,
Representation representation,
Node* value, bool transition_to_field) {
DCHECK_EQ(index.is_double(), representation.IsDouble());
StoreNamedField(object, IntPtrConstant(index.offset()), index.is_inobject(),
representation, value, transition_to_field);
}
void CodeStubAssembler::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);
}
}
Node* CodeStubAssembler::EmitKeyedSloppyArguments(Node* receiver, Node* key,
Node* value, Label* bailout) {
// Mapped arguments are actual arguments. Unmapped arguments are values added
......
......@@ -975,20 +975,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* LoadReceiverMap(Node* receiver);
// Extends properties backing store by JSObject::kFieldsAdded elements.
void ExtendPropertiesBackingStore(Node* object);
Node* PrepareValueForWrite(Node* value, Representation representation,
Label* bailout);
void StoreNamedField(Node* object, FieldIndex index,
Representation representation, Node* value,
bool transition_to_field);
void StoreNamedField(Node* object, Node* offset, bool is_inobject,
Representation representation, Node* value,
bool transition_to_field);
// Emits keyed sloppy arguments load. Returns either the loaded value.
Node* LoadKeyedSloppyArguments(Node* receiver, Node* key, Label* bailout) {
return EmitKeyedSloppyArguments(receiver, key, nullptr, bailout);
......
......@@ -160,6 +160,17 @@ class AccessorAssemblerImpl : public CodeStubAssembler {
// Low-level helpers.
Node* PrepareValueForStore(Node* handler_word, Node* holder,
Representation representation, Node* transition,
Node* value, Label* bailout);
// Extends properties backing store by JSObject::kFieldsAdded elements.
void ExtendPropertiesBackingStore(Node* object);
void StoreNamedField(Node* object, Node* offset, bool is_inobject,
Representation representation, Node* value,
bool transition_to_field);
void EmitFastElementsBoundsCheck(Node* object, Node* elements,
Node* intptr_index,
Node* is_jsarray_condition, Label* miss);
......
......@@ -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) {
......
......@@ -104,7 +104,8 @@ Handle<Object> StoreHandler::StoreField(Isolate* isolate, Kind kind,
int value_index = DescriptorArray::ToValueIndex(descriptor);
DCHECK(kind == kStoreField || kind == kTransitionToField);
DCHECK_IMPLIES(kind == kStoreField, !extend_storage);
DCHECK_IMPLIES(extend_storage, kind == kTransitionToField);
DCHECK_IMPLIES(field_index.is_inobject(), !extend_storage);
int config = StoreHandler::KindBits::encode(kind) |
StoreHandler::ExtendStorageBits::encode(extend_storage) |
......
......@@ -362,8 +362,8 @@ void KeyedStoreGenericAssembler::StoreElementWithCapacity(
// Try to store the value as a double.
{
Label non_number_value(this);
Node* double_value = PrepareValueForWrite(value, Representation::Double(),
&non_number_value);
Node* double_value = TryTaggedToFloat64(value, &non_number_value);
// Make sure we do not store signalling NaNs into double arrays.
double_value = Float64SilenceNaN(double_value);
// If we're about to introduce holes, ensure holey elements.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment