78ef2e5b29
BUG=chromium:505998 LOG=n Review URL: https://codereview.chromium.org/1222543003 Cr-Commit-Position: refs/heads/master@{#29419}
142 lines
4.8 KiB
C++
142 lines
4.8 KiB
C++
// Copyright 2014 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef V8_LOOKUP_INL_H_
|
|
#define V8_LOOKUP_INL_H_
|
|
|
|
#include "src/lookup.h"
|
|
|
|
#include "src/elements.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
|
|
|
|
JSReceiver* LookupIterator::NextHolder(Map* map) {
|
|
DisallowHeapAllocation no_gc;
|
|
if (!map->prototype()->IsJSReceiver()) return NULL;
|
|
|
|
JSReceiver* next = JSReceiver::cast(map->prototype());
|
|
DCHECK(!next->map()->IsGlobalObjectMap() ||
|
|
next->map()->is_hidden_prototype());
|
|
|
|
if (!check_prototype_chain() &&
|
|
!(check_hidden() && next->map()->is_hidden_prototype()) &&
|
|
// Always lookup behind the JSGlobalProxy into the JSGlobalObject, even
|
|
// when not checking other hidden prototypes.
|
|
!map->IsJSGlobalProxyMap()) {
|
|
return NULL;
|
|
}
|
|
|
|
return next;
|
|
}
|
|
|
|
|
|
LookupIterator::State LookupIterator::LookupInHolder(Map* const map,
|
|
JSReceiver* const holder) {
|
|
STATIC_ASSERT(INTERCEPTOR == BEFORE_PROPERTY);
|
|
DisallowHeapAllocation no_gc;
|
|
if (interceptor_state_ == InterceptorState::kProcessNonMasking) {
|
|
return LookupNonMaskingInterceptorInHolder(map, holder);
|
|
}
|
|
switch (state_) {
|
|
case NOT_FOUND:
|
|
if (map->IsJSProxyMap()) return JSPROXY;
|
|
if (map->is_access_check_needed() &&
|
|
(IsElement() || !isolate_->IsInternallyUsedPropertyName(name_))) {
|
|
return ACCESS_CHECK;
|
|
}
|
|
// Fall through.
|
|
case ACCESS_CHECK:
|
|
if (exotic_index_state_ != ExoticIndexState::kNotExotic &&
|
|
IsIntegerIndexedExotic(holder)) {
|
|
return INTEGER_INDEXED_EXOTIC;
|
|
}
|
|
if (check_interceptor() && HasInterceptor(map) &&
|
|
!SkipInterceptor(JSObject::cast(holder))) {
|
|
return INTERCEPTOR;
|
|
}
|
|
// Fall through.
|
|
case INTERCEPTOR:
|
|
if (IsElement()) {
|
|
// TODO(verwaest): Optimize.
|
|
if (holder->IsStringObjectWithCharacterAt(index_)) {
|
|
PropertyAttributes attributes =
|
|
static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
|
|
property_details_ = PropertyDetails(attributes, v8::internal::DATA, 0,
|
|
PropertyCellType::kNoCell);
|
|
} else {
|
|
JSObject* js_object = JSObject::cast(holder);
|
|
if (js_object->elements() == isolate()->heap()->empty_fixed_array()) {
|
|
return NOT_FOUND;
|
|
}
|
|
|
|
ElementsAccessor* accessor = js_object->GetElementsAccessor();
|
|
FixedArrayBase* backing_store = js_object->elements();
|
|
number_ = accessor->GetIndexForKey(js_object, backing_store, index_);
|
|
if (number_ == kMaxUInt32) return NOT_FOUND;
|
|
property_details_ = accessor->GetDetails(backing_store, number_);
|
|
}
|
|
} else if (!map->is_dictionary_map()) {
|
|
DescriptorArray* descriptors = map->instance_descriptors();
|
|
int number = descriptors->SearchWithCache(*name_, map);
|
|
if (number == DescriptorArray::kNotFound) return NOT_FOUND;
|
|
number_ = static_cast<uint32_t>(number);
|
|
property_details_ = descriptors->GetDetails(number_);
|
|
} else if (map->IsGlobalObjectMap()) {
|
|
GlobalDictionary* dict = JSObject::cast(holder)->global_dictionary();
|
|
int number = dict->FindEntry(name_);
|
|
if (number == GlobalDictionary::kNotFound) return NOT_FOUND;
|
|
number_ = static_cast<uint32_t>(number);
|
|
DCHECK(dict->ValueAt(number_)->IsPropertyCell());
|
|
PropertyCell* cell = PropertyCell::cast(dict->ValueAt(number_));
|
|
if (cell->value()->IsTheHole()) return NOT_FOUND;
|
|
property_details_ = cell->property_details();
|
|
} else {
|
|
NameDictionary* dict = JSObject::cast(holder)->property_dictionary();
|
|
int number = dict->FindEntry(name_);
|
|
if (number == NameDictionary::kNotFound) return NOT_FOUND;
|
|
number_ = static_cast<uint32_t>(number);
|
|
property_details_ = dict->DetailsAt(number_);
|
|
}
|
|
has_property_ = true;
|
|
switch (property_details_.kind()) {
|
|
case v8::internal::kData:
|
|
return DATA;
|
|
case v8::internal::kAccessor:
|
|
return ACCESSOR;
|
|
}
|
|
case ACCESSOR:
|
|
case DATA:
|
|
return NOT_FOUND;
|
|
case INTEGER_INDEXED_EXOTIC:
|
|
case JSPROXY:
|
|
case TRANSITION:
|
|
UNREACHABLE();
|
|
}
|
|
UNREACHABLE();
|
|
return state_;
|
|
}
|
|
|
|
|
|
LookupIterator::State LookupIterator::LookupNonMaskingInterceptorInHolder(
|
|
Map* const map, JSReceiver* const holder) {
|
|
switch (state_) {
|
|
case NOT_FOUND:
|
|
if (check_interceptor() && HasInterceptor(map) &&
|
|
!SkipInterceptor(JSObject::cast(holder))) {
|
|
return INTERCEPTOR;
|
|
}
|
|
// Fall through.
|
|
default:
|
|
return NOT_FOUND;
|
|
}
|
|
UNREACHABLE();
|
|
return state_;
|
|
}
|
|
}
|
|
} // namespace v8::internal
|
|
|
|
#endif // V8_LOOKUP_INL_H_
|