summaryrefslogtreecommitdiff
path: root/deps/v8/src/lookup.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/lookup.cc')
-rw-r--r--deps/v8/src/lookup.cc183
1 files changed, 171 insertions, 12 deletions
diff --git a/deps/v8/src/lookup.cc b/deps/v8/src/lookup.cc
index 809c35e4a5..f60563b19e 100644
--- a/deps/v8/src/lookup.cc
+++ b/deps/v8/src/lookup.cc
@@ -6,13 +6,45 @@
#include "src/bootstrapper.h"
#include "src/deoptimizer.h"
+#include "src/elements.h"
#include "src/isolate-inl.h"
-#include "src/lookup-inl.h"
namespace v8 {
namespace internal {
+// static
+LookupIterator LookupIterator::PropertyOrElement(Isolate* isolate,
+ Handle<Object> receiver,
+ Handle<Object> key,
+ bool* success,
+ Configuration configuration) {
+ uint32_t index = 0;
+ if (key->ToArrayIndex(&index)) {
+ *success = true;
+ return LookupIterator(isolate, receiver, index, configuration);
+ }
+
+ Handle<Name> name;
+ *success = Object::ToName(isolate, key).ToHandle(&name);
+ if (!*success) {
+ DCHECK(isolate->has_pending_exception());
+ // Return an unusable dummy.
+ return LookupIterator(receiver, isolate->factory()->empty_string());
+ }
+
+ if (name->AsArrayIndex(&index)) {
+ LookupIterator it(isolate, receiver, index, configuration);
+ // Here we try to avoid having to rebuild the string later
+ // by storing it on the indexed LookupIterator.
+ it.name_ = name;
+ return it;
+ }
+
+ return LookupIterator(receiver, name, configuration);
+}
+
+
void LookupIterator::Next() {
DCHECK_NE(JSPROXY, state_);
DCHECK_NE(TRANSITION, state_);
@@ -48,13 +80,13 @@ void LookupIterator::Next() {
}
-void LookupIterator::RestartLookupForNonMaskingInterceptors() {
- interceptor_state_ = InterceptorState::kProcessNonMasking;
+void LookupIterator::RestartInternal(InterceptorState interceptor_state) {
state_ = NOT_FOUND;
+ interceptor_state_ = interceptor_state;
property_details_ = PropertyDetails::Empty();
- number_ = DescriptorArray::kNotFound;
holder_ = initial_holder_;
holder_map_ = handle(holder_->map(), isolate_);
+ number_ = DescriptorArray::kNotFound;
Next();
}
@@ -102,7 +134,8 @@ Handle<JSObject> LookupIterator::GetStoreTarget() const {
bool LookupIterator::HasAccess() const {
DCHECK_EQ(ACCESS_CHECK, state_);
- return isolate_->MayAccess(GetHolder<JSObject>());
+ return isolate_->MayAccess(handle(isolate_->context()),
+ GetHolder<JSObject>());
}
@@ -212,11 +245,11 @@ void LookupIterator::PrepareTransitionToDataProperty(
state_ = TRANSITION;
transition_ = transition;
- if (receiver->IsGlobalObject()) {
+ if (receiver->IsJSGlobalObject()) {
// Install a property cell.
InternalizeName();
- auto cell = GlobalObject::EnsurePropertyCell(
- Handle<GlobalObject>::cast(receiver), name());
+ auto cell = JSGlobalObject::EnsurePropertyCell(
+ Handle<JSGlobalObject>::cast(receiver), name());
DCHECK(cell->value()->IsTheHole());
transition_ = cell;
} else if (!transition->is_dictionary_map()) {
@@ -230,7 +263,7 @@ void LookupIterator::ApplyTransitionToDataProperty() {
DCHECK_EQ(TRANSITION, state_);
Handle<JSObject> receiver = GetStoreTarget();
- if (receiver->IsGlobalObject()) return;
+ if (receiver->IsJSGlobalObject()) return;
holder_ = receiver;
holder_map_ = transition_map();
JSObject::MigrateToMap(receiver, holder_map_);
@@ -394,7 +427,7 @@ Handle<Object> LookupIterator::FetchValue() const {
ElementsAccessor* accessor = holder->GetElementsAccessor();
return accessor->Get(handle(holder->elements()), number_);
- } else if (holder_map_->IsGlobalObjectMap()) {
+ } else if (holder_map_->IsJSGlobalObjectMap()) {
result = holder->global_dictionary()->ValueAt(number_);
DCHECK(result->IsPropertyCell());
result = PropertyCell::cast(result)->value();
@@ -453,7 +486,7 @@ Handle<HeapType> LookupIterator::GetFieldType() const {
Handle<PropertyCell> LookupIterator::GetPropertyCell() const {
DCHECK(!IsElement());
Handle<JSObject> holder = GetHolder<JSObject>();
- Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
+ Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(holder);
Object* value = global->global_dictionary()->ValueAt(dictionary_entry());
DCHECK(value->IsPropertyCell());
return handle(PropertyCell::cast(value));
@@ -479,7 +512,7 @@ void LookupIterator::WriteDataValue(Handle<Object> value) {
if (IsElement()) {
ElementsAccessor* accessor = holder->GetElementsAccessor();
accessor->Set(holder->elements(), number_, *value);
- } else if (holder->IsGlobalObject()) {
+ } else if (holder->IsJSGlobalObject()) {
Handle<GlobalDictionary> property_dictionary =
handle(holder->global_dictionary());
PropertyCell::UpdateCell(property_dictionary, dictionary_entry(), value,
@@ -561,5 +594,131 @@ bool LookupIterator::SkipInterceptor(JSObject* holder) {
}
return interceptor_state_ == InterceptorState::kProcessNonMasking;
}
+
+
+JSReceiver* LookupIterator::NextHolder(Map* map) {
+ DisallowHeapAllocation no_gc;
+ if (!map->prototype()->IsJSReceiver()) return NULL;
+
+ JSReceiver* next = JSReceiver::cast(map->prototype());
+ DCHECK(!next->map()->IsJSGlobalObjectMap() ||
+ 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->GetEntryForIndex(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->IsJSGlobalObjectMap()) {
+ 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 internal
} // namespace v8