[ic] Support store-normal IC with prototype check
BUG= Change-Id: I56b865a5ae4283876058e2c2edf73a296608fc97 Reviewed-on: https://chromium-review.googlesource.com/448219 Reviewed-by: Igor Sheludko <ishell@chromium.org> Commit-Queue: Toon Verwaest <verwaest@chromium.org> Cr-Commit-Position: refs/heads/master@{#43517}
This commit is contained in:
parent
6cff2ddf7d
commit
e4f1862b52
@ -631,7 +631,8 @@ void AccessorAssembler::HandleStoreICProtoHandler(const StoreICParameters* p,
|
||||
Branch(TaggedIsSmi(maybe_transition_cell), &array_handler, &tuple_handler);
|
||||
|
||||
Variable var_transition(this, MachineRepresentation::kTagged);
|
||||
Label if_transition(this), if_transition_to_constant(this);
|
||||
Label if_transition(this), if_transition_to_constant(this),
|
||||
if_store_normal(this);
|
||||
Bind(&tuple_handler);
|
||||
{
|
||||
Node* transition = LoadWeakCellValue(maybe_transition_cell, miss);
|
||||
@ -666,6 +667,8 @@ void AccessorAssembler::HandleStoreICProtoHandler(const StoreICParameters* p,
|
||||
GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(transition)), miss);
|
||||
|
||||
Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
|
||||
GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kStoreNormal)),
|
||||
&if_store_normal);
|
||||
GotoIf(WordEqual(handler_kind,
|
||||
IntPtrConstant(StoreHandler::kTransitionToConstant)),
|
||||
&if_transition_to_constant);
|
||||
@ -696,6 +699,42 @@ void AccessorAssembler::HandleStoreICProtoHandler(const StoreICParameters* p,
|
||||
StoreMap(p->receiver, transition);
|
||||
Return(p->value);
|
||||
}
|
||||
|
||||
Bind(&if_store_normal);
|
||||
{
|
||||
Node* properties = LoadProperties(p->receiver);
|
||||
|
||||
Variable var_name_index(this, MachineType::PointerRepresentation());
|
||||
Label found(this, &var_name_index), not_found(this);
|
||||
NameDictionaryLookup<NameDictionary>(properties, p->name, &found,
|
||||
&var_name_index, ¬_found);
|
||||
Bind(&found);
|
||||
{
|
||||
Node* details = LoadDetailsByKeyIndex<NameDictionary>(
|
||||
properties, var_name_index.value());
|
||||
// Check that the property is a writable data property (no accessor).
|
||||
const int kTypeAndReadOnlyMask =
|
||||
PropertyDetails::KindField::kMask |
|
||||
PropertyDetails::kAttributesReadOnlyMask;
|
||||
STATIC_ASSERT(kData == 0);
|
||||
GotoIf(IsSetWord32(details, kTypeAndReadOnlyMask), miss);
|
||||
|
||||
StoreValueByKeyIndex<NameDictionary>(properties, var_name_index.value(),
|
||||
p->value);
|
||||
Return(p->value);
|
||||
}
|
||||
|
||||
Bind(¬_found);
|
||||
{
|
||||
Label slow(this);
|
||||
Add<NameDictionary>(properties, p->name, p->value, &slow);
|
||||
Return(p->value);
|
||||
|
||||
Bind(&slow);
|
||||
TailCallRuntime(Runtime::kKeyedStoreIC_Slow, p->context, p->value,
|
||||
p->slot, p->vector, p->receiver, p->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
44
src/ic/ic.cc
44
src/ic/ic.cc
@ -1818,28 +1818,33 @@ Handle<Object> StoreIC::StoreTransition(Handle<Map> receiver_map,
|
||||
Handle<JSObject> holder,
|
||||
Handle<Map> transition,
|
||||
Handle<Name> name) {
|
||||
int descriptor = transition->LastAdded();
|
||||
Handle<DescriptorArray> descriptors(transition->instance_descriptors());
|
||||
PropertyDetails details = descriptors->GetDetails(descriptor);
|
||||
Representation representation = details.representation();
|
||||
DCHECK(!representation.IsNone());
|
||||
|
||||
// Declarative handlers don't support access checks.
|
||||
DCHECK(!transition->is_access_check_needed());
|
||||
|
||||
Handle<Object> smi_handler;
|
||||
DCHECK_EQ(kData, details.kind());
|
||||
if (details.location() == kDescriptor) {
|
||||
smi_handler = StoreHandler::TransitionToConstant(isolate(), descriptor);
|
||||
|
||||
if (transition->is_dictionary_map()) {
|
||||
smi_handler = StoreHandler::StoreNormal(isolate());
|
||||
} else {
|
||||
DCHECK_EQ(kField, details.location());
|
||||
bool extend_storage =
|
||||
Map::cast(transition->GetBackPointer())->unused_property_fields() == 0;
|
||||
int descriptor = transition->LastAdded();
|
||||
Handle<DescriptorArray> descriptors(transition->instance_descriptors());
|
||||
PropertyDetails details = descriptors->GetDetails(descriptor);
|
||||
Representation representation = details.representation();
|
||||
DCHECK(!representation.IsNone());
|
||||
|
||||
FieldIndex index = FieldIndex::ForDescriptor(*transition, descriptor);
|
||||
smi_handler = StoreHandler::TransitionToField(
|
||||
isolate(), descriptor, index, representation, extend_storage);
|
||||
// Declarative handlers don't support access checks.
|
||||
DCHECK(!transition->is_access_check_needed());
|
||||
|
||||
DCHECK_EQ(kData, details.kind());
|
||||
if (details.location() == kDescriptor) {
|
||||
smi_handler = StoreHandler::TransitionToConstant(isolate(), descriptor);
|
||||
|
||||
} else {
|
||||
DCHECK_EQ(kField, details.location());
|
||||
bool extend_storage =
|
||||
Map::cast(transition->GetBackPointer())->unused_property_fields() ==
|
||||
0;
|
||||
|
||||
FieldIndex index = FieldIndex::ForDescriptor(*transition, descriptor);
|
||||
smi_handler = StoreHandler::TransitionToField(
|
||||
isolate(), descriptor, index, representation, extend_storage);
|
||||
}
|
||||
}
|
||||
// |holder| is either a receiver if the property is non-existent or
|
||||
// one of the prototypes.
|
||||
@ -1910,6 +1915,7 @@ Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
|
||||
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
|
||||
return slow_stub();
|
||||
}
|
||||
|
||||
DCHECK(lookup->IsCacheableTransition());
|
||||
Handle<Map> transition = lookup->transition_map();
|
||||
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreTransitionDH);
|
||||
|
@ -211,8 +211,9 @@ class V8_EXPORT_PRIVATE LookupIterator final BASE_EMBEDDED {
|
||||
bool IsCacheableTransition() {
|
||||
DCHECK_EQ(TRANSITION, state_);
|
||||
return transition_->IsPropertyCell() ||
|
||||
(!transition_map()->is_dictionary_map() &&
|
||||
transition_map()->GetBackPointer()->IsMap());
|
||||
(transition_map()->is_dictionary_map() &&
|
||||
!GetStoreTarget()->HasFastProperties()) ||
|
||||
transition_map()->GetBackPointer()->IsMap();
|
||||
}
|
||||
void ApplyTransitionToDataProperty(Handle<JSObject> receiver);
|
||||
void ReconfigureDataProperty(Handle<Object> value,
|
||||
|
Loading…
Reference in New Issue
Block a user