Commit 78ab62e4 authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[ic] Use StoreHandler objects instead of Tuple2 handlers in KeyedStoreICs.

Bug: v8:7206, v8:5561
Change-Id: Ieb8bae0a245c6135d375cec0f76ce80a240391b9
Reviewed-on: https://chromium-review.googlesource.com/819290
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50109}
parent e3790896
......@@ -56,6 +56,7 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
V(OneClosureCellMap, one_closure_cell_map, OneClosureCellMap) \
V(prototype_string, prototype_string, PrototypeString) \
V(SpeciesProtector, species_protector, SpeciesProtector) \
V(StoreHandler0Map, store_handler0_map, StoreHandler0Map) \
V(SymbolMap, symbol_map, SymbolMap) \
V(TheHoleValue, the_hole_value, TheHole) \
V(TrueValue, true_value, True) \
......
......@@ -2791,11 +2791,19 @@ Handle<LoadHandler> Factory::NewLoadHandler(int data_count) {
Handle<StoreHandler> Factory::NewStoreHandler(int data_count) {
Handle<Map> map;
if (data_count == 1) {
map = store_handler1_map();
} else {
DCHECK_EQ(2, data_count);
map = store_handler2_map();
switch (data_count) {
case 0:
map = store_handler0_map();
break;
case 1:
map = store_handler1_map();
break;
case 2:
map = store_handler2_map();
break;
default:
UNREACHABLE();
break;
}
return New<StoreHandler>(map, OLD_SPACE);
}
......
......@@ -958,14 +958,9 @@ KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const {
// The first handler that isn't the slow handler will have the bits we need.
Handle<Code> handler;
if (maybe_code_handler->IsStoreHandler()) {
// Elements transition.
Handle<StoreHandler> data_handler =
Handle<StoreHandler>::cast(maybe_code_handler);
handler = handle(Code::cast(data_handler->smi_handler()));
} else if (maybe_code_handler->IsTuple2()) {
// Element store with prototype chain check.
Handle<Tuple2> data_handler = Handle<Tuple2>::cast(maybe_code_handler);
handler = handle(Code::cast(data_handler->value2()));
} else if (maybe_code_handler->IsSmi()) {
// Skip proxy handlers.
DCHECK_EQ(*maybe_code_handler, *StoreHandler::StoreProxy(GetIsolate()));
......
......@@ -799,7 +799,7 @@ void AccessorAssembler::HandleStoreICHandlerCase(
{
Node* handler_map = LoadMap(handler);
if (support_elements == kSupportElements) {
GotoIf(IsTuple2Map(handler_map), &if_element_handler);
GotoIf(IsStoreHandler0Map(handler_map), &if_element_handler);
}
GotoIf(IsWeakCellMap(handler_map), &store_global);
Branch(IsCodeMap(handler_map), &call_handler, &if_proto_handler);
......@@ -834,12 +834,14 @@ void AccessorAssembler::HandleStoreICHandlerCase(
void AccessorAssembler::HandleStoreICElementHandlerCase(
const StoreICParameters* p, Node* handler, Label* miss) {
Comment("HandleStoreICElementHandlerCase");
Node* validity_cell = LoadObjectField(handler, Tuple2::kValue1Offset);
Node* validity_cell =
LoadObjectField(handler, StoreHandler::kValidityCellOffset);
Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset);
GotoIf(WordNotEqual(cell_value, SmiConstant(Map::kPrototypeChainValid)),
miss);
Node* code_handler = LoadObjectField(handler, Tuple2::kValue2Offset);
Node* code_handler =
LoadObjectField(handler, StoreHandler::kSmiHandlerOffset);
CSA_ASSERT(this, IsCodeMap(LoadMap(code_handler)));
StoreWithVectorDescriptor descriptor(isolate());
......
......@@ -41,8 +41,8 @@ Address IC::raw_constant_pool() const {
bool IC::IsHandler(Object* object) {
return (object->IsSmi() && (object != nullptr)) || object->IsTuple2() ||
object->IsDataHandler() || object->IsWeakCell() || object->IsCode();
return (object->IsSmi() && (object != nullptr)) || object->IsDataHandler() ||
object->IsWeakCell() || object->IsCode();
}
bool IC::AddressIsDeoptimizedCode() const {
......
......@@ -1800,6 +1800,7 @@ Handle<Object> KeyedStoreIC::StoreElementHandler(
return StoreHandler::StoreProxy(isolate());
}
// TODO(ishell): move to StoreHandler::StoreElement().
ElementsKind elements_kind = receiver_map->elements_kind();
bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
Handle<Code> stub;
......@@ -1821,7 +1822,10 @@ Handle<Object> KeyedStoreIC::StoreElementHandler(
Handle<Object> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (validity_cell.is_null()) return stub;
return isolate()->factory()->NewTuple2(validity_cell, stub, TENURED);
Handle<StoreHandler> handler = isolate()->factory()->NewStoreHandler(0);
handler->set_validity_cell(*validity_cell);
handler->set_smi_handler(*stub);
return handler;
}
void KeyedStoreIC::StoreElementPolymorphicHandlers(
......
......@@ -1350,8 +1350,11 @@ void DataHandler::DataHandlerVerify() {
CHECK_IMPLIES(!smi_handler()->IsSmi(),
smi_handler()->IsCode() && IsStoreHandler());
CHECK(validity_cell()->IsSmi() || validity_cell()->IsCell());
VerifyObjectField(kData1Offset);
if (map()->instance_size() >= kSizeWithData2) {
int data_count = data_field_count();
if (data_count >= 1) {
VerifyObjectField(kData1Offset);
}
if (data_count >= 2) {
VerifyObjectField(kData2Offset);
}
}
......
......@@ -1452,8 +1452,11 @@ void LoadHandler::LoadHandlerPrint(std::ostream& os) { // NOLINT
// TODO(ishell): implement printing based on handler kind
os << "\n - handler: " << Brief(smi_handler());
os << "\n - validity_cell: " << Brief(validity_cell());
os << "\n - data1: " << Brief(data1());
if (map()->instance_size() >= kSizeWithData2) {
int data_count = data_field_count();
if (data_count >= 1) {
os << "\n - data1: " << Brief(data1());
}
if (data_count >= 2) {
os << "\n - data2: " << Brief(data2());
}
os << "\n";
......@@ -1464,8 +1467,11 @@ void StoreHandler::StoreHandlerPrint(std::ostream& os) { // NOLINT
// TODO(ishell): implement printing based on handler kind
os << "\n - handler: " << Brief(smi_handler());
os << "\n - validity_cell: " << Brief(validity_cell());
os << "\n - data1: " << Brief(data1());
if (map()->instance_size() >= kSizeWithData2) {
int data_count = data_field_count();
if (data_count >= 1) {
os << "\n - data1: " << Brief(data1());
}
if (data_count >= 2) {
os << "\n - data2: " << Brief(data2());
}
os << "\n";
......
......@@ -560,6 +560,7 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
#define DATA_HANDLER_LIST(V) \
V(LOAD_HANDLER, LoadHandler, 1, load_handler1) \
V(LOAD_HANDLER, LoadHandler, 2, load_handler2) \
V(STORE_HANDLER, StoreHandler, 0, store_handler0) \
V(STORE_HANDLER, StoreHandler, 1, store_handler1) \
V(STORE_HANDLER, StoreHandler, 2, store_handler2)
......
......@@ -22,7 +22,12 @@ CAST_ACCESSOR(DataHandler)
ACCESSORS(DataHandler, smi_handler, Object, kSmiHandlerOffset)
ACCESSORS(DataHandler, validity_cell, Object, kValidityCellOffset)
ACCESSORS(DataHandler, data1, Object, kData1Offset)
int DataHandler::data_field_count() const {
return (map()->instance_size() - kSizeWithData0) / kPointerSize;
}
ACCESSORS_CHECKED(DataHandler, data1, Object, kData1Offset,
map()->instance_size() >= kSizeWithData1)
ACCESSORS_CHECKED(DataHandler, data2, Object, kData2Offset,
map()->instance_size() >= kSizeWithData2)
......
......@@ -26,6 +26,9 @@ class DataHandler : public Struct {
// [validity_cell]: A validity Cell that guards prototype chain modifications.
DECL_ACCESSORS(validity_cell, Object)
// Returns number of optional data fields available in the object.
inline int data_field_count() const;
// [data1,2]: These are optional general-purpose fields whose content and
// presence depends on the handler kind.
DECL_ACCESSORS(data1, Object)
......@@ -35,6 +38,7 @@ class DataHandler : public Struct {
#define DATA_HANDLER_FIELDS(V) \
V(kSmiHandlerOffset, kPointerSize) \
V(kValidityCellOffset, kPointerSize) \
V(kSizeWithData0, 0) \
V(kData1Offset, kPointerSize) \
V(kSizeWithData1, 0) \
V(kData2Offset, kPointerSize) \
......
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