Index: src/lookup.cc |
diff --git a/src/lookup.cc b/src/lookup.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..17a8ed0ed718c0b3d032f24334929a48511c4cd0 |
--- /dev/null |
+++ b/src/lookup.cc |
@@ -0,0 +1,202 @@ |
+// 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. |
+ |
+#include "src/v8.h" |
+ |
+#include "src/bootstrapper.h" |
+#include "src/lookup.h" |
+ |
+namespace v8 { |
+namespace internal { |
+ |
+ |
+void LookupIterator::Next() { |
+ has_property_ = false; |
+ do { |
+ LookupInHolder(); |
+ } while (!IsFound() && NextHolder()); |
+} |
+ |
+ |
+Handle<JSReceiver> LookupIterator::GetOrigin() const { |
+ Handle<Object> receiver = GetReceiver(); |
+ if (receiver->IsJSReceiver()) return Handle<JSReceiver>::cast(receiver); |
+ Context* native_context = isolate_->context()->native_context(); |
+ JSFunction* function; |
+ if (receiver->IsNumber()) { |
+ function = native_context->number_function(); |
+ } else if (receiver->IsString()) { |
+ function = native_context->string_function(); |
+ } else if (receiver->IsSymbol()) { |
+ function = native_context->symbol_function(); |
+ } else if (receiver->IsBoolean()) { |
+ function = native_context->boolean_function(); |
+ } else { |
+ UNREACHABLE(); |
+ function = NULL; |
+ } |
+ return handle(JSReceiver::cast(function->instance_prototype())); |
+} |
+ |
+ |
+Handle<Map> LookupIterator::GetReceiverMap() const { |
+ Handle<Object> receiver = GetReceiver(); |
+ if (receiver->IsNumber()) return isolate_->factory()->heap_number_map(); |
+ return handle(Handle<HeapObject>::cast(receiver)->map()); |
+} |
+ |
+ |
+bool LookupIterator::NextHolder() { |
+ if (holder_map_->prototype()->IsNull()) return false; |
+ |
+ Handle<JSReceiver> next(JSReceiver::cast(holder_map_->prototype())); |
+ |
+ if (!check_derived() && |
+ // TODO(verwaest): Check if this is actually necessary currently. If it |
+ // is, this should be handled by setting is_hidden_prototype on the |
+ // global object behind the proxy. |
+ !holder_map_->IsJSGlobalProxyMap() && |
+ !next->map()->is_hidden_prototype()) { |
+ return false; |
+ } |
+ |
+ holder_map_ = handle(next->map()); |
+ maybe_holder_ = next; |
+ return true; |
+} |
+ |
+ |
+void LookupIterator::LookupInHolder() { |
+ State old_state = state_; |
+ state_ = NOT_FOUND; |
rossberg
2014/06/11 15:37:00
Might be clearer to not pre-default this. There ar
Toon Verwaest
2014/06/11 17:32:18
Done.
|
+ switch (old_state) { |
+ case NOT_FOUND: |
+ if (holder_map_->IsJSProxyMap()) { |
+ state_ = JSPROXY; |
+ return; |
+ } |
+ if (check_access_check() && holder_map_->is_access_check_needed()) { |
+ state_ = ACCESS_CHECK; |
+ return; |
+ } |
rossberg
2014/06/11 15:37:00
Put a fall-through comment here and below.
Toon Verwaest
2014/06/11 17:32:18
Done.
|
+ case ACCESS_CHECK: |
+ if (check_interceptor() && holder_map_->has_named_interceptor()) { |
+ state_ = INTERCEPTOR; |
+ return; |
+ } |
+ case INTERCEPTOR: |
+ if (holder_map_->is_dictionary_map()) { |
+ property_encoding_ = DICTIONARY; |
+ } else { |
+ DescriptorArray* descriptors = holder_map_->instance_descriptors(); |
+ number_ = descriptors->SearchWithCache(*name_, *holder_map_); |
+ if (number_ == DescriptorArray::kNotFound) return; |
+ property_encoding_ = DESCRIPTOR; |
+ } |
+ state_ = PROPERTY; |
+ case PROPERTY: |
+ return; |
+ case JSPROXY: |
+ UNREACHABLE(); |
+ } |
+} |
+ |
+ |
+bool LookupIterator::IsBootstrapping() const { |
+ return isolate_->bootstrapper()->IsActive(); |
+} |
+ |
+ |
+bool LookupIterator::HasAccess(v8::AccessType access_type) const { |
+ ASSERT_EQ(ACCESS_CHECK, state_); |
+ ASSERT(is_guaranteed_to_have_holder()); |
+ return isolate_->MayNamedAccess(GetHolder(), name_, access_type); |
+} |
+ |
+ |
+bool LookupIterator::HasProperty() { |
+ ASSERT_EQ(PROPERTY, state_); |
+ ASSERT(is_guaranteed_to_have_holder()); |
+ |
+ if (property_encoding_ == DICTIONARY) { |
+ Handle<JSObject> holder = GetHolder(); |
+ number_ = holder->property_dictionary()->FindEntry(name_); |
+ if (number_ == NameDictionary::kNotFound) return false; |
+ |
+ property_details_ = GetHolder()->property_dictionary()->DetailsAt(number_); |
+ // Holes in dictionary cells are absent values unless marked as read-only. |
+ if (holder->IsGlobalObject() && |
+ (property_details_.IsDeleted() || |
+ (!property_details_.IsReadOnly() && FetchValue()->IsTheHole()))) { |
+ return false; |
+ } |
+ } else { |
+ property_details_ = holder_map_->instance_descriptors()->GetDetails( |
+ number_); |
+ } |
+ |
+ switch (property_details_.type()) { |
+ case v8::internal::FIELD: |
+ case v8::internal::NORMAL: |
+ case v8::internal::CONSTANT: |
+ property_type_ = DATA; |
+ break; |
+ case v8::internal::CALLBACKS: |
+ property_type_ = ACCESSORS; |
+ break; |
+ case v8::internal::HANDLER: |
+ case v8::internal::NONEXISTENT: |
+ case v8::internal::INTERCEPTOR: |
+ UNREACHABLE(); |
+ } |
+ |
+ has_property_ = true; |
+ return true; |
+} |
+ |
+ |
+Handle<Object> LookupIterator::FetchValue() const { |
+ Object* result = NULL; |
+ switch (property_encoding_) { |
+ case DICTIONARY: |
+ result = GetHolder()->property_dictionary()->ValueAt(number_); |
+ if (GetHolder()->IsGlobalObject()) { |
+ result = PropertyCell::cast(result)->value(); |
+ } |
+ break; |
+ case DESCRIPTOR: |
+ if (property_details_.type() == v8::internal::FIELD) { |
+ FieldIndex field_index = FieldIndex::ForDescriptor( |
+ *holder_map_, number_); |
+ return JSObject::FastPropertyAt( |
+ GetHolder(), property_details_.representation(), field_index); |
+ } |
+ result = holder_map_->instance_descriptors()->GetValue(number_); |
+ } |
+ return handle(result, isolate_); |
+} |
+ |
+ |
+Handle<Object> LookupIterator::GetAccessors() const { |
+ ASSERT(has_property_); |
+ ASSERT_EQ(ACCESSORS, property_type_); |
+ return FetchValue(); |
+} |
+ |
+ |
+Handle<Object> LookupIterator::GetDataValue() const { |
+ ASSERT(has_property_); |
+ ASSERT_EQ(DATA, property_type_); |
+ Handle<Object> value = FetchValue(); |
+ if (value->IsTheHole()) { |
+ ASSERT_EQ(DICTIONARY, property_encoding_); |
+ ASSERT(GetHolder()->IsGlobalObject()); |
+ ASSERT(property_details_.IsReadOnly()); |
+ return factory()->undefined_value(); |
+ } |
+ return value; |
+} |
+ |
+ |
+} } // namespace v8::internal |