3df2194d3f9f462869bd71653e625693fec97736
[platform/upstream/v8.git] / src / lookup-inl.h
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_LOOKUP_INL_H_
6 #define V8_LOOKUP_INL_H_
7
8 #include "src/lookup.h"
9
10 #include "src/elements.h"
11
12 namespace v8 {
13 namespace internal {
14
15
16 JSReceiver* LookupIterator::NextHolder(Map* map) {
17   DisallowHeapAllocation no_gc;
18   if (!map->prototype()->IsJSReceiver()) return NULL;
19
20   JSReceiver* next = JSReceiver::cast(map->prototype());
21   DCHECK(!next->map()->IsGlobalObjectMap() ||
22          next->map()->is_hidden_prototype());
23
24   if (!check_prototype_chain() &&
25       !(check_hidden() && next->map()->is_hidden_prototype()) &&
26       // Always lookup behind the JSGlobalProxy into the JSGlobalObject, even
27       // when not checking other hidden prototypes.
28       !map->IsJSGlobalProxyMap()) {
29     return NULL;
30   }
31
32   return next;
33 }
34
35
36 LookupIterator::State LookupIterator::LookupInHolder(Map* const map,
37                                                      JSReceiver* const holder) {
38   STATIC_ASSERT(INTERCEPTOR == BEFORE_PROPERTY);
39   DisallowHeapAllocation no_gc;
40   if (interceptor_state_ == InterceptorState::kProcessNonMasking) {
41     return LookupNonMaskingInterceptorInHolder(map, holder);
42   }
43   switch (state_) {
44     case NOT_FOUND:
45       if (map->IsJSProxyMap()) return JSPROXY;
46       if (map->is_access_check_needed() &&
47           (IsElement() || !isolate_->IsInternallyUsedPropertyName(name_))) {
48         return ACCESS_CHECK;
49       }
50     // Fall through.
51     case ACCESS_CHECK:
52       if (exotic_index_state_ != ExoticIndexState::kNotExotic &&
53           IsIntegerIndexedExotic(holder)) {
54         return INTEGER_INDEXED_EXOTIC;
55       }
56       if (check_interceptor() && HasInterceptor(map) &&
57           !SkipInterceptor(JSObject::cast(holder))) {
58         return INTERCEPTOR;
59       }
60     // Fall through.
61     case INTERCEPTOR:
62       if (IsElement()) {
63         // TODO(verwaest): Optimize.
64         if (holder->IsStringObjectWithCharacterAt(index_)) {
65           PropertyAttributes attributes =
66               static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
67           property_details_ = PropertyDetails(attributes, v8::internal::DATA, 0,
68                                               PropertyCellType::kNoCell);
69         } else {
70           JSObject* js_object = JSObject::cast(holder);
71           if (js_object->elements() == isolate()->heap()->empty_fixed_array()) {
72             return NOT_FOUND;
73           }
74
75           ElementsAccessor* accessor = js_object->GetElementsAccessor();
76           FixedArrayBase* backing_store = js_object->elements();
77           number_ =
78               accessor->GetEntryForIndex(js_object, backing_store, index_);
79           if (number_ == kMaxUInt32) return NOT_FOUND;
80           property_details_ = accessor->GetDetails(backing_store, number_);
81         }
82       } else if (!map->is_dictionary_map()) {
83         DescriptorArray* descriptors = map->instance_descriptors();
84         int number = descriptors->SearchWithCache(*name_, map);
85         if (number == DescriptorArray::kNotFound) return NOT_FOUND;
86         number_ = static_cast<uint32_t>(number);
87         property_details_ = descriptors->GetDetails(number_);
88       } else if (map->IsGlobalObjectMap()) {
89         GlobalDictionary* dict = JSObject::cast(holder)->global_dictionary();
90         int number = dict->FindEntry(name_);
91         if (number == GlobalDictionary::kNotFound) return NOT_FOUND;
92         number_ = static_cast<uint32_t>(number);
93         DCHECK(dict->ValueAt(number_)->IsPropertyCell());
94         PropertyCell* cell = PropertyCell::cast(dict->ValueAt(number_));
95         if (cell->value()->IsTheHole()) return NOT_FOUND;
96         property_details_ = cell->property_details();
97       } else {
98         NameDictionary* dict = JSObject::cast(holder)->property_dictionary();
99         int number = dict->FindEntry(name_);
100         if (number == NameDictionary::kNotFound) return NOT_FOUND;
101         number_ = static_cast<uint32_t>(number);
102         property_details_ = dict->DetailsAt(number_);
103       }
104       has_property_ = true;
105       switch (property_details_.kind()) {
106         case v8::internal::kData:
107           return DATA;
108         case v8::internal::kAccessor:
109           return ACCESSOR;
110       }
111     case ACCESSOR:
112     case DATA:
113       return NOT_FOUND;
114     case INTEGER_INDEXED_EXOTIC:
115     case JSPROXY:
116     case TRANSITION:
117       UNREACHABLE();
118   }
119   UNREACHABLE();
120   return state_;
121 }
122
123
124 LookupIterator::State LookupIterator::LookupNonMaskingInterceptorInHolder(
125     Map* const map, JSReceiver* const holder) {
126   switch (state_) {
127     case NOT_FOUND:
128       if (check_interceptor() && HasInterceptor(map) &&
129           !SkipInterceptor(JSObject::cast(holder))) {
130         return INTERCEPTOR;
131       }
132     // Fall through.
133     default:
134       return NOT_FOUND;
135   }
136   UNREACHABLE();
137   return state_;
138 }
139 }
140 }  // namespace v8::internal
141
142 #endif  // V8_LOOKUP_INL_H_