Home | History | Annotate | Download | only in src
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_CONTEXTS_H_
     29 #define V8_CONTEXTS_H_
     30 
     31 #include "heap.h"
     32 #include "objects.h"
     33 
     34 namespace v8 {
     35 namespace internal {
     36 
     37 
     38 enum ContextLookupFlags {
     39   FOLLOW_CONTEXT_CHAIN = 1,
     40   FOLLOW_PROTOTYPE_CHAIN = 2,
     41 
     42   DONT_FOLLOW_CHAINS = 0,
     43   FOLLOW_CHAINS = FOLLOW_CONTEXT_CHAIN | FOLLOW_PROTOTYPE_CHAIN
     44 };
     45 
     46 
     47 // ES5 10.2 defines lexical environments with mutable and immutable bindings.
     48 // Immutable bindings have two states, initialized and uninitialized, and
     49 // their state is changed by the InitializeImmutableBinding method. The
     50 // BindingFlags enum represents information if a binding has definitely been
     51 // initialized. A mutable binding does not need to be checked and thus has
     52 // the BindingFlag MUTABLE_IS_INITIALIZED.
     53 //
     54 // There are two possibilities for immutable bindings
     55 //  * 'const' declared variables. They are initialized when evaluating the
     56 //    corresponding declaration statement. They need to be checked for being
     57 //    initialized and thus get the flag IMMUTABLE_CHECK_INITIALIZED.
     58 //  * The function name of a named function literal. The binding is immediately
     59 //    initialized when entering the function and thus does not need to be
     60 //    checked. it gets the BindingFlag IMMUTABLE_IS_INITIALIZED.
     61 // Accessing an uninitialized binding produces the undefined value.
     62 //
     63 // The harmony proposal for block scoped bindings also introduces the
     64 // uninitialized state for mutable bindings.
     65 //  * A 'let' declared variable. They are initialized when evaluating the
     66 //    corresponding declaration statement. They need to be checked for being
     67 //    initialized and thus get the flag MUTABLE_CHECK_INITIALIZED.
     68 //  * A 'var' declared variable. It is initialized immediately upon creation
     69 //    and thus doesn't need to be checked. It gets the flag
     70 //    MUTABLE_IS_INITIALIZED.
     71 //  * Catch bound variables, function parameters and variables introduced by
     72 //    function declarations are initialized immediately and do not need to be
     73 //    checked. Thus they get the flag MUTABLE_IS_INITIALIZED.
     74 // Immutable bindings in harmony mode get the _HARMONY flag variants. Accessing
     75 // an uninitialized binding produces a reference error.
     76 //
     77 // In V8 uninitialized bindings are set to the hole value upon creation and set
     78 // to a different value upon initialization.
     79 enum BindingFlags {
     80   MUTABLE_IS_INITIALIZED,
     81   MUTABLE_CHECK_INITIALIZED,
     82   IMMUTABLE_IS_INITIALIZED,
     83   IMMUTABLE_CHECK_INITIALIZED,
     84   IMMUTABLE_IS_INITIALIZED_HARMONY,
     85   IMMUTABLE_CHECK_INITIALIZED_HARMONY,
     86   MISSING_BINDING
     87 };
     88 
     89 
     90 // Heap-allocated activation contexts.
     91 //
     92 // Contexts are implemented as FixedArray objects; the Context
     93 // class is a convenience interface casted on a FixedArray object.
     94 //
     95 // Note: Context must have no virtual functions and Context objects
     96 // must always be allocated via Heap::AllocateContext() or
     97 // Factory::NewContext.
     98 
     99 #define GLOBAL_CONTEXT_FIELDS(V) \
    100   V(GLOBAL_PROXY_INDEX, JSObject, global_proxy_object) \
    101   V(SECURITY_TOKEN_INDEX, Object, security_token) \
    102   V(BOOLEAN_FUNCTION_INDEX, JSFunction, boolean_function) \
    103   V(NUMBER_FUNCTION_INDEX, JSFunction, number_function) \
    104   V(STRING_FUNCTION_INDEX, JSFunction, string_function) \
    105   V(STRING_FUNCTION_PROTOTYPE_MAP_INDEX, Map, string_function_prototype_map) \
    106   V(OBJECT_FUNCTION_INDEX, JSFunction, object_function) \
    107   V(INTERNAL_ARRAY_FUNCTION_INDEX, JSFunction, internal_array_function) \
    108   V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \
    109   V(SMI_JS_ARRAY_MAP_INDEX, Object, smi_js_array_map) \
    110   V(DOUBLE_JS_ARRAY_MAP_INDEX, Object, double_js_array_map) \
    111   V(OBJECT_JS_ARRAY_MAP_INDEX, Object, object_js_array_map) \
    112   V(DATE_FUNCTION_INDEX, JSFunction, date_function) \
    113   V(JSON_OBJECT_INDEX, JSObject, json_object) \
    114   V(REGEXP_FUNCTION_INDEX, JSFunction, regexp_function) \
    115   V(INITIAL_OBJECT_PROTOTYPE_INDEX, JSObject, initial_object_prototype) \
    116   V(CREATE_DATE_FUN_INDEX, JSFunction,  create_date_fun) \
    117   V(TO_NUMBER_FUN_INDEX, JSFunction, to_number_fun) \
    118   V(TO_STRING_FUN_INDEX, JSFunction, to_string_fun) \
    119   V(TO_DETAIL_STRING_FUN_INDEX, JSFunction, to_detail_string_fun) \
    120   V(TO_OBJECT_FUN_INDEX, JSFunction, to_object_fun) \
    121   V(TO_INTEGER_FUN_INDEX, JSFunction, to_integer_fun) \
    122   V(TO_UINT32_FUN_INDEX, JSFunction, to_uint32_fun) \
    123   V(TO_INT32_FUN_INDEX, JSFunction, to_int32_fun) \
    124   V(GLOBAL_EVAL_FUN_INDEX, JSFunction, global_eval_fun) \
    125   V(INSTANTIATE_FUN_INDEX, JSFunction, instantiate_fun) \
    126   V(CONFIGURE_INSTANCE_FUN_INDEX, JSFunction, configure_instance_fun) \
    127   V(FUNCTION_MAP_INDEX, Map, function_map) \
    128   V(STRICT_MODE_FUNCTION_MAP_INDEX, Map, strict_mode_function_map) \
    129   V(FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, function_without_prototype_map) \
    130   V(STRICT_MODE_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, \
    131     strict_mode_function_without_prototype_map) \
    132   V(FUNCTION_INSTANCE_MAP_INDEX, Map, function_instance_map) \
    133   V(STRICT_MODE_FUNCTION_INSTANCE_MAP_INDEX, Map, \
    134     strict_mode_function_instance_map) \
    135   V(REGEXP_RESULT_MAP_INDEX, Map, regexp_result_map)\
    136   V(ARGUMENTS_BOILERPLATE_INDEX, JSObject, arguments_boilerplate) \
    137   V(ALIASED_ARGUMENTS_BOILERPLATE_INDEX, JSObject, \
    138     aliased_arguments_boilerplate) \
    139   V(STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX, JSObject, \
    140     strict_mode_arguments_boilerplate) \
    141   V(MESSAGE_LISTENERS_INDEX, JSObject, message_listeners) \
    142   V(MAKE_MESSAGE_FUN_INDEX, JSFunction, make_message_fun) \
    143   V(GET_STACK_TRACE_LINE_INDEX, JSFunction, get_stack_trace_line_fun) \
    144   V(CONFIGURE_GLOBAL_INDEX, JSFunction, configure_global_fun) \
    145   V(FUNCTION_CACHE_INDEX, JSObject, function_cache) \
    146   V(JSFUNCTION_RESULT_CACHES_INDEX, FixedArray, jsfunction_result_caches) \
    147   V(NORMALIZED_MAP_CACHE_INDEX, NormalizedMapCache, normalized_map_cache) \
    148   V(RUNTIME_CONTEXT_INDEX, Context, runtime_context) \
    149   V(CALL_AS_FUNCTION_DELEGATE_INDEX, JSFunction, call_as_function_delegate) \
    150   V(CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, JSFunction, \
    151     call_as_constructor_delegate) \
    152   V(SCRIPT_FUNCTION_INDEX, JSFunction, script_function) \
    153   V(OPAQUE_REFERENCE_FUNCTION_INDEX, JSFunction, opaque_reference_function) \
    154   V(CONTEXT_EXTENSION_FUNCTION_INDEX, JSFunction, context_extension_function) \
    155   V(OUT_OF_MEMORY_INDEX, Object, out_of_memory) \
    156   V(MAP_CACHE_INDEX, Object, map_cache) \
    157   V(CONTEXT_DATA_INDEX, Object, data) \
    158   V(ALLOW_CODE_GEN_FROM_STRINGS_INDEX, Object, allow_code_gen_from_strings) \
    159   V(TO_COMPLETE_PROPERTY_DESCRIPTOR_INDEX, JSFunction, \
    160     to_complete_property_descriptor) \
    161   V(DERIVED_HAS_TRAP_INDEX, JSFunction, derived_has_trap) \
    162   V(DERIVED_GET_TRAP_INDEX, JSFunction, derived_get_trap) \
    163   V(DERIVED_SET_TRAP_INDEX, JSFunction, derived_set_trap) \
    164   V(PROXY_ENUMERATE, JSFunction, proxy_enumerate) \
    165   V(RANDOM_SEED_INDEX, ByteArray, random_seed)
    166 
    167 // JSFunctions are pairs (context, function code), sometimes also called
    168 // closures. A Context object is used to represent function contexts and
    169 // dynamically pushed 'with' contexts (or 'scopes' in ECMA-262 speak).
    170 //
    171 // At runtime, the contexts build a stack in parallel to the execution
    172 // stack, with the top-most context being the current context. All contexts
    173 // have the following slots:
    174 //
    175 // [ closure   ]  This is the current function. It is the same for all
    176 //                contexts inside a function. It provides access to the
    177 //                incoming context (i.e., the outer context, which may
    178 //                or may not become the current function's context), and
    179 //                it provides access to the functions code and thus it's
    180 //                scope information, which in turn contains the names of
    181 //                statically allocated context slots. The names are needed
    182 //                for dynamic lookups in the presence of 'with' or 'eval'.
    183 //
    184 // [ previous  ]  A pointer to the previous context. It is NULL for
    185 //                function contexts, and non-NULL for 'with' contexts.
    186 //                Used to implement the 'with' statement.
    187 //
    188 // [ extension ]  A pointer to an extension JSObject, or NULL. Used to
    189 //                implement 'with' statements and dynamic declarations
    190 //                (through 'eval'). The object in a 'with' statement is
    191 //                stored in the extension slot of a 'with' context.
    192 //                Dynamically declared variables/functions are also added
    193 //                to lazily allocated extension object. Context::Lookup
    194 //                searches the extension object for properties.
    195 //
    196 // [ global    ]  A pointer to the global object. Provided for quick
    197 //                access to the global object from inside the code (since
    198 //                we always have a context pointer).
    199 //
    200 // In addition, function contexts may have statically allocated context slots
    201 // to store local variables/functions that are accessed from inner functions
    202 // (via static context addresses) or through 'eval' (dynamic context lookups).
    203 // Finally, the global context contains additional slots for fast access to
    204 // global properties.
    205 
    206 class Context: public FixedArray {
    207  public:
    208   // Conversions.
    209   static Context* cast(Object* context) {
    210     ASSERT(context->IsContext());
    211     return reinterpret_cast<Context*>(context);
    212   }
    213 
    214   // The default context slot layout; indices are FixedArray slot indices.
    215   enum {
    216     // These slots are in all contexts.
    217     CLOSURE_INDEX,
    218     PREVIOUS_INDEX,
    219     // The extension slot is used for either the global object (in global
    220     // contexts), eval extension object (function contexts), subject of with
    221     // (with contexts), or the variable name (catch contexts), the serialized
    222     // scope info (block contexts).
    223     EXTENSION_INDEX,
    224     GLOBAL_INDEX,
    225     MIN_CONTEXT_SLOTS,
    226 
    227     // This slot holds the thrown value in catch contexts.
    228     THROWN_OBJECT_INDEX = MIN_CONTEXT_SLOTS,
    229 
    230     // These slots are only in global contexts.
    231     GLOBAL_PROXY_INDEX = MIN_CONTEXT_SLOTS,
    232     SECURITY_TOKEN_INDEX,
    233     ARGUMENTS_BOILERPLATE_INDEX,
    234     ALIASED_ARGUMENTS_BOILERPLATE_INDEX,
    235     STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX,
    236     REGEXP_RESULT_MAP_INDEX,
    237     FUNCTION_MAP_INDEX,
    238     STRICT_MODE_FUNCTION_MAP_INDEX,
    239     FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
    240     STRICT_MODE_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
    241     FUNCTION_INSTANCE_MAP_INDEX,
    242     STRICT_MODE_FUNCTION_INSTANCE_MAP_INDEX,
    243     INITIAL_OBJECT_PROTOTYPE_INDEX,
    244     BOOLEAN_FUNCTION_INDEX,
    245     NUMBER_FUNCTION_INDEX,
    246     STRING_FUNCTION_INDEX,
    247     STRING_FUNCTION_PROTOTYPE_MAP_INDEX,
    248     OBJECT_FUNCTION_INDEX,
    249     INTERNAL_ARRAY_FUNCTION_INDEX,
    250     ARRAY_FUNCTION_INDEX,
    251     SMI_JS_ARRAY_MAP_INDEX,
    252     DOUBLE_JS_ARRAY_MAP_INDEX,
    253     OBJECT_JS_ARRAY_MAP_INDEX,
    254     DATE_FUNCTION_INDEX,
    255     JSON_OBJECT_INDEX,
    256     REGEXP_FUNCTION_INDEX,
    257     CREATE_DATE_FUN_INDEX,
    258     TO_NUMBER_FUN_INDEX,
    259     TO_STRING_FUN_INDEX,
    260     TO_DETAIL_STRING_FUN_INDEX,
    261     TO_OBJECT_FUN_INDEX,
    262     TO_INTEGER_FUN_INDEX,
    263     TO_UINT32_FUN_INDEX,
    264     TO_INT32_FUN_INDEX,
    265     TO_BOOLEAN_FUN_INDEX,
    266     GLOBAL_EVAL_FUN_INDEX,
    267     INSTANTIATE_FUN_INDEX,
    268     CONFIGURE_INSTANCE_FUN_INDEX,
    269     MESSAGE_LISTENERS_INDEX,
    270     MAKE_MESSAGE_FUN_INDEX,
    271     GET_STACK_TRACE_LINE_INDEX,
    272     CONFIGURE_GLOBAL_INDEX,
    273     FUNCTION_CACHE_INDEX,
    274     JSFUNCTION_RESULT_CACHES_INDEX,
    275     NORMALIZED_MAP_CACHE_INDEX,
    276     RUNTIME_CONTEXT_INDEX,
    277     CALL_AS_FUNCTION_DELEGATE_INDEX,
    278     CALL_AS_CONSTRUCTOR_DELEGATE_INDEX,
    279     SCRIPT_FUNCTION_INDEX,
    280     OPAQUE_REFERENCE_FUNCTION_INDEX,
    281     CONTEXT_EXTENSION_FUNCTION_INDEX,
    282     OUT_OF_MEMORY_INDEX,
    283     CONTEXT_DATA_INDEX,
    284     ALLOW_CODE_GEN_FROM_STRINGS_INDEX,
    285     TO_COMPLETE_PROPERTY_DESCRIPTOR_INDEX,
    286     DERIVED_HAS_TRAP_INDEX,
    287     DERIVED_GET_TRAP_INDEX,
    288     DERIVED_SET_TRAP_INDEX,
    289     PROXY_ENUMERATE,
    290     RANDOM_SEED_INDEX,
    291 
    292     // Properties from here are treated as weak references by the full GC.
    293     // Scavenge treats them as strong references.
    294     OPTIMIZED_FUNCTIONS_LIST,  // Weak.
    295     MAP_CACHE_INDEX,  // Weak.
    296     NEXT_CONTEXT_LINK,  // Weak.
    297 
    298     // Total number of slots.
    299     GLOBAL_CONTEXT_SLOTS,
    300 
    301     FIRST_WEAK_SLOT = OPTIMIZED_FUNCTIONS_LIST
    302   };
    303 
    304   // Direct slot access.
    305   JSFunction* closure() { return JSFunction::cast(get(CLOSURE_INDEX)); }
    306   void set_closure(JSFunction* closure) { set(CLOSURE_INDEX, closure); }
    307 
    308   Context* previous() {
    309     Object* result = unchecked_previous();
    310     ASSERT(IsBootstrappingOrContext(result));
    311     return reinterpret_cast<Context*>(result);
    312   }
    313   void set_previous(Context* context) { set(PREVIOUS_INDEX, context); }
    314 
    315   bool has_extension() { return extension() != NULL; }
    316   Object* extension() { return get(EXTENSION_INDEX); }
    317   void set_extension(Object* object) { set(EXTENSION_INDEX, object); }
    318 
    319   // Get the context where var declarations will be hoisted to, which
    320   // may be the context itself.
    321   Context* declaration_context();
    322 
    323   GlobalObject* global() {
    324     Object* result = get(GLOBAL_INDEX);
    325     ASSERT(IsBootstrappingOrGlobalObject(result));
    326     return reinterpret_cast<GlobalObject*>(result);
    327   }
    328   void set_global(GlobalObject* global) { set(GLOBAL_INDEX, global); }
    329 
    330   // Returns a JSGlobalProxy object or null.
    331   JSObject* global_proxy();
    332   void set_global_proxy(JSObject* global);
    333 
    334   // The builtins object.
    335   JSBuiltinsObject* builtins();
    336 
    337   // Compute the global context by traversing the context chain.
    338   Context* global_context();
    339 
    340   // Predicates for context types.  IsGlobalContext is defined on Object
    341   // because we frequently have to know if arbitrary objects are global
    342   // contexts.
    343   bool IsFunctionContext() {
    344     Map* map = this->map();
    345     return map == map->GetHeap()->function_context_map();
    346   }
    347   bool IsCatchContext() {
    348     Map* map = this->map();
    349     return map == map->GetHeap()->catch_context_map();
    350   }
    351   bool IsWithContext() {
    352     Map* map = this->map();
    353     return map == map->GetHeap()->with_context_map();
    354   }
    355   bool IsBlockContext() {
    356     Map* map = this->map();
    357     return map == map->GetHeap()->block_context_map();
    358   }
    359   bool IsModuleContext() {
    360     Map* map = this->map();
    361     return map == map->GetHeap()->module_context_map();
    362   }
    363 
    364   // Tells whether the global context is marked with out of memory.
    365   inline bool has_out_of_memory();
    366 
    367   // Mark the global context with out of memory.
    368   inline void mark_out_of_memory();
    369 
    370   // A global context hold a list of all functions which have been optimized.
    371   void AddOptimizedFunction(JSFunction* function);
    372   void RemoveOptimizedFunction(JSFunction* function);
    373   Object* OptimizedFunctionsListHead();
    374   void ClearOptimizedFunctions();
    375 
    376   static int GetContextMapIndexFromElementsKind(
    377       ElementsKind elements_kind) {
    378     if (elements_kind == FAST_DOUBLE_ELEMENTS) {
    379       return Context::DOUBLE_JS_ARRAY_MAP_INDEX;
    380     } else if (elements_kind == FAST_ELEMENTS) {
    381       return Context::OBJECT_JS_ARRAY_MAP_INDEX;
    382     } else {
    383       ASSERT(elements_kind == FAST_SMI_ONLY_ELEMENTS);
    384       return Context::SMI_JS_ARRAY_MAP_INDEX;
    385     }
    386   }
    387 
    388 #define GLOBAL_CONTEXT_FIELD_ACCESSORS(index, type, name) \
    389   void  set_##name(type* value) {                         \
    390     ASSERT(IsGlobalContext());                            \
    391     set(index, value);                                    \
    392   }                                                       \
    393   type* name() {                                          \
    394     ASSERT(IsGlobalContext());                            \
    395     return type::cast(get(index));                        \
    396   }
    397   GLOBAL_CONTEXT_FIELDS(GLOBAL_CONTEXT_FIELD_ACCESSORS)
    398 #undef GLOBAL_CONTEXT_FIELD_ACCESSORS
    399 
    400   // Lookup the the slot called name, starting with the current context.
    401   // There are three possibilities:
    402   //
    403   // 1) result->IsContext():
    404   //    The binding was found in a context.  *index is always the
    405   //    non-negative slot index.  *attributes is NONE for var and let
    406   //    declarations, READ_ONLY for const declarations (never ABSENT).
    407   //
    408   // 2) result->IsJSObject():
    409   //    The binding was found as a named property in a context extension
    410   //    object (i.e., was introduced via eval), as a property on the subject
    411   //    of with, or as a property of the global object.  *index is -1 and
    412   //    *attributes is not ABSENT.
    413   //
    414   // 3) result.is_null():
    415   //    There was no binding found, *index is always -1 and *attributes is
    416   //    always ABSENT.
    417   Handle<Object> Lookup(Handle<String> name,
    418                         ContextLookupFlags flags,
    419                         int* index,
    420                         PropertyAttributes* attributes,
    421                         BindingFlags* binding_flags);
    422 
    423   // Code generation support.
    424   static int SlotOffset(int index) {
    425     return kHeaderSize + index * kPointerSize - kHeapObjectTag;
    426   }
    427 
    428   static const int kSize = kHeaderSize + GLOBAL_CONTEXT_SLOTS * kPointerSize;
    429 
    430   // GC support.
    431   typedef FixedBodyDescriptor<
    432       kHeaderSize, kSize, kSize> ScavengeBodyDescriptor;
    433 
    434   typedef FixedBodyDescriptor<
    435       kHeaderSize,
    436       kHeaderSize + FIRST_WEAK_SLOT * kPointerSize,
    437       kSize> MarkCompactBodyDescriptor;
    438 
    439  private:
    440   // Unchecked access to the slots.
    441   Object* unchecked_previous() { return get(PREVIOUS_INDEX); }
    442 
    443 #ifdef DEBUG
    444   // Bootstrapping-aware type checks.
    445   static bool IsBootstrappingOrContext(Object* object);
    446   static bool IsBootstrappingOrGlobalObject(Object* object);
    447 #endif
    448 };
    449 
    450 } }  // namespace v8::internal
    451 
    452 #endif  // V8_CONTEXTS_H_
    453