Commit 584fb75a authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[ic] Restructure API load/store data handlers.

... by "inlining" the Tuple2 object into the data handler.

Bug: v8:7206, v8:5561
Change-Id: I8517b2faa8d13bd16b8ec99c7ea8ab97c73a5f2a
Reviewed-on: https://chromium-review.googlesource.com/819233Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50164}
parent 03165cb9
......@@ -2780,11 +2780,19 @@ Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<Context> native_context,
Handle<LoadHandler> Factory::NewLoadHandler(int data_count) {
Handle<Map> map;
if (data_count == 1) {
switch (data_count) {
case 1:
map = load_handler1_map();
} else {
DCHECK_EQ(2, data_count);
break;
case 2:
map = load_handler2_map();
break;
case 3:
map = load_handler3_map();
break;
default:
UNREACHABLE();
break;
}
return New<LoadHandler>(map, OLD_SPACE);
}
......@@ -2801,6 +2809,9 @@ Handle<StoreHandler> Factory::NewStoreHandler(int data_count) {
case 2:
map = store_handler2_map();
break;
case 3:
map = store_handler3_map();
break;
default:
UNREACHABLE();
break;
......
......@@ -31,13 +31,22 @@ Node* AccessorAssembler::LoadHandlerDataField(Node* handler, int data_index) {
InstanceTypeEqual(instance_type, STORE_HANDLER_TYPE)));
int offset = 0;
int minimum_size = 0;
if (data_index == 1) {
switch (data_index) {
case 1:
offset = DataHandler::kData1Offset;
minimum_size = DataHandler::kSizeWithData1;
} else {
DCHECK_EQ(2, data_index);
break;
case 2:
offset = DataHandler::kData2Offset;
minimum_size = DataHandler::kSizeWithData2;
break;
case 3:
offset = DataHandler::kData3Offset;
minimum_size = DataHandler::kSizeWithData3;
break;
default:
UNREACHABLE();
break;
}
USE(minimum_size);
CSA_ASSERT(this, UintPtrGreaterThanOrEqual(
......@@ -172,7 +181,8 @@ void AccessorAssembler::HandleLoadICHandlerCase(
BIND(&if_smi_handler);
{
HandleLoadICSmiHandlerCase(p, var_holder.value(), var_smi_handler.value(),
miss, exit_point, false, support_elements);
handler, miss, exit_point, false,
support_elements);
}
BIND(&try_proto_handler);
......@@ -246,8 +256,9 @@ Node* AccessorAssembler::LoadDescriptorValue(Node* map, Node* descriptor) {
}
void AccessorAssembler::HandleLoadICSmiHandlerCase(
const LoadICParameters* p, Node* holder, Node* smi_handler, Label* miss,
ExitPoint* exit_point, bool throw_reference_error_if_nonexistent,
const LoadICParameters* p, Node* holder, Node* smi_handler, Node* handler,
Label* miss, ExitPoint* exit_point,
bool throw_reference_error_if_nonexistent,
ElementSupport support_elements) {
VARIABLE(var_double_value, MachineRepresentation::kFloat64);
Label rebox_double(this, &var_double_value);
......@@ -450,11 +461,18 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase(
BIND(&api_getter);
{
Comment("api_getter");
Node* context = LoadWeakCellValueUnchecked(
LoadObjectField(holder, Tuple2::kValue1Offset));
Node* call_handler_info = LoadWeakCellValueUnchecked(
LoadObjectField(holder, Tuple2::kValue2Offset));
CSA_ASSERT(this, TaggedIsNotSmi(handler));
Node* call_handler_info = holder;
// Context is stored either in data2 or data3 field depending on whether
// the access check is enabled for this handler or not.
Node* context_cell = Select(
IsSetWord<LoadHandler::DoAccessCheckOnReceiverBits>(handler_word),
[=] { return LoadHandlerDataField(handler, 3); },
[=] { return LoadHandlerDataField(handler, 2); },
MachineRepresentation::kTagged);
Node* context = LoadWeakCellValueUnchecked(context_cell);
Node* foreign =
LoadObjectField(call_handler_info, CallHandlerInfo::kJsCallbackOffset);
Node* callback = LoadObjectField(foreign, Foreign::kForeignAddressOffset,
......@@ -709,11 +727,6 @@ void AccessorAssembler::HandleLoadICProtoHandler(
Branch(IsNull(maybe_holder_cell), &done, &load_from_cached_holder);
BIND(&load_from_cached_holder);
{
Label unwrap_cell(this), bind_holder(this);
Branch(IsWeakCell(maybe_holder_cell), &unwrap_cell, &bind_holder);
BIND(&unwrap_cell);
{
// For regular holders, having passed the receiver map check and the
// validity cell check implies that |holder| is alive. However, for
......@@ -724,13 +737,6 @@ void AccessorAssembler::HandleLoadICProtoHandler(
Goto(&done);
}
BIND(&bind_holder);
{
var_holder->Bind(maybe_holder_cell);
Goto(&done);
}
}
BIND(&done);
{
var_smi_handler->Bind(smi_handler);
......@@ -774,8 +780,8 @@ void AccessorAssembler::HandleLoadGlobalICHandlerCase(
ICMode::kGlobalIC);
BIND(&if_smi_handler);
HandleLoadICSmiHandlerCase(
&p, var_holder.value(), var_smi_handler.value(), miss, exit_point,
throw_reference_error_if_nonexistent, kOnlyProperties);
&p, var_holder.value(), var_smi_handler.value(), handler, miss,
exit_point, throw_reference_error_if_nonexistent, kOnlyProperties);
}
void AccessorAssembler::JumpIfDataProperty(Node* details, Label* writable,
......@@ -973,30 +979,20 @@ void AccessorAssembler::HandleStoreICProtoHandler(
},
miss, ic_mode);
VARIABLE(var_transition_map_or_holder, MachineRepresentation::kTagged);
Label if_transition_map(this), if_holder_object(this);
{
Node* maybe_transition_cell = LoadHandlerDataField(handler, 1);
var_transition_map_or_holder.Bind(maybe_transition_cell);
Label unwrap_cell(this);
Branch(IsWeakCell(maybe_transition_cell), &unwrap_cell, &if_holder_object);
BIND(&unwrap_cell);
{
Node* maybe_transition = LoadWeakCellValue(maybe_transition_cell, miss);
var_transition_map_or_holder.Bind(maybe_transition);
Branch(IsMap(maybe_transition), &if_transition_map, &if_holder_object);
}
}
Node* maybe_transition_or_holder_cell = LoadHandlerDataField(handler, 1);
Node* maybe_transition_or_holder =
LoadWeakCellValue(maybe_transition_or_holder_cell, miss);
Branch(IsMap(maybe_transition_or_holder), &if_transition_map,
&if_holder_object);
BIND(&if_transition_map);
{
Label if_transition_to_constant(this), if_store_normal(this);
Node* holder = p->receiver;
Node* transition_map = var_transition_map_or_holder.value();
Node* transition_map = maybe_transition_or_holder;
GotoIf(IsDeprecatedMap(transition_map), miss);
Node* handler_word = SmiUntag(smi_handler);
......@@ -1070,7 +1066,7 @@ void AccessorAssembler::HandleStoreICProtoHandler(
{
Label if_store_global_proxy(this), if_api_setter(this), if_accessor(this),
if_native_data_property(this);
Node* holder = var_transition_map_or_holder.value();
Node* holder = maybe_transition_or_holder;
CSA_ASSERT(this, TaggedIsSmi(smi_handler));
Node* handler_word = SmiUntag(smi_handler);
......@@ -1106,10 +1102,18 @@ void AccessorAssembler::HandleStoreICProtoHandler(
BIND(&if_api_setter);
{
Comment("api_setter");
Node* context = LoadWeakCellValueUnchecked(
LoadObjectField(holder, Tuple2::kValue1Offset));
Node* call_handler_info = LoadWeakCellValueUnchecked(
LoadObjectField(holder, Tuple2::kValue2Offset));
CSA_ASSERT(this, TaggedIsNotSmi(handler));
Node* call_handler_info = holder;
// Context is stored either in data2 or data3 field depending on whether
// the access check is enabled for this handler or not.
Node* context_cell = Select(
IsSetWord<LoadHandler::DoAccessCheckOnReceiverBits>(handler_word),
[=] { return LoadHandlerDataField(handler, 3); },
[=] { return LoadHandlerDataField(handler, 2); },
MachineRepresentation::kTagged);
Node* context = LoadWeakCellValueUnchecked(context_cell);
Node* foreign = LoadObjectField(call_handler_info,
CallHandlerInfo::kJsCallbackOffset);
......@@ -2338,6 +2342,8 @@ void AccessorAssembler::LoadGlobalIC_TryHandlerCase(const LoadICParameters* pp,
bool throw_reference_error_if_nonexistent = typeof_mode == NOT_INSIDE_TYPEOF;
// TODO(ishell): revisit if this way of code organization still improves
// things given that we don't have array handlers anymore.
{
LoadICParameters p = *pp;
DCHECK_NULL(p.receiver);
......@@ -2345,7 +2351,7 @@ void AccessorAssembler::LoadGlobalIC_TryHandlerCase(const LoadICParameters* pp,
p.receiver =
LoadContextElement(native_context, Context::GLOBAL_PROXY_INDEX);
Node* holder = LoadContextElement(native_context, Context::EXTENSION_INDEX);
HandleLoadICSmiHandlerCase(&p, holder, handler, miss, exit_point,
HandleLoadICSmiHandlerCase(&p, holder, handler, handler, miss, exit_point,
throw_reference_error_if_nonexistent,
kOnlyProperties);
}
......
......@@ -146,7 +146,7 @@ class AccessorAssembler : public CodeStubAssembler {
ElementSupport support_elements = kOnlyProperties);
void HandleLoadICSmiHandlerCase(const LoadICParameters* p, Node* holder,
Node* smi_handler, Label* miss,
Node* smi_handler, Node* handler, Label* miss,
ExitPoint* exit_point,
bool throw_reference_error_if_nonexistent,
ElementSupport support_elements);
......
......@@ -23,14 +23,15 @@ Handle<Smi> SetBitFieldValue(Isolate* isolate, Handle<Smi> smi_handler,
// TODO(ishell): Remove templatezation once we move common bits from
// Load/StoreHandler to the base class.
template <typename ICHandler, bool fill_array = true>
int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
Handle<JSReceiver> holder, Handle<Name> name,
Handle<ICHandler> handler,
Handle<Smi>* smi_handler = nullptr) {
if (!holder.is_null() && holder->map() == *receiver_map) return 0;
template <typename ICHandler, bool fill_handler = true>
int InitPrototypeChecksImpl(Isolate* isolate, Handle<ICHandler> handler,
Handle<Smi>* smi_handler, Handle<Map> receiver_map,
Handle<JSReceiver> holder, Handle<Object> data1,
MaybeHandle<Object> maybe_data2) {
int checks_count = 0;
// Holder-is-receiver case itself does not add entries unless there is an
// optional data2 value provided.
if (receiver_map->IsPrimitiveMap() ||
receiver_map->is_access_check_needed()) {
DCHECK(!receiver_map->IsJSGlobalObjectMap());
......@@ -40,7 +41,7 @@ int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
// be used in other native context through the megamorphic stub cache.
// So we record the original native context to which this handler
// corresponds.
if (fill_array) {
if (fill_handler) {
Handle<Context> native_context = isolate->native_context();
handler->set_data2(native_context->self_weak_cell());
} else {
......@@ -51,12 +52,29 @@ int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
checks_count++;
} else if (receiver_map->is_dictionary_map() &&
!receiver_map->IsJSGlobalObjectMap()) {
if (!fill_array) {
if (!fill_handler) {
// Enable lookup on receiver.
typedef typename ICHandler::LookupOnReceiverBits Bit;
*smi_handler = SetBitFieldValue<Bit>(isolate, *smi_handler, true);
}
}
if (fill_handler) {
handler->set_data1(*data1);
}
Handle<Object> data2;
if (maybe_data2.ToHandle(&data2)) {
if (fill_handler) {
// This value will go either to data2 or data3 slot depending on whether
// data2 slot is already occupied by native context.
if (checks_count == 0) {
handler->set_data2(*data2);
} else {
DCHECK_EQ(1, checks_count);
handler->set_data3(*data2);
}
}
checks_count++;
}
return checks_count;
}
......@@ -67,12 +85,23 @@ int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
// Returns -1 if the handler has to be compiled or the number of prototype
// checks otherwise.
template <typename ICHandler>
int GetPrototypeCheckCount(Isolate* isolate, Handle<Map> receiver_map,
Handle<JSReceiver> holder, Handle<Name> name,
Handle<Smi>* smi_handler) {
int GetPrototypeCheckCount(
Isolate* isolate, Handle<Smi>* smi_handler, Handle<Map> receiver_map,
Handle<JSReceiver> holder, Handle<Object> data1,
MaybeHandle<Object> maybe_data2 = MaybeHandle<Object>()) {
DCHECK_NOT_NULL(smi_handler);
return InitPrototypeChecks<ICHandler, false>(
isolate, receiver_map, holder, name, Handle<ICHandler>(), smi_handler);
return InitPrototypeChecksImpl<ICHandler, false>(isolate, Handle<ICHandler>(),
smi_handler, receiver_map,
holder, data1, maybe_data2);
}
template <typename ICHandler>
void InitPrototypeChecks(
Isolate* isolate, Handle<ICHandler> handler, Handle<Map> receiver_map,
Handle<JSReceiver> holder, Handle<Object> data1,
MaybeHandle<Object> maybe_data2 = MaybeHandle<Object>()) {
InitPrototypeChecksImpl<ICHandler, true>(
isolate, handler, nullptr, receiver_map, holder, data1, maybe_data2);
}
} // namespace
......@@ -81,28 +110,28 @@ int GetPrototypeCheckCount(Isolate* isolate, Handle<Map> receiver_map,
Handle<Object> LoadHandler::LoadFromPrototype(Isolate* isolate,
Handle<Map> receiver_map,
Handle<JSReceiver> holder,
Handle<Name> name,
Handle<Smi> smi_handler,
MaybeHandle<Object> maybe_data) {
MaybeHandle<Object> maybe_data1,
MaybeHandle<Object> maybe_data2) {
Handle<Object> data1;
if (!maybe_data1.ToHandle(&data1)) {
data1 = Map::GetOrCreatePrototypeWeakCell(holder, isolate);
}
int checks_count = GetPrototypeCheckCount<LoadHandler>(
isolate, receiver_map, holder, name, &smi_handler);
isolate, &smi_handler, receiver_map, holder, data1, maybe_data2);
Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
DCHECK(!validity_cell.is_null());
Handle<Object> data;
if (!maybe_data.ToHandle(&data)) {
data = Map::GetOrCreatePrototypeWeakCell(holder, isolate);
}
int data_count = 1 + checks_count;
Handle<LoadHandler> handler = isolate->factory()->NewLoadHandler(data_count);
handler->set_smi_handler(*smi_handler);
handler->set_validity_cell(*validity_cell);
handler->set_data1(*data);
InitPrototypeChecks(isolate, receiver_map, holder, name, handler);
InitPrototypeChecks(isolate, handler, receiver_map, holder, data1,
maybe_data2);
return handler;
}
......@@ -110,11 +139,11 @@ Handle<Object> LoadHandler::LoadFromPrototype(Isolate* isolate,
Handle<Object> LoadHandler::LoadFullChain(Isolate* isolate,
Handle<Map> receiver_map,
Handle<Object> holder,
Handle<Name> name,
Handle<Smi> smi_handler) {
Handle<JSReceiver> end; // null handle
Handle<JSReceiver> end; // null handle, means full prototype chain lookup.
Handle<Object> data1 = holder;
int checks_count = GetPrototypeCheckCount<LoadHandler>(
isolate, receiver_map, end, name, &smi_handler);
isolate, &smi_handler, receiver_map, end, data1);
Handle<Object> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
......@@ -130,8 +159,7 @@ Handle<Object> LoadHandler::LoadFullChain(Isolate* isolate,
handler->set_smi_handler(*smi_handler);
handler->set_validity_cell(*validity_cell);
handler->set_data1(*holder);
InitPrototypeChecks(isolate, receiver_map, end, name, handler);
InitPrototypeChecks(isolate, handler, receiver_map, end, data1);
return handler;
}
......@@ -199,10 +227,15 @@ Handle<Smi> StoreHandler::StoreTransition(Isolate* isolate,
// static
Handle<Object> StoreHandler::StoreThroughPrototype(
Isolate* isolate, Handle<Map> receiver_map, Handle<JSReceiver> holder,
Handle<Name> name, Handle<Smi> smi_handler,
MaybeHandle<Object> maybe_data) {
Handle<Smi> smi_handler, MaybeHandle<Object> maybe_data1,
MaybeHandle<Object> maybe_data2) {
Handle<Object> data1;
if (!maybe_data1.ToHandle(&data1)) {
data1 = Map::GetOrCreatePrototypeWeakCell(holder, isolate);
}
int checks_count = GetPrototypeCheckCount<StoreHandler>(
isolate, receiver_map, holder, name, &smi_handler);
isolate, &smi_handler, receiver_map, holder, data1, maybe_data2);
Handle<Object> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
......@@ -211,19 +244,14 @@ Handle<Object> StoreHandler::StoreThroughPrototype(
validity_cell = handle(Smi::kZero, isolate);
}
Handle<Object> data;
if (!maybe_data.ToHandle(&data)) {
data = Map::GetOrCreatePrototypeWeakCell(holder, isolate);
}
int data_count = 1 + checks_count;
Handle<StoreHandler> handler =
isolate->factory()->NewStoreHandler(data_count);
handler->set_smi_handler(*smi_handler);
handler->set_validity_cell(*validity_cell);
handler->set_data1(*data);
InitPrototypeChecks(isolate, receiver_map, holder, name, handler);
InitPrototypeChecks(isolate, handler, receiver_map, holder, data1,
maybe_data2);
return handler;
}
......@@ -237,12 +265,11 @@ Handle<Object> StoreHandler::StoreGlobal(Isolate* isolate,
Handle<Object> StoreHandler::StoreProxy(Isolate* isolate,
Handle<Map> receiver_map,
Handle<JSProxy> proxy,
Handle<JSReceiver> receiver,
Handle<Name> name) {
Handle<JSReceiver> receiver) {
Handle<Smi> smi_handler = StoreProxy(isolate);
if (receiver.is_identical_to(proxy)) return smi_handler;
Handle<WeakCell> holder_cell = isolate->factory()->NewWeakCell(proxy);
return StoreThroughPrototype(isolate, receiver_map, proxy, name, smi_handler,
return StoreThroughPrototype(isolate, receiver_map, proxy, smi_handler,
holder_cell);
}
......
......@@ -147,7 +147,7 @@ class LoadHandler final : public DataHandler {
// needed (e.g., for "nonexistent"), null_value() may be passed in.
static Handle<Object> LoadFullChain(Isolate* isolate,
Handle<Map> receiver_map,
Handle<Object> holder, Handle<Name> name,
Handle<Object> holder,
Handle<Smi> smi_handler);
// Creates a data handler that represents a prototype chain check followed
......@@ -155,8 +155,9 @@ class LoadHandler final : public DataHandler {
// Can be used only if GetPrototypeCheckCount() returns non negative value.
static Handle<Object> LoadFromPrototype(
Isolate* isolate, Handle<Map> receiver_map, Handle<JSReceiver> holder,
Handle<Name> name, Handle<Smi> smi_handler,
MaybeHandle<Object> maybe_data = MaybeHandle<Object>());
Handle<Smi> smi_handler,
MaybeHandle<Object> maybe_data1 = MaybeHandle<Object>(),
MaybeHandle<Object> maybe_data2 = MaybeHandle<Object>());
// Creates a Smi-handler for loading a non-existent property. Works only as
// a part of prototype chain check.
......@@ -272,8 +273,9 @@ class StoreHandler final : public DataHandler {
static Handle<Object> StoreThroughPrototype(
Isolate* isolate, Handle<Map> receiver_map, Handle<JSReceiver> holder,
Handle<Name> name, Handle<Smi> smi_handler,
MaybeHandle<Object> data = MaybeHandle<Object>());
Handle<Smi> smi_handler,
MaybeHandle<Object> maybe_data1 = MaybeHandle<Object>(),
MaybeHandle<Object> maybe_data2 = MaybeHandle<Object>());
static Handle<Object> StoreElementTransition(Isolate* isolate,
Handle<Map> receiver_map,
......@@ -282,8 +284,7 @@ class StoreHandler final : public DataHandler {
static Handle<Object> StoreProxy(Isolate* isolate, Handle<Map> receiver_map,
Handle<JSProxy> proxy,
Handle<JSReceiver> receiver,
Handle<Name> name);
Handle<JSReceiver> receiver);
// Creates a handler for storing a property to the property cell of a global
// object.
......
......@@ -669,7 +669,7 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) {
Handle<Smi> smi_handler = LoadHandler::LoadNonExistent(isolate());
code = LoadHandler::LoadFullChain(isolate(), receiver_map(),
isolate()->factory()->null_value(),
lookup->name(), smi_handler);
smi_handler);
} else {
if (IsLoadGlobalIC()) {
if (lookup->TryLookupCachedProperty()) {
......@@ -759,7 +759,7 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
}
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonMaskingInterceptorDH);
return LoadHandler::LoadFullChain(isolate(), map, holder_ref,
lookup->name(), smi_handler);
smi_handler);
}
if (receiver_is_holder) {
......@@ -770,7 +770,7 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadInterceptorFromPrototypeDH);
return LoadHandler::LoadFromPrototype(isolate(), map, holder,
lookup->name(), smi_handler);
smi_handler);
}
case LookupIterator::ACCESSOR: {
......@@ -836,12 +836,10 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
isolate()->factory()->NewWeakCell(context);
Handle<WeakCell> data_cell = isolate()->factory()->NewWeakCell(
call_optimization.api_call_info());
Handle<Tuple2> data =
isolate()->factory()->NewTuple2(context_cell, data_cell, TENURED);
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterFromPrototypeDH);
return LoadHandler::LoadFromPrototype(
isolate(), map, holder, lookup->name(), smi_handler, data);
isolate(), map, holder, smi_handler, data_cell, context_cell);
}
if (holder->HasFastProperties()) {
......@@ -856,8 +854,8 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
smi_handler = LoadHandler::LoadGlobal(isolate());
Handle<WeakCell> cell =
isolate()->factory()->NewWeakCell(lookup->GetPropertyCell());
return LoadHandler::LoadFromPrototype(
isolate(), map, holder, lookup->name(), smi_handler, cell);
return LoadHandler::LoadFromPrototype(isolate(), map, holder,
smi_handler, cell);
} else {
smi_handler = LoadHandler::LoadNormal(isolate());
......@@ -867,7 +865,7 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
}
return LoadHandler::LoadFromPrototype(isolate(), map, holder,
lookup->name(), smi_handler);
smi_handler);
}
Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
......@@ -887,7 +885,7 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
TRACE_HANDLER_STATS(isolate(),
LoadIC_LoadNativeDataPropertyFromPrototypeDH);
return LoadHandler::LoadFromPrototype(isolate(), map, holder,
lookup->name(), smi_handler);
smi_handler);
}
case LookupIterator::DATA: {
......@@ -901,8 +899,8 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
smi_handler = LoadHandler::LoadGlobal(isolate());
Handle<WeakCell> cell =
isolate()->factory()->NewWeakCell(lookup->GetPropertyCell());
return LoadHandler::LoadFromPrototype(
isolate(), map, holder, lookup->name(), smi_handler, cell);
return LoadHandler::LoadFromPrototype(isolate(), map, holder,
smi_handler, cell);
}
smi_handler = LoadHandler::LoadNormal(isolate());
......@@ -925,7 +923,7 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH);
}
return LoadHandler::LoadFromPrototype(isolate(), map, holder,
lookup->name(), smi_handler);
smi_handler);
}
case LookupIterator::INTEGER_INDEXED_EXOTIC:
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadIntegerIndexedExoticDH);
......@@ -938,7 +936,7 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
return smi_handler;
}
return LoadHandler::LoadFromPrototype(isolate(), map, holder_proxy,
lookup->name(), smi_handler);
smi_handler);
}
case LookupIterator::ACCESS_CHECK:
case LookupIterator::NOT_FOUND:
......@@ -1444,8 +1442,7 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
Handle<WeakCell> cell =
isolate()->factory()->NewWeakCell(lookup->transition_cell());
Handle<Object> handler = StoreHandler::StoreThroughPrototype(
isolate(), receiver_map(), store_target, lookup->name(),
smi_handler, cell);
isolate(), receiver_map(), store_target, smi_handler, cell);
return handler;
}
// Currently not handled by CompileStoreTransition.
......@@ -1469,7 +1466,7 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
Handle<WeakCell> cell = Map::WeakCellForMap(transition);
Handle<Object> handler = StoreHandler::StoreThroughPrototype(
isolate(), receiver_map(), holder, lookup->name(), smi_handler, cell);
isolate(), receiver_map(), holder, smi_handler, cell);
TransitionsAccessor(receiver_map())
.UpdateHandler(*lookup->name(), *handler);
return handler;
......@@ -1523,8 +1520,8 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
if (receiver.is_identical_to(holder)) return smi_handler;
TRACE_HANDLER_STATS(isolate(),
StoreIC_StoreNativeDataPropertyOnPrototypeDH);
return StoreHandler::StoreThroughPrototype(
isolate(), receiver_map(), holder, lookup->name(), smi_handler);
return StoreHandler::StoreThroughPrototype(isolate(), receiver_map(),
holder, smi_handler);
} else if (accessors->IsAccessorPair()) {
Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
......@@ -1551,12 +1548,10 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
isolate()->factory()->NewWeakCell(context);
Handle<WeakCell> data_cell = isolate()->factory()->NewWeakCell(
call_optimization.api_call_info());
Handle<Tuple2> data = isolate()->factory()->NewTuple2(
context_cell, data_cell, TENURED);
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreApiSetterOnPrototypeDH);
return StoreHandler::StoreThroughPrototype(
isolate(), receiver_map(), holder, lookup->name(), smi_handler,
data);
isolate(), receiver_map(), holder, smi_handler, data_cell,
context_cell);
}
TRACE_GENERIC_IC("incompatible receiver");
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
......@@ -1574,8 +1569,8 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
if (receiver.is_identical_to(holder)) return smi_handler;
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreAccessorOnPrototypeDH);
return StoreHandler::StoreThroughPrototype(
isolate(), receiver_map(), holder, lookup->name(), smi_handler);
return StoreHandler::StoreThroughPrototype(isolate(), receiver_map(),
holder, smi_handler);
}
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
return slow_stub();
......@@ -1626,7 +1621,7 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
Handle<JSReceiver>::cast(lookup->GetReceiver());
Handle<JSProxy> holder = lookup->GetHolder<JSProxy>();
return StoreHandler::StoreProxy(isolate(), receiver_map(), holder,
receiver, lookup->name());
receiver);
}
case LookupIterator::INTEGER_INDEXED_EXOTIC:
......
......@@ -1357,6 +1357,9 @@ void DataHandler::DataHandlerVerify() {
if (data_count >= 2) {
VerifyObjectField(kData2Offset);
}
if (data_count >= 3) {
VerifyObjectField(kData3Offset);
}
}
void LoadHandler::LoadHandlerVerify() {
......
......@@ -1459,6 +1459,9 @@ void LoadHandler::LoadHandlerPrint(std::ostream& os) { // NOLINT
if (data_count >= 2) {
os << "\n - data2: " << Brief(data2());
}
if (data_count >= 3) {
os << "\n - data3: " << Brief(data3());
}
os << "\n";
}
......@@ -1474,6 +1477,9 @@ void StoreHandler::StoreHandlerPrint(std::ostream& os) { // NOLINT
if (data_count >= 2) {
os << "\n - data2: " << Brief(data2());
}
if (data_count >= 3) {
os << "\n - data3: " << Brief(data3());
}
os << "\n";
}
......
......@@ -560,9 +560,11 @@ 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(LOAD_HANDLER, LoadHandler, 3, load_handler3) \
V(STORE_HANDLER, StoreHandler, 0, store_handler0) \
V(STORE_HANDLER, StoreHandler, 1, store_handler1) \
V(STORE_HANDLER, StoreHandler, 2, store_handler2)
V(STORE_HANDLER, StoreHandler, 2, store_handler2) \
V(STORE_HANDLER, StoreHandler, 3, store_handler3)
// We use the full 16 bits of the instance_type field to encode heap object
// instance types. All the high-order bits (bit 7-15) are cleared if the object
......
......@@ -30,6 +30,8 @@ ACCESSORS_CHECKED(DataHandler, data1, Object, kData1Offset,
map()->instance_size() >= kSizeWithData1)
ACCESSORS_CHECKED(DataHandler, data2, Object, kData2Offset,
map()->instance_size() >= kSizeWithData2)
ACCESSORS_CHECKED(DataHandler, data3, Object, kData3Offset,
map()->instance_size() >= kSizeWithData3)
} // namespace internal
} // namespace v8
......
......@@ -29,10 +29,11 @@ class DataHandler : public Struct {
// 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-3]: These are optional general-purpose fields whose content and
// presence depends on the handler kind.
DECL_ACCESSORS(data1, Object)
DECL_ACCESSORS(data2, Object)
DECL_ACCESSORS(data3, Object)
// Layout description.
#define DATA_HANDLER_FIELDS(V) \
......@@ -42,7 +43,9 @@ class DataHandler : public Struct {
V(kData1Offset, kPointerSize) \
V(kSizeWithData1, 0) \
V(kData2Offset, kPointerSize) \
V(kSizeWithData2, 0)
V(kSizeWithData2, 0) \
V(kData3Offset, kPointerSize) \
V(kSizeWithData3, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, DATA_HANDLER_FIELDS)
#undef DATA_HANDLER_FIELDS
......
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