contexts-inl.h 7.45 KB
Newer Older
1 2 3 4 5 6 7 8
// Copyright 2015 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_CONTEXTS_INL_H_
#define V8_CONTEXTS_INL_H_

#include "src/contexts.h"
9
#include "src/heap/heap.h"
10
#include "src/objects-inl.h"
11
#include "src/objects/dictionary.h"
12
#include "src/objects/js-weak-refs-inl.h"
13
#include "src/objects/map-inl.h"
14
#include "src/objects/regexp-match-info.h"
15
#include "src/objects/scope-info.h"
16
#include "src/objects/shared-function-info-inl.h"
17
#include "src/objects/template-objects.h"
18 19 20 21 22 23 24 25 26 27 28

namespace v8 {
namespace internal {


// static
ScriptContextTable* ScriptContextTable::cast(Object* context) {
  DCHECK(context->IsScriptContextTable());
  return reinterpret_cast<ScriptContextTable*>(context);
}

29
int ScriptContextTable::used() const { return Smi::ToInt(get(kUsedSlotIndex)); }
30 31

void ScriptContextTable::set_used(int used) {
32
  set(kUsedSlotIndex, Smi::FromInt(used));
33 34 35 36
}


// static
37 38
Handle<Context> ScriptContextTable::GetContext(Isolate* isolate,
                                               Handle<ScriptContextTable> table,
39 40
                                               int i) {
  DCHECK(i < table->used());
41
  return Handle<Context>::cast(
42
      FixedArray::get(*table, i + kFirstContextSlotIndex, isolate));
43 44 45 46 47 48 49 50
}

// static
Context* Context::cast(Object* context) {
  DCHECK(context->IsContext());
  return reinterpret_cast<Context*>(context);
}

51 52 53 54 55
NativeContext* NativeContext::cast(Object* context) {
  DCHECK(context->IsNativeContext());
  return reinterpret_cast<NativeContext*>(context);
}

56 57 58
void Context::set_scope_info(ScopeInfo* scope_info) {
  set(SCOPE_INFO_INDEX, scope_info);
}
59 60 61 62 63 64 65 66

Context* Context::previous() {
  Object* result = get(PREVIOUS_INDEX);
  DCHECK(IsBootstrappingOrValidParentContext(result, this));
  return reinterpret_cast<Context*>(result);
}
void Context::set_previous(Context* context) { set(PREVIOUS_INDEX, context); }

67
Object* Context::next_context_link() { return get(Context::NEXT_CONTEXT_LINK); }
68

69
bool Context::has_extension() { return !extension()->IsTheHole(); }
70 71 72 73 74 75
HeapObject* Context::extension() {
  return HeapObject::cast(get(EXTENSION_INDEX));
}
void Context::set_extension(HeapObject* object) {
  set(EXTENSION_INDEX, object);
}
76

77
NativeContext* Context::native_context() const {
78 79
  Object* result = get(NATIVE_CONTEXT_INDEX);
  DCHECK(IsBootstrappingOrNativeContext(this->GetIsolate(), result));
80
  return reinterpret_cast<NativeContext*>(result);
81 82
}

83
void Context::set_native_context(NativeContext* context) {
84
  set(NATIVE_CONTEXT_INDEX, context);
85 86
}

87
bool Context::IsFunctionContext() const {
88
  return map()->instance_type() == FUNCTION_CONTEXT_TYPE;
89 90
}

91
bool Context::IsCatchContext() const {
92
  return map()->instance_type() == CATCH_CONTEXT_TYPE;
93 94
}

95
bool Context::IsWithContext() const {
96
  return map()->instance_type() == WITH_CONTEXT_TYPE;
97 98
}

99
bool Context::IsDebugEvaluateContext() const {
100
  return map()->instance_type() == DEBUG_EVALUATE_CONTEXT_TYPE;
101
}
102

103 104 105 106
bool Context::IsAwaitContext() const {
  return map()->instance_type() == AWAIT_CONTEXT_TYPE;
}

107
bool Context::IsBlockContext() const {
108
  return map()->instance_type() == BLOCK_CONTEXT_TYPE;
109 110
}

111
bool Context::IsModuleContext() const {
112
  return map()->instance_type() == MODULE_CONTEXT_TYPE;
113 114
}

115
bool Context::IsEvalContext() const {
116
  return map()->instance_type() == EVAL_CONTEXT_TYPE;
117
}
118

119
bool Context::IsScriptContext() const {
120
  return map()->instance_type() == SCRIPT_CONTEXT_TYPE;
121 122
}

123
bool Context::HasSameSecurityTokenAs(Context* that) const {
124 125
  return this->native_context()->security_token() ==
         that->native_context()->security_token();
126 127 128
}

#define NATIVE_CONTEXT_FIELD_ACCESSORS(index, type, name) \
129
  void Context::set_##name(type##ArgType value) {         \
130 131 132
    DCHECK(IsNativeContext());                            \
    set(index, value);                                    \
  }                                                       \
133
  bool Context::is_##name(type##ArgType value) const {    \
134 135 136
    DCHECK(IsNativeContext());                            \
    return type::cast(get(index)) == value;               \
  }                                                       \
