[ic] Introduce canonical invalid prototype validity cell.
... and use Smi Map::kPrototypeChainValid for the cases where direct receiver's prototype is not JSObject instead of creating a new valid cell for each such case. This will make a validity cell checking code simpler. Bug: v8:5988 Change-Id: I52cf55797171cc8021d80e4e441615d0c8fc8bd4 Reviewed-on: https://chromium-review.googlesource.com/951384 Commit-Queue: Igor Sheludko <ishell@chromium.org> Reviewed-by: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Cr-Commit-Position: refs/heads/master@{#51803}
This commit is contained in:
parent
501f250c0b
commit
aeee606360
@ -2493,6 +2493,7 @@ AllocationResult Heap::AllocatePartialMap(InstanceType instance_type,
|
||||
map->set_visitor_id(Map::GetVisitorId(map));
|
||||
map->set_inobject_properties_start_or_constructor_function_index(0);
|
||||
DCHECK(!map->IsJSObjectMap());
|
||||
map->set_prototype_validity_cell(Smi::FromInt(Map::kPrototypeChainValid));
|
||||
map->SetInObjectUnusedPropertyFields(0);
|
||||
map->set_bit_field(0);
|
||||
map->set_bit_field2(0);
|
||||
@ -2501,7 +2502,6 @@ AllocationResult Heap::AllocatePartialMap(InstanceType instance_type,
|
||||
Map::ConstructionCounterBits::encode(Map::kNoSlackTracking);
|
||||
map->set_bit_field3(bit_field3);
|
||||
map->set_weak_cell_cache(Smi::kZero);
|
||||
map->set_prototype_validity_cell(Smi::kZero);
|
||||
map->set_elements_kind(TERMINAL_FAST_ELEMENTS_KIND);
|
||||
return map;
|
||||
}
|
||||
@ -2530,14 +2530,15 @@ AllocationResult Heap::AllocateMap(InstanceType instance_type,
|
||||
map->SetInObjectPropertiesStartInWords(instance_size / kPointerSize -
|
||||
inobject_properties);
|
||||
DCHECK_EQ(map->GetInObjectProperties(), inobject_properties);
|
||||
map->set_prototype_validity_cell(invalid_prototype_validity_cell());
|
||||
} else {
|
||||
DCHECK_EQ(inobject_properties, 0);
|
||||
map->set_inobject_properties_start_or_constructor_function_index(0);
|
||||
map->set_prototype_validity_cell(Smi::FromInt(Map::kPrototypeChainValid));
|
||||
}
|
||||
map->set_dependent_code(DependentCode::cast(empty_fixed_array()),
|
||||
SKIP_WRITE_BARRIER);
|
||||
map->set_weak_cell_cache(Smi::kZero);
|
||||
map->set_prototype_validity_cell(Smi::kZero);
|
||||
map->set_raw_transitions(Smi::kZero);
|
||||
map->SetInObjectUnusedPropertyFields(inobject_properties);
|
||||
map->set_instance_descriptors(empty_descriptor_array());
|
||||
|
@ -213,6 +213,7 @@ using v8::MemoryPressureLevel;
|
||||
V(FixedArray, empty_ordered_hash_set, EmptyOrderedHashSet) \
|
||||
V(PropertyCell, empty_property_cell, EmptyPropertyCell) \
|
||||
V(WeakCell, empty_weak_cell, EmptyWeakCell) \
|
||||
V(Cell, invalid_prototype_validity_cell, InvalidPrototypeValidityCell) \
|
||||
V(InterceptorInfo, noop_interceptor_info, NoOpInterceptorInfo) \
|
||||
/* Protectors */ \
|
||||
V(Cell, array_constructor_protector, ArrayConstructorProtector) \
|
||||
|
@ -287,7 +287,15 @@ bool Heap::CreateInitialMaps() {
|
||||
|
||||
ALLOCATE_VARSIZE_MAP(CODE_TYPE, code)
|
||||
|
||||
ALLOCATE_MAP(CELL_TYPE, Cell::kSize, cell)
|
||||
ALLOCATE_MAP(CELL_TYPE, Cell::kSize, cell);
|
||||
{
|
||||
// The invalid_prototype_validity_cell is needed for JSObject maps.
|
||||
Smi* value = Smi::FromInt(Map::kPrototypeChainInvalid);
|
||||
Cell* cell;
|
||||
if (!AllocateCell(value).To(&cell)) return false;
|
||||
set_invalid_prototype_validity_cell(cell);
|
||||
}
|
||||
|
||||
ALLOCATE_MAP(PROPERTY_CELL_TYPE, PropertyCell::kSize, global_property_cell)
|
||||
ALLOCATE_MAP(WEAK_CELL_TYPE, WeakCell::kSize, weak_cell)
|
||||
ALLOCATE_MAP(FILLER_TYPE, kPointerSize, one_pointer_filler)
|
||||
|
@ -609,15 +609,9 @@ Node* AccessorAssembler::HandleProtoHandler(
|
||||
// Check prototype validity cell.
|
||||
//
|
||||
{
|
||||
Label done(this);
|
||||
Node* validity_cell =
|
||||
Node* maybe_validity_cell =
|
||||
LoadObjectField(handler, ICHandler::kValidityCellOffset);
|
||||
GotoIf(WordEqual(validity_cell, SmiConstant(0)), &done);
|
||||
Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset);
|
||||
GotoIf(WordNotEqual(cell_value, SmiConstant(Map::kPrototypeChainValid)),
|
||||
miss);
|
||||
Goto(&done);
|
||||
BIND(&done);
|
||||
CheckPrototypeValidityCell(maybe_validity_cell, miss);
|
||||
}
|
||||
|
||||
//
|
||||
@ -891,6 +885,20 @@ void AccessorAssembler::HandleStoreICHandlerCase(
|
||||
}
|
||||
}
|
||||
|
||||
void AccessorAssembler::CheckPrototypeValidityCell(Node* maybe_validity_cell,
|
||||
Label* miss) {
|
||||
Label done(this);
|
||||
GotoIf(WordEqual(maybe_validity_cell, SmiConstant(Map::kPrototypeChainValid)),
|
||||
&done);
|
||||
CSA_ASSERT(this, TaggedIsNotSmi(maybe_validity_cell));
|
||||
|
||||
Node* cell_value = LoadObjectField(maybe_validity_cell, Cell::kValueOffset);
|
||||
Branch(WordEqual(cell_value, SmiConstant(Map::kPrototypeChainValid)), &done,
|
||||
miss);
|
||||
|
||||
BIND(&done);
|
||||
}
|
||||
|
||||
void AccessorAssembler::HandleStoreAccessor(const StoreICParameters* p,
|
||||
Node* holder, Node* handler_word) {
|
||||
Comment("accessor_store");
|
||||
|
@ -197,6 +197,7 @@ class AccessorAssembler : public CodeStubAssembler {
|
||||
Representation representation, Node* value,
|
||||
Node* transition, Label* miss);
|
||||
|
||||
void CheckPrototypeValidityCell(Node* maybe_validity_cell, Label* miss);
|
||||
void HandleStoreICNativeDataProperty(const StoreICParameters* p, Node* holder,
|
||||
Node* handler_word);
|
||||
|
||||
|
@ -124,11 +124,7 @@ Handle<Object> LoadHandler::LoadFromPrototype(Isolate* isolate,
|
||||
Handle<Object> validity_cell =
|
||||
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
|
||||
if (validity_cell.is_null()) {
|
||||
// Although in case of kApiGetter we load from receiver we still have to
|
||||
// use the "prototype" shape of a handler in order to provide additional
|
||||
// data to the dispatcher.
|
||||
DCHECK_EQ(kApiGetter, GetHandlerKind(*smi_handler));
|
||||
validity_cell = handle(Smi::kZero, isolate);
|
||||
validity_cell = handle(Smi::FromInt(Map::kPrototypeChainValid), isolate);
|
||||
}
|
||||
|
||||
int data_count = 1 + checks_count;
|
||||
@ -157,7 +153,7 @@ Handle<Object> LoadHandler::LoadFullChain(Isolate* isolate,
|
||||
DCHECK_EQ(0, checks_count);
|
||||
// Lookup on receiver isn't supported in case of a simple smi handler.
|
||||
if (!LookupOnReceiverBits::decode(smi_handler->value())) return smi_handler;
|
||||
validity_cell = handle(Smi::kZero, isolate);
|
||||
validity_cell = handle(Smi::FromInt(Map::kPrototypeChainValid), isolate);
|
||||
}
|
||||
|
||||
int data_count = 1 + checks_count;
|
||||
@ -196,7 +192,7 @@ Handle<Object> StoreHandler::StoreElementTransition(
|
||||
Handle<Object> validity_cell =
|
||||
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
|
||||
if (validity_cell.is_null()) {
|
||||
validity_cell = handle(Smi::kZero, isolate);
|
||||
validity_cell = handle(Smi::FromInt(Map::kPrototypeChainValid), isolate);
|
||||
}
|
||||
Handle<WeakCell> cell = Map::WeakCellForMap(transition);
|
||||
Handle<StoreHandler> handler = isolate->factory()->NewStoreHandler(1);
|
||||
@ -247,7 +243,7 @@ Handle<Object> StoreHandler::StoreThroughPrototype(
|
||||
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
|
||||
if (validity_cell.is_null()) {
|
||||
DCHECK_EQ(0, checks_count);
|
||||
validity_cell = handle(Smi::kZero, isolate);
|
||||
validity_cell = handle(Smi::FromInt(Map::kPrototypeChainValid), isolate);
|
||||
}
|
||||
|
||||
int data_count = 1 + checks_count;
|
||||
|
@ -12510,13 +12510,8 @@ Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
|
||||
} else {
|
||||
maybe_prototype =
|
||||
handle(map->GetPrototypeChainRootMap(isolate)->prototype(), isolate);
|
||||
if (!maybe_prototype->IsJSReceiver()) return Handle<Cell>::null();
|
||||
}
|
||||
if (maybe_prototype->IsJSProxy()) {
|
||||
Handle<Cell> cell = isolate->factory()->NewCell(
|
||||
handle(Smi::FromInt(Map::kPrototypeChainValid), isolate));
|
||||
return cell;
|
||||
}
|
||||
if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null();
|
||||
Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype);
|
||||
// Ensure the prototype is registered with its own prototypes so its cell
|
||||
// will be invalidated when necessary.
|
||||
|
@ -292,33 +292,33 @@ KNOWN_OBJECTS = {
|
||||
("OLD_SPACE", 0x02519): "TerminationException",
|
||||
("OLD_SPACE", 0x02579): "OptimizedOut",
|
||||
("OLD_SPACE", 0x025d1): "StaleRegister",
|
||||
("OLD_SPACE", 0x02651): "EmptyByteArray",
|
||||
("OLD_SPACE", 0x02671): "EmptyFixedUint8Array",
|
||||
("OLD_SPACE", 0x02691): "EmptyFixedInt8Array",
|
||||
("OLD_SPACE", 0x026b1): "EmptyFixedUint16Array",
|
||||
("OLD_SPACE", 0x026d1): "EmptyFixedInt16Array",
|
||||
("OLD_SPACE", 0x026f1): "EmptyFixedUint32Array",
|
||||
("OLD_SPACE", 0x02711): "EmptyFixedInt32Array",
|
||||
("OLD_SPACE", 0x02731): "EmptyFixedFloat32Array",
|
||||
("OLD_SPACE", 0x02751): "EmptyFixedFloat64Array",
|
||||
("OLD_SPACE", 0x02771): "EmptyFixedUint8ClampedArray",
|
||||
("OLD_SPACE", 0x027d1): "EmptyScript",
|
||||
("OLD_SPACE", 0x02859): "ManyClosuresCell",
|
||||
("OLD_SPACE", 0x02869): "EmptySloppyArgumentsElements",
|
||||
("OLD_SPACE", 0x02889): "EmptySlowElementDictionary",
|
||||
("OLD_SPACE", 0x028d1): "EmptyOrderedHashMap",
|
||||
("OLD_SPACE", 0x028f9): "EmptyOrderedHashSet",
|
||||
("OLD_SPACE", 0x02921): "EmptyPropertyCell",
|
||||
("OLD_SPACE", 0x02949): "EmptyWeakCell",
|
||||
("OLD_SPACE", 0x029b9): "NoElementsProtector",
|
||||
("OLD_SPACE", 0x029e1): "IsConcatSpreadableProtector",
|
||||
("OLD_SPACE", 0x029f1): "SpeciesProtector",
|
||||
("OLD_SPACE", 0x02a19): "StringLengthProtector",
|
||||
("OLD_SPACE", 0x02a29): "ArrayIteratorProtector",
|
||||
("OLD_SPACE", 0x02a51): "ArrayBufferNeuteringProtector",
|
||||
("OLD_SPACE", 0x02ac9): "InfinityValue",
|
||||
("OLD_SPACE", 0x02ad9): "MinusZeroValue",
|
||||
("OLD_SPACE", 0x02ae9): "MinusInfinityValue",
|
||||
("OLD_SPACE", 0x02661): "EmptyByteArray",
|
||||
("OLD_SPACE", 0x02681): "EmptyFixedUint8Array",
|
||||
("OLD_SPACE", 0x026a1): "EmptyFixedInt8Array",
|
||||
("OLD_SPACE", 0x026c1): "EmptyFixedUint16Array",
|
||||
("OLD_SPACE", 0x026e1): "EmptyFixedInt16Array",
|
||||
("OLD_SPACE", 0x02701): "EmptyFixedUint32Array",
|
||||
("OLD_SPACE", 0x02721): "EmptyFixedInt32Array",
|
||||
("OLD_SPACE", 0x02741): "EmptyFixedFloat32Array",
|
||||
("OLD_SPACE", 0x02761): "EmptyFixedFloat64Array",
|
||||
("OLD_SPACE", 0x02781): "EmptyFixedUint8ClampedArray",
|
||||
("OLD_SPACE", 0x027e1): "EmptyScript",
|
||||
("OLD_SPACE", 0x02869): "ManyClosuresCell",
|
||||
("OLD_SPACE", 0x02879): "EmptySloppyArgumentsElements",
|
||||
("OLD_SPACE", 0x02899): "EmptySlowElementDictionary",
|
||||
("OLD_SPACE", 0x028e1): "EmptyOrderedHashMap",
|
||||
("OLD_SPACE", 0x02909): "EmptyOrderedHashSet",
|
||||
("OLD_SPACE", 0x02931): "EmptyPropertyCell",
|
||||
("OLD_SPACE", 0x02959): "EmptyWeakCell",
|
||||
("OLD_SPACE", 0x029c9): "NoElementsProtector",
|
||||
("OLD_SPACE", 0x029f1): "IsConcatSpreadableProtector",
|
||||
("OLD_SPACE", 0x02a01): "SpeciesProtector",
|
||||
("OLD_SPACE", 0x02a29): "StringLengthProtector",
|
||||
("OLD_SPACE", 0x02a39): "ArrayIteratorProtector",
|
||||
("OLD_SPACE", 0x02a61): "ArrayBufferNeuteringProtector",
|
||||
("OLD_SPACE", 0x02ad9): "InfinityValue",
|
||||
("OLD_SPACE", 0x02ae9): "MinusZeroValue",
|
||||
("OLD_SPACE", 0x02af9): "MinusInfinityValue",
|
||||
}
|
||||
|
||||
# List of known V8 Frame Markers.
|
||||
|
Loading…
Reference in New Issue
Block a user