[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:
Igor Sheludko 2018-03-08 10:59:52 +01:00 committed by Commit Bot
parent 501f250c0b
commit aeee606360
8 changed files with 62 additions and 52 deletions

View File

@ -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());

View File

@ -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) \

View File

@ -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)

View File

@ -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");

View File

@ -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);

View File

@ -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;

View File

@ -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.

View File

@ -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.