[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); Node* handler_flags = SmiUntag(smi_handler);
Label check_prototypes(this); Label check_prototypes(this);
GotoIfNot( GotoIfNot(IsSetWord<LoadHandler::LookupOnReceiverBits>(handler_flags),
IsSetWord<LoadHandler::DoNegativeLookupOnReceiverBits>(handler_flags), &check_prototypes);
&check_prototypes);
{ {
CSA_ASSERT(this, Word32BinaryNot( CSA_ASSERT(this, Word32BinaryNot(
HasInstanceType(p->receiver, JS_GLOBAL_OBJECT_TYPE))); HasInstanceType(p->receiver, JS_GLOBAL_OBJECT_TYPE)));
// We have a dictionary receiver, do a negative lookup check. Node* properties = LoadProperties(p->receiver);
NameDictionaryNegativeLookup(p->receiver, p->name, miss); Variable var_name_index(this, MachineType::PointerRepresentation());
Goto(&check_prototypes); 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); Bind(&check_prototypes);

View File

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

View File

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