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 namespace v8 {
11 namespace internal {
12 
13 
NextHolder(Map * map)14 JSReceiver* LookupIterator::NextHolder(Map* map) {
15   DisallowHeapAllocation no_gc;
16   if (map->prototype()->IsNull()) return NULL;
17 
18   JSReceiver* next = JSReceiver::cast(map->prototype());
19   DCHECK(!next->map()->IsGlobalObjectMap() ||
20          next->map()->is_hidden_prototype());
21 
22   if (!check_prototype_chain() &&
23       !(check_hidden() && next->map()->is_hidden_prototype()) &&
24       // Always lookup behind the JSGlobalProxy into the JSGlobalObject, even
25       // when not checking other hidden prototypes.
26       !map->IsJSGlobalProxyMap()) {
27     return NULL;
28   }
29 
30   return next;
31 }
32 
33 
LookupInHolder(Map * map,JSReceiver * holder)34 LookupIterator::State LookupIterator::LookupInHolder(Map* map,
35                                                      JSReceiver* holder) {
36   STATIC_ASSERT(INTERCEPTOR == BEFORE_PROPERTY);
37   DisallowHeapAllocation no_gc;
38   switch (state_) {
39     case NOT_FOUND:
40       if (map->IsJSProxyMap()) return JSPROXY;
41       if (map->is_access_check_needed()) return ACCESS_CHECK;
42     // Fall through.
43     case ACCESS_CHECK:
44       if (check_interceptor() && map->has_named_interceptor()) {
45         return INTERCEPTOR;
46       }
47     // Fall through.
48     case INTERCEPTOR:
49       if (map->is_dictionary_map()) {
50         NameDictionary* dict = JSObject::cast(holder)->property_dictionary();
51         number_ = dict->FindEntry(name_);
52         if (number_ == NameDictionary::kNotFound) return NOT_FOUND;
53         property_details_ = dict->DetailsAt(number_);
54         if (holder->IsGlobalObject()) {
55           if (property_details_.IsDeleted()) return NOT_FOUND;
56           PropertyCell* cell = PropertyCell::cast(dict->ValueAt(number_));
57           if (cell->value()->IsTheHole()) return NOT_FOUND;
58         }
59       } else {
60         DescriptorArray* descriptors = map->instance_descriptors();
61         number_ = descriptors->SearchWithCache(*name_, map);
62         if (number_ == DescriptorArray::kNotFound) return NOT_FOUND;
63         property_details_ = descriptors->GetDetails(number_);
64       }
65       has_property_ = true;
66       switch (property_details_.type()) {
67         case v8::internal::CONSTANT:
68         case v8::internal::FIELD:
69         case v8::internal::NORMAL:
70           return DATA;
71         case v8::internal::CALLBACKS:
72           return ACCESSOR;
73       }
74     case ACCESSOR:
75     case DATA:
76       return NOT_FOUND;
77     case JSPROXY:
78     case TRANSITION:
79       UNREACHABLE();
80   }
81   UNREACHABLE();
82   return state_;
83 }
84 }
85 }  // namespace v8::internal
86 
87 #endif  // V8_LOOKUP_INL_H_
88