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