[ic] Deal with lookup result immediately when we find a property on a dictionary receiver

BUG=v8:6039

Change-Id: I69bae9ed49d91b0bc67a8e66e469d57ea7799cca
Reviewed-on: https://chromium-review.googlesource.com/449793
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43584}
This commit is contained in:
Toon Verwaest 2017-03-03 11:58:02 +01:00 committed by Commit Bot
parent eb36a7dbcf
commit 6a0acc135e
4 changed files with 37 additions and 27 deletions

View File

@ -368,15 +368,26 @@ void AccessorAssembler::HandleLoadICProtoHandlerCase(
Node* handler_flags = SmiUntag(smi_handler);
Label check_prototypes(this);
GotoIfNot(
IsSetWord<LoadHandler::DoNegativeLookupOnReceiverBits>(handler_flags),
&check_prototypes);
GotoIfNot(IsSetWord<LoadHandler::LookupOnReceiverBits>(handler_flags),
&check_prototypes);
{
CSA_ASSERT(this, Word32BinaryNot(
HasInstanceType(p->receiver, JS_GLOBAL_OBJECT_TYPE)));
// We have a dictionary receiver, do a negative lookup check.
NameDictionaryNegativeLookup(p->receiver, p->name, miss);
Goto(&check_prototypes);
Node* properties = LoadProperties(p->receiver);
Variable var_name_index(this, MachineType::PointerRepresentation());
Label found(this, &var_name_index);
NameDictionaryLookup<NameDictionary>(properties, p->name, &found,
&var_name_index, &check_prototypes);
Bind(&found);
{
Variable var_details(this, MachineRepresentation::kWord32);
Variable var_value(this, MachineRepresentation::kTagged);
LoadPropertyFromNameDictionary(properties, var_name_index.value(),
&var_details, &var_value);
Node* value = CallGetterIfAccessor(var_value.value(), var_details.value(),
p->context, p->receiver, miss);
exit_point->Return(value);
}
}
Bind(&check_prototypes);

View File

@ -52,22 +52,21 @@ Handle<Object> LoadHandler::EnableAccessCheckOnReceiver(
return handle(Smi::FromInt(config), isolate);
}
Handle<Object> LoadHandler::EnableNegativeLookupOnReceiver(
Isolate* isolate, Handle<Object> smi_handler) {
Handle<Object> LoadHandler::EnableLookupOnReceiver(Isolate* isolate,
Handle<Object> smi_handler) {
int config = Smi::cast(*smi_handler)->value();
#ifdef DEBUG
Kind kind = KindBits::decode(config);
DCHECK_NE(kForElements, kind);
#endif
config = DoNegativeLookupOnReceiverBits::update(config, true);
config = LookupOnReceiverBits::update(config, true);
return handle(Smi::FromInt(config), isolate);
}
Handle<Object> LoadHandler::LoadNonExistent(
Isolate* isolate, bool do_negative_lookup_on_receiver) {
int config =
KindBits::encode(kForNonExistent) |
DoNegativeLookupOnReceiverBits::encode(do_negative_lookup_on_receiver);
Handle<Object> LoadHandler::LoadNonExistent(Isolate* isolate,
bool do_lookup_on_receiver) {
int config = KindBits::encode(kForNonExistent) |
LookupOnReceiverBits::encode(do_lookup_on_receiver);
return handle(Smi::FromInt(config), isolate);
}

View File

@ -31,10 +31,11 @@ class LoadHandler {
class DoAccessCheckOnReceiverBits
: public BitField<bool, KindBits::kNext, 1> {};
// Defines whether negative lookup check should be done on receiver object.
// Applicable to kForFields, kForConstants and kForNonExistent kinds only when
// loading value from prototype chain. Ignored when loading from holder.
class DoNegativeLookupOnReceiverBits
// Defines whether a lookup should be done on receiver object before
// proceeding to the prototype chain. Applicable to kForFields, kForConstants
// and kForNonExistent kinds only when loading value from prototype chain.
// Ignored when loading from holder.
class LookupOnReceiverBits
: public BitField<bool, DoAccessCheckOnReceiverBits::kNext, 1> {};
//
@ -42,7 +43,7 @@ class LoadHandler {
//
class IsAccessorInfoBits
: public BitField<bool, DoNegativeLookupOnReceiverBits::kNext, 1> {};
: public BitField<bool, LookupOnReceiverBits::kNext, 1> {};
// Index of a value entry in the descriptor array.
class DescriptorBits : public BitField<unsigned, IsAccessorInfoBits::kNext,
kDescriptorIndexBitCount> {};
@ -52,8 +53,8 @@ class LoadHandler {
//
// Encoding when KindBits contains kForFields.
//
class IsInobjectBits
: public BitField<bool, DoNegativeLookupOnReceiverBits::kNext, 1> {};
class IsInobjectBits : public BitField<bool, LookupOnReceiverBits::kNext, 1> {
};
class IsDoubleBits : public BitField<bool, IsInobjectBits::kNext, 1> {};
// +1 here is to cover all possible JSObject header sizes.
class FieldOffsetBits
@ -105,15 +106,15 @@ class LoadHandler {
static inline Handle<Object> EnableAccessCheckOnReceiver(
Isolate* isolate, Handle<Object> smi_handler);
// Sets DoNegativeLookupOnReceiverBits in given Smi-handler. The receiver
// Sets LookupOnReceiverBits in given Smi-handler. The receiver
// check is a part of a prototype chain check.
static inline Handle<Object> EnableNegativeLookupOnReceiver(
static inline Handle<Object> EnableLookupOnReceiver(
Isolate* isolate, Handle<Object> smi_handler);
// Creates a Smi-handler for loading a non-existent property. Works only as
// a part of prototype chain check.
static inline Handle<Object> LoadNonExistent(
Isolate* isolate, bool do_negative_lookup_on_receiver);
static inline Handle<Object> LoadNonExistent(Isolate* isolate,
bool do_lookup_on_receiver);
// Creates a Smi-handler for loading an element.
static inline Handle<Object> LoadElement(Isolate* isolate,

View File

@ -979,8 +979,7 @@ Handle<Object> LoadIC::LoadFromPrototype(Handle<Map> receiver_map,
LoadHandler::EnableAccessCheckOnReceiver(isolate(), smi_handler);
} else if (receiver_map->is_dictionary_map() &&
!receiver_map->IsJSGlobalObjectMap()) {
smi_handler =
LoadHandler::EnableNegativeLookupOnReceiver(isolate(), smi_handler);
smi_handler = LoadHandler::EnableLookupOnReceiver(isolate(), smi_handler);
}
Handle<Cell> validity_cell =