137
  type##ArgType Context::name() const {                   \
138 139 140 141 142 143
    DCHECK(IsNativeContext());                            \
    return type::cast(get(index));                        \
  }
NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELD_ACCESSORS)
#undef NATIVE_CONTEXT_FIELD_ACCESSORS

144 145 146 147 148 149 150
#define CHECK_FOLLOWS2(v1, v2) STATIC_ASSERT((v1 + 1) == (v2))
#define CHECK_FOLLOWS4(v1, v2, v3, v4) \
  CHECK_FOLLOWS2(v1, v2);              \
  CHECK_FOLLOWS2(v2, v3);              \
  CHECK_FOLLOWS2(v3, v4)

int Context::FunctionMapIndex(LanguageMode language_mode, FunctionKind kind,
151 152
                              bool has_prototype_slot, bool has_shared_name,
                              bool needs_home_object) {
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
  if (IsClassConstructor(kind)) {
    // Like the strict function map, but with no 'name' accessor. 'name'
    // needs to be the last property and it is added during instantiation,
    // in case a static property with the same name exists"
    return CLASS_FUNCTION_MAP_INDEX;
  }

  int base = 0;
  if (IsGeneratorFunction(kind)) {
    CHECK_FOLLOWS4(GENERATOR_FUNCTION_MAP_INDEX,
                   GENERATOR_FUNCTION_WITH_NAME_MAP_INDEX,
                   GENERATOR_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX,
                   GENERATOR_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX);
    CHECK_FOLLOWS4(
        ASYNC_GENERATOR_FUNCTION_MAP_INDEX,
        ASYNC_GENERATOR_FUNCTION_WITH_NAME_MAP_INDEX,
        ASYNC_GENERATOR_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX,
        ASYNC_GENERATOR_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX);

    base = IsAsyncFunction(kind) ? ASYNC_GENERATOR_FUNCTION_MAP_INDEX
                                 : GENERATOR_FUNCTION_MAP_INDEX;

  } else if (IsAsyncFunction(kind)) {
    CHECK_FOLLOWS4(ASYNC_FUNCTION_MAP_INDEX, ASYNC_FUNCTION_WITH_NAME_MAP_INDEX,
                   ASYNC_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX,
                   ASYNC_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX);

    base = ASYNC_FUNCTION_MAP_INDEX;

  } else if (IsArrowFunction(kind) || IsConciseMethod(kind) ||
             IsAccessorFunction(kind)) {
    DCHECK_IMPLIES(IsArrowFunction(kind), !needs_home_object);
    CHECK_FOLLOWS4(STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
                   METHOD_WITH_NAME_MAP_INDEX,
                   METHOD_WITH_HOME_OBJECT_MAP_INDEX,
                   METHOD_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX);

    base = STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX;

  } else {
    DCHECK(!needs_home_object);
    CHECK_FOLLOWS2(SLOPPY_FUNCTION_MAP_INDEX,
                   SLOPPY_FUNCTION_WITH_NAME_MAP_INDEX);
    CHECK_FOLLOWS2(STRICT_FUNCTION_MAP_INDEX,
                   STRICT_FUNCTION_WITH_NAME_MAP_INDEX);

    base = is_strict(language_mode) ? STRICT_FUNCTION_MAP_INDEX
                                    : SLOPPY_FUNCTION_MAP_INDEX;
  }
  int offset = static_cast<int>(!has_shared_name) |
               (static_cast<int>(needs_home_object) << 1);
  DCHECK_EQ(0, offset & ~3);

  return base + offset;
}

#undef CHECK_FOLLOWS2
#undef CHECK_FOLLOWS4
211

212 213 214 215 216
Map* Context::GetInitialJSArrayMap(ElementsKind kind) const {
  DCHECK(IsNativeContext());
  if (!IsFastElementsKind(kind)) return nullptr;
  DisallowHeapAllocation no_gc;
  Object* const initial_js_array_map = get(Context::ArrayMapIndex(kind));
217
  DCHECK(!initial_js_array_map->IsUndefined());
218 219 220
  return Map::cast(initial_js_array_map);
}

221 222 223 224
}  // namespace internal
}  // namespace v8

#endif  // V8_CONTEXTS_INL_H_