lookup-inl.h 6.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// 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/handles-inl.h"
11 12 13 14 15
#include "src/heap/factory-inl.h"
#include "src/objects-inl.h"
#include "src/objects/api-callbacks.h"
#include "src/objects/name-inl.h"
#include "src/objects/map-inl.h"
16 17 18 19

namespace v8 {
namespace internal {

20 21 22 23 24
LookupIterator::LookupIterator(Isolate* isolate, Handle<Object> receiver,
                               Handle<Name> name, Configuration configuration)
    : LookupIterator(isolate, receiver, name, GetRoot(isolate, receiver),
                     configuration) {}

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
LookupIterator::LookupIterator(Handle<Object> receiver, Handle<Name> name,
                               Handle<JSReceiver> holder,
                               Configuration configuration)
    : LookupIterator(holder->GetIsolate(), receiver, name, holder,
                     configuration) {}

LookupIterator::LookupIterator(Isolate* isolate, Handle<Object> receiver,
                               Handle<Name> name, Handle<JSReceiver> holder,
                               Configuration configuration)
    : configuration_(ComputeConfiguration(configuration, name)),
      interceptor_state_(InterceptorState::kUninitialized),
      property_details_(PropertyDetails::Empty()),
      isolate_(isolate),
      name_(isolate_->factory()->InternalizeName(name)),
      receiver_(receiver),
      initial_holder_(holder),
      // kMaxUInt32 isn't a valid index.
      index_(kMaxUInt32),
      number_(static_cast<uint32_t>(DescriptorArray::kNotFound)) {
#ifdef DEBUG
  uint32_t index;  // Assert that the name is not an array index.
  DCHECK(!name->AsArrayIndex(&index));
#endif  // DEBUG
  Start<false>();
}

51 52 53 54 55
LookupIterator::LookupIterator(Isolate* isolate, Handle<Object> receiver,
                               uint32_t index, Configuration configuration)
    : LookupIterator(isolate, receiver, index,
                     GetRoot(isolate, receiver, index), configuration) {}

56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
LookupIterator LookupIterator::PropertyOrElement(
    Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
    Handle<JSReceiver> holder, Configuration configuration) {
  uint32_t index;
  if (name->AsArrayIndex(&index)) {
    LookupIterator it =
        LookupIterator(isolate, receiver, index, holder, configuration);
    it.name_ = name;
    return it;
  }
  return LookupIterator(receiver, name, holder, configuration);
}

LookupIterator LookupIterator::PropertyOrElement(
    Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
    Configuration configuration) {
  uint32_t index;
  if (name->AsArrayIndex(&index)) {
    LookupIterator it = LookupIterator(isolate, receiver, index, configuration);
    it.name_ = name;
    return it;
  }
  return LookupIterator(isolate, receiver, name, configuration);
}

Handle<Name> LookupIterator::GetName() {
  if (name_.is_null()) {
    DCHECK(IsElement());
    name_ = factory()->Uint32ToString(index_);
  }
  return name_;
}

bool LookupIterator::is_dictionary_holder() const {
  return !holder_->HasFastProperties();
}

93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
Handle<Map> LookupIterator::transition_map() const {
  DCHECK_EQ(TRANSITION, state_);
  return Handle<Map>::cast(transition_);
}

Handle<PropertyCell> LookupIterator::transition_cell() const {
  DCHECK_EQ(TRANSITION, state_);
  return Handle<PropertyCell>::cast(transition_);
}

template <class T>
Handle<T> LookupIterator::GetHolder() const {
  DCHECK(IsFound());
  return Handle<T>::cast(holder_);
}

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
bool LookupIterator::ExtendingNonExtensible(Handle<JSReceiver> receiver) {
  DCHECK(receiver.is_identical_to(GetStoreTarget<JSReceiver>()));
  return !receiver->map()->is_extensible() &&
         (IsElement() || !name_->IsPrivate());
}

bool LookupIterator::IsCacheableTransition() {
  DCHECK_EQ(TRANSITION, state_);
  return transition_->IsPropertyCell() ||
         (transition_map()->is_dictionary_map() &&
          !GetStoreTarget<JSReceiver>()->HasFastProperties()) ||
         transition_map()->GetBackPointer()->IsMap();
}

void LookupIterator::UpdateProtector() {
  if (IsElement()) return;
  // This list must be kept in sync with
  // CodeStubAssembler::CheckForAssociatedProtector!
  ReadOnlyRoots roots(heap());
  if (*name_ == roots.is_concat_spreadable_symbol() ||
      *name_ == roots.constructor_string() || *name_ == roots.next_string() ||
      *name_ == roots.species_symbol() || *name_ == roots.iterator_symbol() ||
      *name_ == roots.resolve_string() || *name_ == roots.then_string()) {
    InternalUpdateProtector();
  }
}

136 137 138 139 140 141 142 143 144 145 146 147 148 149
int LookupIterator::descriptor_number() const {
  DCHECK(!IsElement());
  DCHECK(has_property_);
  DCHECK(holder_->HasFastProperties());
  return number_;
}

int LookupIterator::dictionary_entry() const {
  DCHECK(!IsElement());
  DCHECK(has_property_);
  DCHECK(!holder_->HasFastProperties());
  return number_;
}

150 151 152 153 154 155 156 157 158 159 160 161
LookupIterator::Configuration LookupIterator::ComputeConfiguration(
    Configuration configuration, Handle<Name> name) {
  return name->IsPrivate() ? OWN_SKIP_INTERCEPTOR : configuration;
}

Handle<JSReceiver> LookupIterator::GetRoot(Isolate* isolate,
                                           Handle<Object> receiver,
                                           uint32_t index) {
  if (receiver->IsJSReceiver()) return Handle<JSReceiver>::cast(receiver);
  return GetRootForNonJSReceiver(isolate, receiver, index);
}

162 163 164 165
template <class T>
Handle<T> LookupIterator::GetStoreTarget() const {
  DCHECK(receiver_->IsJSReceiver());
  if (receiver_->IsJSGlobalProxy()) {
166
    Map map = JSGlobalProxy::cast(*receiver_)->map();
167 168 169 170 171 172
    if (map->has_hidden_prototype()) {
      return handle(JSGlobalObject::cast(map->prototype()), isolate_);
    }
  }
  return Handle<T>::cast(receiver_);
}
173 174 175 176 177 178 179

template <bool is_element>
InterceptorInfo LookupIterator::GetInterceptor(JSObject holder) {
  return is_element ? holder->GetIndexedInterceptor()
                    : holder->GetNamedInterceptor();
}

180 181
inline Handle<InterceptorInfo> LookupIterator::GetInterceptor() const {
  DCHECK_EQ(INTERCEPTOR, state_);
182
  InterceptorInfo result =
183 184 185 186 187 188 189 190 191
      IsElement() ? GetInterceptor<true>(JSObject::cast(*holder_))
                  : GetInterceptor<false>(JSObject::cast(*holder_));
  return handle(result, isolate_);
}

}  // namespace internal
}  // namespace v8

#endif  // V8_LOOKUP_INL_H_