Commit f1783617 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[ic] Make transition-code unaware of handler encodings

Bug: 
Change-Id: I6894c097a994527b5e749527966c5de6c42d964b
Reviewed-on: https://chromium-review.googlesource.com/668405
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48195}
parent aaebbbaa
......@@ -182,19 +182,24 @@ Handle<Smi> StoreHandler::TransitionToConstant(Isolate* isolate,
}
// static
WeakCell* StoreHandler::GetTuple3TransitionCell(Object* tuple3_handler) {
STATIC_ASSERT(kTransitionCellOffset == Tuple3::kValue1Offset);
WeakCell* cell = WeakCell::cast(Tuple3::cast(tuple3_handler)->value1());
WeakCell* StoreHandler::GetTransitionCell(Object* handler) {
if (handler->IsTuple3()) {
STATIC_ASSERT(kTransitionCellOffset == Tuple3::kValue1Offset);
WeakCell* cell = WeakCell::cast(Tuple3::cast(handler)->value1());
DCHECK(!cell->cleared());
return cell;
}
DCHECK(handler->IsFixedArray());
WeakCell* cell =
WeakCell::cast(FixedArray::cast(handler)->get(kTransitionCellIndex));
DCHECK(!cell->cleared());
return cell;
}
// static
WeakCell* StoreHandler::GetArrayTransitionCell(Object* array_handler) {
WeakCell* cell = WeakCell::cast(
FixedArray::cast(array_handler)->get(kTransitionCellIndex));
DCHECK(!cell->cleared());
return cell;
bool StoreHandler::IsHandler(Object* maybe_handler) {
return maybe_handler->IsFixedArray() || maybe_handler->IsTuple3();
}
} // namespace internal
......
......@@ -209,34 +209,6 @@ Handle<Object> LoadHandler::LoadFullChain(Isolate* isolate,
return handler_array;
}
// |name| can be nullptr if no name/details check needs to be performed.
Object* StoreHandler::ValidTuple3HandlerOrNull(Object* handler, Name* name,
Handle<Map>* out_transition) {
DCHECK(handler->IsTuple3());
// Step 1: Check validity cell.
STATIC_ASSERT(kValidityCellOffset == Tuple3::kValue3Offset);
Object* raw_validity_cell = Tuple3::cast(handler)->value3();
Smi* valid = Smi::FromInt(Map::kPrototypeChainValid);
// |raw_valitity_cell| can be Smi::kZero if no validity cell is required
// (which counts as valid).
if (raw_validity_cell->IsCell() &&
Cell::cast(raw_validity_cell)->value() != valid) {
return nullptr;
}
// Step 2 (optional): Check transition key.
WeakCell* target_cell = GetTuple3TransitionCell(handler);
if (name != nullptr) {
if (!TransitionsAccessor::IsMatchingMap(target_cell, name, kData, NONE)) {
return nullptr;
}
}
// Step 3: Check if the transition target is deprecated.
Map* transition = Map::cast(target_cell->value());
if (transition->is_deprecated()) return nullptr;
*out_transition = handle(transition);
return handler;
}
// static
Handle<Object> StoreHandler::StoreElementTransition(
Isolate* isolate, Handle<Map> receiver_map, Handle<Map> transition,
......@@ -363,44 +335,67 @@ Handle<Object> StoreHandler::StoreProxy(Isolate* isolate,
return handler_array;
}
Object* StoreHandler::ValidFixedArrayHandlerOrNull(
Object* raw_handler, Name* name, Handle<Map>* out_transition) {
DCHECK(raw_handler->IsFixedArray());
FixedArray* handler = FixedArray::cast(raw_handler);
// Step 1: Check validity cell.
Object* value = Cell::cast(handler->get(kValidityCellIndex))->value();
if (value != Smi::FromInt(Map::kPrototypeChainValid)) return nullptr;
// Step 2: Check transition key.
WeakCell* target_cell = GetArrayTransitionCell(handler);
if (!TransitionsAccessor::IsMatchingMap(target_cell, name, kData, NONE)) {
return nullptr;
}
// Step 3: Check prototypes.
Heap* heap = handler->GetHeap();
Isolate* isolate = heap->isolate();
Handle<Name> name_handle(name, isolate);
for (int i = kFirstPrototypeIndex; i < handler->length(); i++) {
// This mirrors AccessorAssembler::CheckPrototype.
WeakCell* prototype_cell = WeakCell::cast(handler->get(i));
if (prototype_cell->cleared()) return nullptr;
HeapObject* maybe_prototype = HeapObject::cast(prototype_cell->value());
if (maybe_prototype->IsPropertyCell()) {
Object* value = PropertyCell::cast(maybe_prototype)->value();
if (value != heap->the_hole_value()) return nullptr;
} else {
DCHECK(maybe_prototype->map()->is_dictionary_map());
// Do a negative dictionary lookup.
NameDictionary* dict =
JSObject::cast(maybe_prototype)->property_dictionary();
int number = dict->FindEntry(isolate, name_handle);
if (number != NameDictionary::kNotFound) return nullptr;
Object* StoreHandler::ValidHandlerOrNull(Object* raw_handler, Name* name,
Handle<Map>* out_transition) {
STATIC_ASSERT(kValidityCellOffset == Tuple3::kValue3Offset);
Smi* valid = Smi::FromInt(Map::kPrototypeChainValid);
if (raw_handler->IsTuple3()) {
// Check validity cell.
Tuple3* handler = Tuple3::cast(raw_handler);
Object* raw_validity_cell = handler->value3();
// |raw_valitity_cell| can be Smi::kZero if no validity cell is required
// (which counts as valid).
if (raw_validity_cell->IsCell() &&
Cell::cast(raw_validity_cell)->value() != valid) {
return nullptr;
}
} else {
DCHECK(raw_handler->IsFixedArray());
FixedArray* handler = FixedArray::cast(raw_handler);
// Check validity cell.
Object* value = Cell::cast(handler->get(kValidityCellIndex))->value();
if (value != valid) return nullptr;
// Check prototypes.
Heap* heap = handler->GetHeap();
Isolate* isolate = heap->isolate();
Handle<Name> name_handle(name, isolate);
for (int i = kFirstPrototypeIndex; i < handler->length(); i++) {
// This mirrors AccessorAssembler::CheckPrototype.
WeakCell* prototype_cell = WeakCell::cast(handler->get(i));
if (prototype_cell->cleared()) return nullptr;
HeapObject* maybe_prototype = HeapObject::cast(prototype_cell->value());
if (maybe_prototype->IsPropertyCell()) {
Object* value = PropertyCell::cast(maybe_prototype)->value();
if (value != heap->the_hole_value()) return nullptr;
} else {
DCHECK(maybe_prototype->map()->is_dictionary_map());
// Do a negative dictionary lookup.
NameDictionary* dict =
JSObject::cast(maybe_prototype)->property_dictionary();
int number = dict->FindEntry(isolate, name_handle);
if (number != NameDictionary::kNotFound) {
PropertyDetails details = dict->DetailsAt(number);
if (details.IsReadOnly() || details.kind() == kAccessor) {
return nullptr;
}
break;
}
}
}
}
// Step 4: Check if the transition target is deprecated.
// Check if the transition target is deprecated.
WeakCell* target_cell = GetTransitionCell(raw_handler);
Map* transition = Map::cast(target_cell->value());
if (transition->is_deprecated()) return nullptr;
*out_transition = handle(transition);
return handler;
return raw_handler;
}
} // namespace internal
......
......@@ -189,6 +189,8 @@ class StoreHandler {
enum FieldRepresentation { kSmi, kDouble, kHeapObject, kTagged };
static inline bool IsHandler(Object* maybe_handler);
// Applicable to kStoreField, kTransitionToField and kTransitionToConstant
// kinds.
......@@ -223,9 +225,9 @@ class StoreHandler {
static const int kSmiHandlerOffset = Tuple3::kValue2Offset;
static const int kValidityCellOffset = Tuple3::kValue3Offset;
static inline WeakCell* GetTuple3TransitionCell(Object* tuple3_handler);
static Object* ValidTuple3HandlerOrNull(Object* handler, Name* name,
Handle<Map>* out_transition);
static inline WeakCell* GetTransitionCell(Object* handler);
static Object* ValidHandlerOrNull(Object* handler, Name* name,
Handle<Map>* out_transition);
// The layout of an array handler representing a transitioning store
// when prototype chain checks include non-existing lookups and access checks.
......@@ -234,10 +236,6 @@ class StoreHandler {
static const int kTransitionCellIndex = 2;
static const int kFirstPrototypeIndex = 3;
static inline WeakCell* GetArrayTransitionCell(Object* array_handler);
static Object* ValidFixedArrayHandlerOrNull(Object* raw_handler, Name* name,
Handle<Map>* out_transition);
// Creates a Smi-handler for storing a field to fast object.
static inline Handle<Smi> StoreField(Isolate* isolate, int descriptor,
FieldIndex field_index,
......
......@@ -1738,11 +1738,8 @@ void TransitionsAccessor::PrintTransitions(std::ostream& os) { // NOLINT
case kWeakCell:
cell = GetTargetCell<kWeakCell>();
break;
case kTuple3Handler:
cell = GetTargetCell<kTuple3Handler>();
break;
case kFixedArrayHandler:
cell = GetTargetCell<kFixedArrayHandler>();
case kHandler:
cell = GetTargetCell<kHandler>();
break;
case kFullTransitionArray:
return transitions()->Print(os);
......
......@@ -18,10 +18,8 @@ WeakCell* TransitionsAccessor::GetTargetCell() {
if (target_cell_ != nullptr) return target_cell_;
if (enc == kWeakCell) {
target_cell_ = WeakCell::cast(raw_transitions_);
} else if (enc == kTuple3Handler) {
target_cell_ = StoreHandler::GetTuple3TransitionCell(raw_transitions_);
} else if (enc == kFixedArrayHandler) {
target_cell_ = StoreHandler::GetArrayTransitionCell(raw_transitions_);
} else if (enc == kHandler) {
target_cell_ = StoreHandler::GetTransitionCell(raw_transitions_);
} else {
UNREACHABLE();
}
......@@ -84,11 +82,8 @@ Name* TransitionsAccessor::GetKey(int transition_number) {
case kWeakCell:
cell = GetTargetCell<kWeakCell>();
break;
case kTuple3Handler:
cell = GetTargetCell<kTuple3Handler>();
break;
case kFixedArrayHandler:
cell = GetTargetCell<kFixedArrayHandler>();
case kHandler:
cell = GetTargetCell<kHandler>();
break;
case kFullTransitionArray:
return transitions()->GetKey(transition_number);
......@@ -119,14 +114,8 @@ PropertyDetails TransitionsAccessor::GetTargetDetails(Name* name, Map* target) {
// static
Map* TransitionsAccessor::GetTargetFromRaw(Object* raw) {
if (raw->IsWeakCell()) {
return Map::cast(WeakCell::cast(raw)->value());
} else if (raw->IsTuple3()) {
return Map::cast(StoreHandler::GetTuple3TransitionCell(raw)->value());
} else {
DCHECK(raw->IsFixedArray());
return Map::cast(StoreHandler::GetArrayTransitionCell(raw)->value());
}
if (raw->IsWeakCell()) return Map::cast(WeakCell::cast(raw)->value());
return Map::cast(StoreHandler::GetTransitionCell(raw)->value());
}
Object* TransitionArray::GetRawTarget(int transition_number) {
......@@ -149,11 +138,8 @@ Map* TransitionsAccessor::GetTarget(int transition_number) {
case kWeakCell:
cell = GetTargetCell<kWeakCell>();
break;
case kTuple3Handler:
cell = GetTargetCell<kTuple3Handler>();
break;
case kFixedArrayHandler:
cell = GetTargetCell<kFixedArrayHandler>();
case kHandler:
cell = GetTargetCell<kHandler>();
break;
case kFullTransitionArray:
return transitions()->GetTarget(transition_number);
......
......@@ -17,10 +17,8 @@ void TransitionsAccessor::Initialize() {
encoding_ = kUninitialized;
} else if (HeapObject::cast(raw_transitions_)->IsWeakCell()) {
encoding_ = kWeakCell;
} else if (HeapObject::cast(raw_transitions_)->IsTuple3()) {
encoding_ = kTuple3Handler;
} else if (HeapObject::cast(raw_transitions_)->IsFixedArray()) {
encoding_ = kFixedArrayHandler;
} else if (StoreHandler::IsHandler(raw_transitions_)) {
encoding_ = kHandler;
} else if (HeapObject::cast(raw_transitions_)->IsTransitionArray()) {
encoding_ = kFullTransitionArray;
} else {
......@@ -37,10 +35,8 @@ Map* TransitionsAccessor::GetSimpleTransition() {
switch (encoding()) {
case kWeakCell:
return Map::cast(GetTargetCell<kWeakCell>()->value());
case kTuple3Handler:
return Map::cast(GetTargetCell<kTuple3Handler>()->value());
case kFixedArrayHandler:
return Map::cast(GetTargetCell<kFixedArrayHandler>()->value());
case kHandler:
return Map::cast(GetTargetCell<kHandler>()->value());
default:
return nullptr;
}
......@@ -51,10 +47,8 @@ bool TransitionsAccessor::HasSimpleTransitionTo(WeakCell* cell) {
switch (encoding()) {
case kWeakCell:
return raw_transitions_ == cell;
case kTuple3Handler:
return StoreHandler::GetTuple3TransitionCell(raw_transitions_) == cell;
case kFixedArrayHandler:
return StoreHandler::GetArrayTransitionCell(raw_transitions_) == cell;
case kHandler:
return StoreHandler::GetTransitionCell(raw_transitions_) == cell;
case kPrototypeInfo:
case kUninitialized:
case kFullTransitionArray:
......@@ -219,8 +213,7 @@ void TransitionsAccessor::UpdateHandler(Name* name, Object* handler) {
UNREACHABLE();
return;
case kWeakCell:
case kTuple3Handler:
case kFixedArrayHandler:
case kHandler:
DCHECK_EQ(GetSimpleTransition(), GetTargetFromRaw(handler));
ReplaceTransitions(handler);
return;
......@@ -243,23 +236,23 @@ Object* TransitionsAccessor::SearchHandler(Name* name,
case kUninitialized:
case kWeakCell:
return nullptr;
case kTuple3Handler:
return StoreHandler::ValidTuple3HandlerOrNull(raw_transitions_, name,
out_transition);
case kFixedArrayHandler:
return StoreHandler::ValidFixedArrayHandlerOrNull(raw_transitions_, name,
out_transition);
case kHandler: {
Object* raw_handler = StoreHandler::ValidHandlerOrNull(
raw_transitions_, name, out_transition);
if (raw_handler == nullptr) return raw_handler;
// Check transition key.
WeakCell* target_cell = StoreHandler::GetTransitionCell(raw_handler);
if (!IsMatchingMap(target_cell, name, kData, NONE)) return nullptr;
return raw_handler;
}
case kFullTransitionArray: {
int transition = transitions()->Search(kData, name, NONE);
if (transition == kNotFound) return nullptr;
Object* raw_handler = transitions()->GetRawTarget(transition);
if (raw_handler->IsTuple3()) {
return StoreHandler::ValidTuple3HandlerOrNull(raw_handler, nullptr,
out_transition);
}
if (raw_handler->IsFixedArray()) {
return StoreHandler::ValidFixedArrayHandlerOrNull(raw_handler, nullptr,
out_transition);
if (StoreHandler::IsHandler(raw_handler)) {
return StoreHandler::ValidHandlerOrNull(raw_handler, name,
out_transition);
}
return nullptr;
}
......@@ -279,11 +272,8 @@ Map* TransitionsAccessor::SearchTransition(Name* name, PropertyKind kind,
case kWeakCell:
cell = GetTargetCell<kWeakCell>();
break;
case kTuple3Handler:
cell = GetTargetCell<kTuple3Handler>();
break;
case kFixedArrayHandler:
cell = GetTargetCell<kFixedArrayHandler>();
case kHandler:
cell = GetTargetCell<kHandler>();
break;
case kFullTransitionArray: {
int transition = transitions()->Search(kind, name, attributes);
......@@ -336,11 +326,8 @@ Handle<String> TransitionsAccessor::ExpectedTransitionKey() {
case kWeakCell:
cell = GetTargetCell<kWeakCell>();
break;
case kTuple3Handler:
cell = GetTargetCell<kTuple3Handler>();
break;
case kFixedArrayHandler:
cell = GetTargetCell<kFixedArrayHandler>();
case kHandler:
cell = GetTargetCell<kHandler>();
break;
}
DCHECK(!cell->cleared());
......@@ -499,8 +486,7 @@ int TransitionsAccessor::NumberOfTransitions() {
case kUninitialized:
return 0;
case kWeakCell:
case kTuple3Handler:
case kFixedArrayHandler:
case kHandler:
return 1;
case kFullTransitionArray:
return transitions()->number_of_transitions();
......@@ -583,11 +569,8 @@ void TransitionsAccessor::TraverseTransitionTreeInternal(
case kWeakCell:
simple_target = Map::cast(GetTargetCell<kWeakCell>()->value());
break;
case kTuple3Handler:
simple_target = Map::cast(GetTargetCell<kTuple3Handler>()->value());
break;
case kFixedArrayHandler:
simple_target = Map::cast(GetTargetCell<kFixedArrayHandler>()->value());
case kHandler:
simple_target = Map::cast(GetTargetCell<kHandler>()->value());
break;
case kFullTransitionArray: {
if (transitions()->HasPrototypeTransitions()) {
......
......@@ -124,8 +124,7 @@ class TransitionsAccessor {
kPrototypeInfo,
kUninitialized,
kWeakCell,
kTuple3Handler,
kFixedArrayHandler,
kHandler,
kFullTransitionArray,
};
......
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