| Index: src/ic/ic.cc
|
| diff --git a/src/ic/ic.cc b/src/ic/ic.cc
|
| index 28070b84dae9b7fb39392de7d0b0b77050162b38..d46388faf9983f4bc8923566eae51e5d22a167f3 100644
|
| --- a/src/ic/ic.cc
|
| +++ b/src/ic/ic.cc
|
| @@ -855,8 +855,8 @@ namespace {
|
|
|
| template <bool fill_array = true>
|
| int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
|
| - Handle<JSObject> holder, Handle<FixedArray> array,
|
| - Handle<Name> name, int first_index) {
|
| + Handle<JSObject> holder, Handle<Name> name,
|
| + Handle<FixedArray> array, int first_index) {
|
| DCHECK(holder.is_null() || holder->HasFastProperties());
|
|
|
| // We don't encode the requirement to check access rights because we already
|
| @@ -894,7 +894,11 @@ int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
|
|
|
| // Create/count entries for each global or dictionary prototype appeared in
|
| // the prototype chain contains from receiver till holder.
|
| - for (PrototypeIterator iter(receiver_map); !iter.IsAtEnd(); iter.Advance()) {
|
| + PrototypeIterator::WhereToEnd end = name->IsPrivate()
|
| + ? PrototypeIterator::END_AT_NON_HIDDEN
|
| + : PrototypeIterator::END_AT_NULL;
|
| + for (PrototypeIterator iter(receiver_map, end); !iter.IsAtEnd();
|
| + iter.Advance()) {
|
| Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
|
| if (holder.is_identical_to(current)) break;
|
| Handle<Map> current_map(current->map(), isolate);
|
| @@ -932,9 +936,9 @@ int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
|
| // Returns -1 if the handler has to be compiled or the number of prototype
|
| // checks otherwise.
|
| int GetPrototypeCheckCount(Isolate* isolate, Handle<Map> receiver_map,
|
| - Handle<JSObject> holder) {
|
| - return InitPrototypeChecks<false>(isolate, receiver_map, holder,
|
| - Handle<FixedArray>(), Handle<Name>(), 0);
|
| + Handle<JSObject> holder, Handle<Name> name) {
|
| + return InitPrototypeChecks<false>(isolate, receiver_map, holder, name,
|
| + Handle<FixedArray>(), 0);
|
| }
|
|
|
| } // namespace
|
| @@ -943,7 +947,8 @@ Handle<Object> LoadIC::LoadFromPrototype(Handle<Map> receiver_map,
|
| Handle<JSObject> holder,
|
| Handle<Name> name,
|
| Handle<Object> smi_handler) {
|
| - int checks_count = GetPrototypeCheckCount(isolate(), receiver_map, holder);
|
| + int checks_count =
|
| + GetPrototypeCheckCount(isolate(), receiver_map, holder, name);
|
| DCHECK_LE(0, checks_count);
|
|
|
| if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) {
|
| @@ -973,7 +978,7 @@ Handle<Object> LoadIC::LoadFromPrototype(Handle<Map> receiver_map,
|
| handler_array->set(LoadHandler::kSmiHandlerIndex, *smi_handler);
|
| handler_array->set(LoadHandler::kValidityCellIndex, *validity_cell);
|
| handler_array->set(LoadHandler::kHolderCellIndex, *holder_cell);
|
| - InitPrototypeChecks(isolate(), receiver_map, holder, handler_array, name,
|
| + InitPrototypeChecks(isolate(), receiver_map, holder, name, handler_array,
|
| LoadHandler::kFirstPrototypeIndex);
|
| return handler_array;
|
| }
|
| @@ -981,7 +986,8 @@ Handle<Object> LoadIC::LoadFromPrototype(Handle<Map> receiver_map,
|
| Handle<Object> LoadIC::LoadNonExistent(Handle<Map> receiver_map,
|
| Handle<Name> name) {
|
| Handle<JSObject> holder; // null handle
|
| - int checks_count = GetPrototypeCheckCount(isolate(), receiver_map, holder);
|
| + int checks_count =
|
| + GetPrototypeCheckCount(isolate(), receiver_map, holder, name);
|
| DCHECK_LE(0, checks_count);
|
|
|
| bool do_negative_lookup_on_receiver =
|
| @@ -999,9 +1005,6 @@ Handle<Object> LoadIC::LoadNonExistent(Handle<Map> receiver_map,
|
| Handle<Object> validity_cell =
|
| Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
|
| if (validity_cell.is_null()) {
|
| - // This must be a case when receiver's prototype is null.
|
| - DCHECK_EQ(*isolate()->factory()->null_value(),
|
| - receiver_map->GetPrototypeChainRootMap(isolate())->prototype());
|
| DCHECK_EQ(0, checks_count);
|
| validity_cell = handle(Smi::FromInt(0), isolate());
|
| }
|
| @@ -1016,7 +1019,7 @@ Handle<Object> LoadIC::LoadNonExistent(Handle<Map> receiver_map,
|
| handler_array->set(LoadHandler::kSmiHandlerIndex, *smi_handler);
|
| handler_array->set(LoadHandler::kValidityCellIndex, *validity_cell);
|
| handler_array->set(LoadHandler::kHolderCellIndex, *factory->null_value());
|
| - InitPrototypeChecks(isolate(), receiver_map, holder, handler_array, name,
|
| + InitPrototypeChecks(isolate(), receiver_map, holder, name, handler_array,
|
| LoadHandler::kFirstPrototypeIndex);
|
| return handler_array;
|
| }
|
| @@ -1893,17 +1896,20 @@ Handle<Object> StoreIC::StoreTransition(Handle<Map> receiver_map,
|
| smi_handler = StoreHandler::TransitionToField(
|
| isolate(), descriptor, index, representation, extend_storage);
|
| }
|
| + // |holder| is either a receiver if the property is non-existent or
|
| + // one of the prototypes.
|
| + DCHECK(!holder.is_null());
|
| + bool is_nonexistent = holder->map() == transition->GetBackPointer();
|
| + if (is_nonexistent) holder = Handle<JSObject>::null();
|
|
|
| - int checks_count = GetPrototypeCheckCount(isolate(), receiver_map, holder);
|
| + int checks_count =
|
| + GetPrototypeCheckCount(isolate(), receiver_map, holder, name);
|
| DCHECK_LE(0, checks_count);
|
| DCHECK(!receiver_map->IsJSGlobalObjectMap());
|
|
|
| Handle<Object> validity_cell =
|
| Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
|
| if (validity_cell.is_null()) {
|
| - // This must be a case when receiver's prototype is null.
|
| - DCHECK_EQ(*isolate()->factory()->null_value(),
|
| - receiver_map->GetPrototypeChainRootMap(isolate())->prototype());
|
| DCHECK_EQ(0, checks_count);
|
| validity_cell = handle(Smi::FromInt(0), isolate());
|
| }
|
| @@ -1919,7 +1925,7 @@ Handle<Object> StoreIC::StoreTransition(Handle<Map> receiver_map,
|
| handler_array->set(StoreHandler::kSmiHandlerIndex, *smi_handler);
|
| handler_array->set(StoreHandler::kValidityCellIndex, *validity_cell);
|
| handler_array->set(StoreHandler::kTransitionCellIndex, *transition_cell);
|
| - InitPrototypeChecks(isolate(), receiver_map, holder, handler_array, name,
|
| + InitPrototypeChecks(isolate(), receiver_map, holder, name, handler_array,
|
| StoreHandler::kFirstPrototypeIndex);
|
| return handler_array;
|
| }
|
|
|