Home | History | Annotate | Download | only in src
      1 // Copyright 2015 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_CONTEXTS_INL_H_
      6 #define V8_CONTEXTS_INL_H_
      7 
      8 #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/map-inl.h"
     13 #include "src/objects/regexp-match-info.h"
     14 #include "src/objects/scope-info.h"
     15 #include "src/objects/shared-function-info-inl.h"
     16 #include "src/objects/template-objects.h"
     17 
     18 namespace v8 {
     19 namespace internal {
     20 
     21 
     22 // static
     23 ScriptContextTable* ScriptContextTable::cast(Object* context) {
     24   DCHECK(context->IsScriptContextTable());
     25   return reinterpret_cast<ScriptContextTable*>(context);
     26 }
     27 
     28 int ScriptContextTable::used() const { return Smi::ToInt(get(kUsedSlotIndex)); }
     29 
     30 void ScriptContextTable::set_used(int used) {
     31   set(kUsedSlotIndex, Smi::FromInt(used));
     32 }
     33 
     34 
     35 // static
     36 Handle<Context> ScriptContextTable::GetContext(Isolate* isolate,
     37                                                Handle<ScriptContextTable> table,
     38                                                int i) {
     39   DCHECK(i < table->used());
     40   return Handle<Context>::cast(
     41       FixedArray::get(*table, i + kFirstContextSlotIndex, isolate));
     42 }
     43 
     44 // static
     45 Context* Context::cast(Object* context) {
     46   DCHECK(context->IsContext());
     47   return reinterpret_cast<Context*>(context);
     48 }
     49 
     50 NativeContext* NativeContext::cast(Object* context) {
     51   DCHECK(context->IsNativeContext());
     52   return reinterpret_cast<NativeContext*>(context);
     53 }
     54 
     55 void Context::set_scope_info(ScopeInfo* scope_info) {
     56   set(SCOPE_INFO_INDEX, scope_info);
     57 }
     58 
     59 Context* Context::previous() {
     60   Object* result = get(PREVIOUS_INDEX);
     61   DCHECK(IsBootstrappingOrValidParentContext(result, this));
     62   return reinterpret_cast<Context*>(result);
     63 }
     64 void Context::set_previous(Context* context) { set(PREVIOUS_INDEX, context); }
     65 
     66 Object* Context::next_context_link() { return get(Context::NEXT_CONTEXT_LINK); }
     67 
     68 bool Context::has_extension() { return !extension()->IsTheHole(); }
     69 HeapObject* Context::extension() {
     70   return HeapObject::cast(get(EXTENSION_INDEX));
     71 }
     72 void Context::set_extension(HeapObject* object) {
     73   set(EXTENSION_INDEX, object);
     74 }
     75 
     76 NativeContext* Context::native_context() const {
     77   Object* result = get(NATIVE_CONTEXT_INDEX);
     78   DCHECK(IsBootstrappingOrNativeContext(this->GetIsolate(), result));
     79   return reinterpret_cast<NativeContext*>(result);
     80 }
     81 
     82 void Context::set_native_context(NativeContext* context) {
     83   set(NATIVE_CONTEXT_INDEX, context);
     84 }
     85 
     86 bool Context::IsFunctionContext() const {
     87   return map()->instance_type() == FUNCTION_CONTEXT_TYPE;
     88 }
     89 
     90 bool Context::IsCatchContext() const {
     91   return map()->instance_type() == CATCH_CONTEXT_TYPE;
     92 }
     93 
     94 bool Context::IsWithContext() const {
     95   return map()->instance_type() == WITH_CONTEXT_TYPE;
     96 }
     97 
     98 bool Context::IsDebugEvaluateContext() const {
     99   return map()->instance_type() == DEBUG_EVALUATE_CONTEXT_TYPE;
    100 }
    101 
    102 bool Context::IsBlockContext() const {
    103   return map()->instance_type() == BLOCK_CONTEXT_TYPE;
    104 }
    105 
    106 bool Context::IsModuleContext() const {
    107   return map()->instance_type() == MODULE_CONTEXT_TYPE;
    108 }
    109 
    110 bool Context::IsEvalContext() const {
    111   return map()->instance_type() == EVAL_CONTEXT_TYPE;
    112 }
    113 
    114 bool Context::IsScriptContext() const {
    115   return map()->instance_type() == SCRIPT_CONTEXT_TYPE;
    116 }
    117 
    118 bool Context::HasSameSecurityTokenAs(Context* that) const {
    119   return this->native_context()->security_token() ==
    120          that->native_context()->security_token();
    121 }
    122 
    123 #define NATIVE_CONTEXT_FIELD_ACCESSORS(index, type, name) \
    124   void Context::set_##name(type* value) {                 \
    125     DCHECK(IsNativeContext());                            \
    126     set(index, value);                                    \
    127   }                                                       \
    128   bool Context::is_##name(type* value) const {            \
    129     DCHECK(IsNativeContext());                            \
    130     return type::cast(get(index)) == value;               \
    131   }                                                       \
    132   type* Context::name() const {                           \
    133     DCHECK(IsNativeContext());                            \
    134     return type::cast(get(index));                        \
    135   }
    136 NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELD_ACCESSORS)
    137 #undef NATIVE_CONTEXT_FIELD_ACCESSORS
    138 
    139 #define CHECK_FOLLOWS2(v1, v2) STATIC_ASSERT((v1 + 1) == (v2))
    140 #define CHECK_FOLLOWS4(v1, v2, v3, v4) \
    141   CHECK_FOLLOWS2(v1, v2);              \
    142   CHECK_FOLLOWS2(v2, v3);              \
    143   CHECK_FOLLOWS2(v3, v4)
    144 
    145 int Context::FunctionMapIndex(LanguageMode language_mode, FunctionKind kind,
    146                               bool has_prototype_slot, bool has_shared_name,
    147                               bool needs_home_object) {
    148   if (IsClassConstructor(kind)) {
    149     // Like the strict function map, but with no 'name' accessor. 'name'
    150     // needs to be the last property and it is added during instantiation,
    151     // in case a static property with the same name exists"
    152     return CLASS_FUNCTION_MAP_INDEX;
    153   }
    154 
    155   int base = 0;
    156   if (IsGeneratorFunction(kind)) {
    157     CHECK_FOLLOWS4(GENERATOR_FUNCTION_MAP_INDEX,
    158                    GENERATOR_FUNCTION_WITH_NAME_MAP_INDEX,
    159                    GENERATOR_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX,
    160                    GENERATOR_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX);
    161     CHECK_FOLLOWS4(
    162         ASYNC_GENERATOR_FUNCTION_MAP_INDEX,
    163         ASYNC_GENERATOR_FUNCTION_WITH_NAME_MAP_INDEX,
    164         ASYNC_GENERATOR_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX,
    165         ASYNC_GENERATOR_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX);
    166 
    167     base = IsAsyncFunction(kind) ? ASYNC_GENERATOR_FUNCTION_MAP_INDEX
    168                                  : GENERATOR_FUNCTION_MAP_INDEX;
    169 
    170   } else if (IsAsyncFunction(kind)) {
    171     CHECK_FOLLOWS4(ASYNC_FUNCTION_MAP_INDEX, ASYNC_FUNCTION_WITH_NAME_MAP_INDEX,
    172                    ASYNC_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX,
    173                    ASYNC_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX);
    174 
    175     base = ASYNC_FUNCTION_MAP_INDEX;
    176 
    177   } else if (IsArrowFunction(kind) || IsConciseMethod(kind) ||
    178              IsAccessorFunction(kind)) {
    179     DCHECK_IMPLIES(IsArrowFunction(kind), !needs_home_object);
    180     CHECK_FOLLOWS4(STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
    181                    METHOD_WITH_NAME_MAP_INDEX,
    182                    METHOD_WITH_HOME_OBJECT_MAP_INDEX,
    183                    METHOD_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX);
    184 
    185     base = STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX;
    186 
    187   } else {
    188     DCHECK(!needs_home_object);
    189     CHECK_FOLLOWS2(SLOPPY_FUNCTION_MAP_INDEX,
    190                    SLOPPY_FUNCTION_WITH_NAME_MAP_INDEX);
    191     CHECK_FOLLOWS2(STRICT_FUNCTION_MAP_INDEX,
    192                    STRICT_FUNCTION_WITH_NAME_MAP_INDEX);
    193 
    194     base = is_strict(language_mode) ? STRICT_FUNCTION_MAP_INDEX
    195                                     : SLOPPY_FUNCTION_MAP_INDEX;
    196   }
    197   int offset = static_cast<int>(!has_shared_name) |
    198                (static_cast<int>(needs_home_object) << 1);
    199   DCHECK_EQ(0, offset & ~3);
    200 
    201   return base + offset;
    202 }
    203 
    204 #undef CHECK_FOLLOWS2
    205 #undef CHECK_FOLLOWS4
    206 
    207 Map* Context::GetInitialJSArrayMap(ElementsKind kind) const {
    208   DCHECK(IsNativeContext());
    209   if (!IsFastElementsKind(kind)) return nullptr;
    210   DisallowHeapAllocation no_gc;
    211   Object* const initial_js_array_map = get(Context::ArrayMapIndex(kind));
    212   DCHECK(!initial_js_array_map->IsUndefined());
    213   return Map::cast(initial_js_array_map);
    214 }
    215 
    216 }  // namespace internal
    217 }  // namespace v8
    218 
    219 #endif  // V8_CONTEXTS_INL_H_
    220