Home | History | Annotate | Download | only in src
      1 // Copyright 2012 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_H_
      6 #define V8_CONTEXTS_H_
      7 
      8 #include "src/heap.h"
      9 #include "src/objects.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 
     14 
     15 enum ContextLookupFlags {
     16   FOLLOW_CONTEXT_CHAIN = 1,
     17   FOLLOW_PROTOTYPE_CHAIN = 2,
     18 
     19   DONT_FOLLOW_CHAINS = 0,
     20   FOLLOW_CHAINS = FOLLOW_CONTEXT_CHAIN | FOLLOW_PROTOTYPE_CHAIN
     21 };
     22 
     23 
     24 // ES5 10.2 defines lexical environments with mutable and immutable bindings.
     25 // Immutable bindings have two states, initialized and uninitialized, and
     26 // their state is changed by the InitializeImmutableBinding method. The
     27 // BindingFlags enum represents information if a binding has definitely been
     28 // initialized. A mutable binding does not need to be checked and thus has
     29 // the BindingFlag MUTABLE_IS_INITIALIZED.
     30 //
     31 // There are two possibilities for immutable bindings
     32 //  * 'const' declared variables. They are initialized when evaluating the
     33 //    corresponding declaration statement. They need to be checked for being
     34 //    initialized and thus get the flag IMMUTABLE_CHECK_INITIALIZED.
     35 //  * The function name of a named function literal. The binding is immediately
     36 //    initialized when entering the function and thus does not need to be
     37 //    checked. it gets the BindingFlag IMMUTABLE_IS_INITIALIZED.
     38 // Accessing an uninitialized binding produces the undefined value.
     39 //
     40 // The harmony proposal for block scoped bindings also introduces the
     41 // uninitialized state for mutable bindings.
     42 //  * A 'let' declared variable. They are initialized when evaluating the
     43 //    corresponding declaration statement. They need to be checked for being
     44 //    initialized and thus get the flag MUTABLE_CHECK_INITIALIZED.
     45 //  * A 'var' declared variable. It is initialized immediately upon creation
     46 //    and thus doesn't need to be checked. It gets the flag
     47 //    MUTABLE_IS_INITIALIZED.
     48 //  * Catch bound variables, function parameters and variables introduced by
     49 //    function declarations are initialized immediately and do not need to be
     50 //    checked. Thus they get the flag MUTABLE_IS_INITIALIZED.
     51 // Immutable bindings in harmony mode get the _HARMONY flag variants. Accessing
     52 // an uninitialized binding produces a reference error.
     53 //
     54 // In V8 uninitialized bindings are set to the hole value upon creation and set
     55 // to a different value upon initialization.
     56 enum BindingFlags {
     57   MUTABLE_IS_INITIALIZED,
     58   MUTABLE_CHECK_INITIALIZED,
     59   IMMUTABLE_IS_INITIALIZED,
     60   IMMUTABLE_CHECK_INITIALIZED,
     61   IMMUTABLE_IS_INITIALIZED_HARMONY,
     62   IMMUTABLE_CHECK_INITIALIZED_HARMONY,
     63   MISSING_BINDING
     64 };
     65 
     66 
     67 // Heap-allocated activation contexts.
     68 //
     69 // Contexts are implemented as FixedArray objects; the Context
     70 // class is a convenience interface casted on a FixedArray object.
     71 //
     72 // Note: Context must have no virtual functions and Context objects
     73 // must always be allocated via Heap::AllocateContext() or
     74 // Factory::NewContext.
     75 
     76 #define NATIVE_CONTEXT_FIELDS(V) \
     77   V(GLOBAL_PROXY_INDEX, JSObject, global_proxy_object) \
     78   V(SECURITY_TOKEN_INDEX, Object, security_token) \
     79   V(BOOLEAN_FUNCTION_INDEX, JSFunction, boolean_function) \
     80   V(NUMBER_FUNCTION_INDEX, JSFunction, number_function) \
     81   V(STRING_FUNCTION_INDEX, JSFunction, string_function) \
     82   V(STRING_FUNCTION_PROTOTYPE_MAP_INDEX, Map, string_function_prototype_map) \
     83   V(SYMBOL_FUNCTION_INDEX, JSFunction, symbol_function) \
     84   V(OBJECT_FUNCTION_INDEX, JSFunction, object_function) \
     85   V(INTERNAL_ARRAY_FUNCTION_INDEX, JSFunction, internal_array_function) \
     86   V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \
     87   V(JS_ARRAY_MAPS_INDEX, Object, js_array_maps) \
     88   V(DATE_FUNCTION_INDEX, JSFunction, date_function) \
     89   V(JSON_OBJECT_INDEX, JSObject, json_object) \
     90   V(REGEXP_FUNCTION_INDEX, JSFunction, regexp_function) \
     91   V(INITIAL_OBJECT_PROTOTYPE_INDEX, JSObject, initial_object_prototype) \
     92   V(INITIAL_ARRAY_PROTOTYPE_INDEX, JSObject, initial_array_prototype) \
     93   V(CREATE_DATE_FUN_INDEX, JSFunction,  create_date_fun) \
     94   V(TO_NUMBER_FUN_INDEX, JSFunction, to_number_fun) \
     95   V(TO_STRING_FUN_INDEX, JSFunction, to_string_fun) \
     96   V(TO_DETAIL_STRING_FUN_INDEX, JSFunction, to_detail_string_fun) \
     97   V(TO_OBJECT_FUN_INDEX, JSFunction, to_object_fun) \
     98   V(TO_INTEGER_FUN_INDEX, JSFunction, to_integer_fun) \
     99   V(TO_UINT32_FUN_INDEX, JSFunction, to_uint32_fun) \
    100   V(TO_INT32_FUN_INDEX, JSFunction, to_int32_fun) \
    101   V(GLOBAL_EVAL_FUN_INDEX, JSFunction, global_eval_fun) \
    102   V(INSTANTIATE_FUN_INDEX, JSFunction, instantiate_fun) \
    103   V(CONFIGURE_INSTANCE_FUN_INDEX, JSFunction, configure_instance_fun) \
    104   V(ARRAY_BUFFER_FUN_INDEX, JSFunction, array_buffer_fun) \
    105   V(UINT8_ARRAY_FUN_INDEX, JSFunction, uint8_array_fun) \
    106   V(INT8_ARRAY_FUN_INDEX, JSFunction, int8_array_fun) \
    107   V(UINT16_ARRAY_FUN_INDEX, JSFunction, uint16_array_fun) \
    108   V(INT16_ARRAY_FUN_INDEX, JSFunction, int16_array_fun) \
    109   V(UINT32_ARRAY_FUN_INDEX, JSFunction, uint32_array_fun) \
    110   V(INT32_ARRAY_FUN_INDEX, JSFunction, int32_array_fun) \
    111   V(FLOAT32_ARRAY_FUN_INDEX, JSFunction, float32_array_fun) \
    112   V(FLOAT64_ARRAY_FUN_INDEX, JSFunction, float64_array_fun) \
    113   V(UINT8_CLAMPED_ARRAY_FUN_INDEX, JSFunction, uint8_clamped_array_fun) \
    114   V(INT8_ARRAY_EXTERNAL_MAP_INDEX, Map, int8_array_external_map) \
    115   V(UINT8_ARRAY_EXTERNAL_MAP_INDEX, Map, uint8_array_external_map) \
    116   V(INT16_ARRAY_EXTERNAL_MAP_INDEX, Map, int16_array_external_map) \
    117   V(UINT16_ARRAY_EXTERNAL_MAP_INDEX, Map, uint16_array_external_map) \
    118   V(INT32_ARRAY_EXTERNAL_MAP_INDEX, Map, int32_array_external_map) \
    119   V(UINT32_ARRAY_EXTERNAL_MAP_INDEX, Map, uint32_array_external_map) \
    120   V(FLOAT32_ARRAY_EXTERNAL_MAP_INDEX, Map, float32_array_external_map) \
    121   V(FLOAT64_ARRAY_EXTERNAL_MAP_INDEX, Map, float64_array_external_map) \
    122   V(UINT8_CLAMPED_ARRAY_EXTERNAL_MAP_INDEX, Map, \
    123       uint8_clamped_array_external_map) \
    124   V(DATA_VIEW_FUN_INDEX, JSFunction, data_view_fun) \
    125   V(SLOPPY_FUNCTION_MAP_INDEX, Map, sloppy_function_map) \
    126   V(SLOPPY_FUNCTION_WITH_READONLY_PROTOTYPE_MAP_INDEX, Map, \
    127     sloppy_function_with_readonly_prototype_map) \
    128   V(STRICT_FUNCTION_MAP_INDEX, Map, strict_function_map) \
    129   V(SLOPPY_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, \
    130     sloppy_function_without_prototype_map) \
    131   V(STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, \
    132     strict_function_without_prototype_map) \
    133   V(BOUND_FUNCTION_MAP_INDEX, Map, bound_function_map) \
    134   V(REGEXP_RESULT_MAP_INDEX, Map, regexp_result_map)\
    135   V(SLOPPY_ARGUMENTS_BOILERPLATE_INDEX, JSObject, \
    136     sloppy_arguments_boilerplate) \
    137   V(ALIASED_ARGUMENTS_BOILERPLATE_INDEX, JSObject, \
    138     aliased_arguments_boilerplate) \
    139   V(STRICT_ARGUMENTS_BOILERPLATE_INDEX, JSObject, \
    140     strict_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(MAP_CACHE_INDEX, Object, map_cache) \
    156   V(EMBEDDER_DATA_INDEX, FixedArray, embedder_data) \
    157   V(ALLOW_CODE_GEN_FROM_STRINGS_INDEX, Object, allow_code_gen_from_strings) \
    158   V(ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX, Object, \
    159     error_message_for_code_gen_from_strings) \
    160   V(IS_PROMISE_INDEX, JSFunction, is_promise) \
    161   V(PROMISE_CREATE_INDEX, JSFunction, promise_create) \
    162   V(PROMISE_RESOLVE_INDEX, JSFunction, promise_resolve) \
    163   V(PROMISE_REJECT_INDEX, JSFunction, promise_reject) \
    164   V(PROMISE_CHAIN_INDEX, JSFunction, promise_chain) \
    165   V(PROMISE_CATCH_INDEX, JSFunction, promise_catch) \
    166   V(PROMISE_THEN_INDEX, JSFunction, promise_then) \
    167   V(TO_COMPLETE_PROPERTY_DESCRIPTOR_INDEX, JSFunction, \
    168     to_complete_property_descriptor) \
    169   V(DERIVED_HAS_TRAP_INDEX, JSFunction, derived_has_trap) \
    170   V(DERIVED_GET_TRAP_INDEX, JSFunction, derived_get_trap) \
    171   V(DERIVED_SET_TRAP_INDEX, JSFunction, derived_set_trap) \
    172   V(PROXY_ENUMERATE_INDEX, JSFunction, proxy_enumerate) \
    173   V(OBSERVERS_NOTIFY_CHANGE_INDEX, JSFunction, observers_notify_change) \
    174   V(OBSERVERS_ENQUEUE_SPLICE_INDEX, JSFunction, observers_enqueue_splice) \
    175   V(OBSERVERS_BEGIN_SPLICE_INDEX, JSFunction, \
    176     observers_begin_perform_splice) \
    177   V(OBSERVERS_END_SPLICE_INDEX, JSFunction, \
    178     observers_end_perform_splice) \
    179   V(NATIVE_OBJECT_OBSERVE_INDEX, JSFunction, \
    180     native_object_observe) \
    181   V(NATIVE_OBJECT_GET_NOTIFIER_INDEX, JSFunction, \
    182     native_object_get_notifier) \
    183   V(NATIVE_OBJECT_NOTIFIER_PERFORM_CHANGE, JSFunction, \
    184     native_object_notifier_perform_change) \
    185   V(SLOPPY_GENERATOR_FUNCTION_MAP_INDEX, Map, sloppy_generator_function_map) \
    186   V(STRICT_GENERATOR_FUNCTION_MAP_INDEX, Map, strict_generator_function_map) \
    187   V(GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX, Map, \
    188     generator_object_prototype_map) \
    189   V(ITERATOR_RESULT_MAP_INDEX, Map, iterator_result_map) \
    190   V(MAP_ITERATOR_MAP_INDEX, Map, map_iterator_map) \
    191   V(SET_ITERATOR_MAP_INDEX, Map, set_iterator_map) \
    192   V(ITERATOR_SYMBOL_INDEX, Symbol, iterator_symbol)
    193 
    194 // JSFunctions are pairs (context, function code), sometimes also called
    195 // closures. A Context object is used to represent function contexts and
    196 // dynamically pushed 'with' contexts (or 'scopes' in ECMA-262 speak).
    197 //
    198 // At runtime, the contexts build a stack in parallel to the execution
    199 // stack, with the top-most context being the current context. All contexts
    200 // have the following slots:
    201 //
    202 // [ closure   ]  This is the current function. It is the same for all
    203 //                contexts inside a function. It provides access to the
    204 //                incoming context (i.e., the outer context, which may
    205 //                or may not become the current function's context), and
    206 //                it provides access to the functions code and thus it's
    207 //                scope information, which in turn contains the names of
    208 //                statically allocated context slots. The names are needed
    209 //                for dynamic lookups in the presence of 'with' or 'eval'.
    210 //
    211 // [ previous  ]  A pointer to the previous context. It is NULL for
    212 //                function contexts, and non-NULL for 'with' contexts.
    213 //                Used to implement the 'with' statement.
    214 //
    215 // [ extension ]  A pointer to an extension JSObject, or NULL. Used to
    216 //                implement 'with' statements and dynamic declarations
    217 //                (through 'eval'). The object in a 'with' statement is
    218 //                stored in the extension slot of a 'with' context.
    219 //                Dynamically declared variables/functions are also added
    220 //                to lazily allocated extension object. Context::Lookup
    221 //                searches the extension object for properties.
    222 //                For global and block contexts, contains the respective
    223 //                ScopeInfo.
    224 //                For module contexts, points back to the respective JSModule.
    225 //
    226 // [ global_object ]  A pointer to the global object. Provided for quick
    227 //                access to the global object from inside the code (since
    228 //                we always have a context pointer).
    229 //
    230 // In addition, function contexts may have statically allocated context slots
    231 // to store local variables/functions that are accessed from inner functions
    232 // (via static context addresses) or through 'eval' (dynamic context lookups).
    233 // The native context contains additional slots for fast access to native
    234 // properties.
    235 //
    236 // Finally, with Harmony scoping, the JSFunction representing a top level
    237 // script will have the GlobalContext rather than a FunctionContext.
    238 
    239 class Context: public FixedArray {
    240  public:
    241   // Conversions.
    242   static Context* cast(Object* context) {
    243     ASSERT(context->IsContext());
    244     return reinterpret_cast<Context*>(context);
    245   }
    246 
    247   // The default context slot layout; indices are FixedArray slot indices.
    248   enum {
    249     // These slots are in all contexts.
    250     CLOSURE_INDEX,
    251     PREVIOUS_INDEX,
    252     // The extension slot is used for either the global object (in global
    253     // contexts), eval extension object (function contexts), subject of with
    254     // (with contexts), or the variable name (catch contexts), the serialized
    255     // scope info (block contexts), or the module instance (module contexts).
    256     EXTENSION_INDEX,
    257     GLOBAL_OBJECT_INDEX,
    258     MIN_CONTEXT_SLOTS,
    259 
    260     // This slot holds the thrown value in catch contexts.
    261     THROWN_OBJECT_INDEX = MIN_CONTEXT_SLOTS,
    262 
    263     // These slots are only in native contexts.
    264     GLOBAL_PROXY_INDEX = MIN_CONTEXT_SLOTS,
    265     SECURITY_TOKEN_INDEX,
    266     SLOPPY_ARGUMENTS_BOILERPLATE_INDEX,
    267     ALIASED_ARGUMENTS_BOILERPLATE_INDEX,
    268     STRICT_ARGUMENTS_BOILERPLATE_INDEX,
    269     REGEXP_RESULT_MAP_INDEX,
    270     SLOPPY_FUNCTION_MAP_INDEX,
    271     SLOPPY_FUNCTION_WITH_READONLY_PROTOTYPE_MAP_INDEX,
    272     STRICT_FUNCTION_MAP_INDEX,
    273     SLOPPY_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
    274     STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
    275     BOUND_FUNCTION_MAP_INDEX,
    276     INITIAL_OBJECT_PROTOTYPE_INDEX,
    277     INITIAL_ARRAY_PROTOTYPE_INDEX,
    278     BOOLEAN_FUNCTION_INDEX,
    279     NUMBER_FUNCTION_INDEX,
    280     STRING_FUNCTION_INDEX,
    281     STRING_FUNCTION_PROTOTYPE_MAP_INDEX,
    282     SYMBOL_FUNCTION_INDEX,
    283     OBJECT_FUNCTION_INDEX,
    284     INTERNAL_ARRAY_FUNCTION_INDEX,
    285     ARRAY_FUNCTION_INDEX,
    286     JS_ARRAY_MAPS_INDEX,
    287     DATE_FUNCTION_INDEX,
    288     JSON_OBJECT_INDEX,
    289     REGEXP_FUNCTION_INDEX,
    290     CREATE_DATE_FUN_INDEX,
    291     TO_NUMBER_FUN_INDEX,
    292     TO_STRING_FUN_INDEX,
    293     TO_DETAIL_STRING_FUN_INDEX,
    294     TO_OBJECT_FUN_INDEX,
    295     TO_INTEGER_FUN_INDEX,
    296     TO_UINT32_FUN_INDEX,
    297     TO_INT32_FUN_INDEX,
    298     TO_BOOLEAN_FUN_INDEX,
    299     GLOBAL_EVAL_FUN_INDEX,
    300     INSTANTIATE_FUN_INDEX,
    301     CONFIGURE_INSTANCE_FUN_INDEX,
    302     ARRAY_BUFFER_FUN_INDEX,
    303     UINT8_ARRAY_FUN_INDEX,
    304     INT8_ARRAY_FUN_INDEX,
    305     UINT16_ARRAY_FUN_INDEX,
    306     INT16_ARRAY_FUN_INDEX,
    307     UINT32_ARRAY_FUN_INDEX,
    308     INT32_ARRAY_FUN_INDEX,
    309     FLOAT32_ARRAY_FUN_INDEX,
    310     FLOAT64_ARRAY_FUN_INDEX,
    311     UINT8_CLAMPED_ARRAY_FUN_INDEX,
    312     INT8_ARRAY_EXTERNAL_MAP_INDEX,
    313     UINT8_ARRAY_EXTERNAL_MAP_INDEX,
    314     INT16_ARRAY_EXTERNAL_MAP_INDEX,
    315     UINT16_ARRAY_EXTERNAL_MAP_INDEX,
    316     INT32_ARRAY_EXTERNAL_MAP_INDEX,
    317     UINT32_ARRAY_EXTERNAL_MAP_INDEX,
    318     FLOAT32_ARRAY_EXTERNAL_MAP_INDEX,
    319     FLOAT64_ARRAY_EXTERNAL_MAP_INDEX,
    320     UINT8_CLAMPED_ARRAY_EXTERNAL_MAP_INDEX,
    321     DATA_VIEW_FUN_INDEX,
    322     MESSAGE_LISTENERS_INDEX,
    323     MAKE_MESSAGE_FUN_INDEX,
    324     GET_STACK_TRACE_LINE_INDEX,
    325     CONFIGURE_GLOBAL_INDEX,
    326     FUNCTION_CACHE_INDEX,
    327     JSFUNCTION_RESULT_CACHES_INDEX,
    328     NORMALIZED_MAP_CACHE_INDEX,
    329     RUNTIME_CONTEXT_INDEX,
    330     CALL_AS_FUNCTION_DELEGATE_INDEX,
    331     CALL_AS_CONSTRUCTOR_DELEGATE_INDEX,
    332     SCRIPT_FUNCTION_INDEX,
    333     OPAQUE_REFERENCE_FUNCTION_INDEX,
    334     CONTEXT_EXTENSION_FUNCTION_INDEX,
    335     OUT_OF_MEMORY_INDEX,
    336     EMBEDDER_DATA_INDEX,
    337     ALLOW_CODE_GEN_FROM_STRINGS_INDEX,
    338     ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX,
    339     RUN_MICROTASKS_INDEX,
    340     ENQUEUE_MICROTASK_INDEX,
    341     IS_PROMISE_INDEX,
    342     PROMISE_CREATE_INDEX,
    343     PROMISE_RESOLVE_INDEX,
    344     PROMISE_REJECT_INDEX,
    345     PROMISE_CHAIN_INDEX,
    346     PROMISE_CATCH_INDEX,
    347     PROMISE_THEN_INDEX,
    348     TO_COMPLETE_PROPERTY_DESCRIPTOR_INDEX,
    349     DERIVED_HAS_TRAP_INDEX,
    350     DERIVED_GET_TRAP_INDEX,
    351     DERIVED_SET_TRAP_INDEX,
    352     PROXY_ENUMERATE_INDEX,
    353     OBSERVERS_NOTIFY_CHANGE_INDEX,
    354     OBSERVERS_ENQUEUE_SPLICE_INDEX,
    355     OBSERVERS_BEGIN_SPLICE_INDEX,
    356     OBSERVERS_END_SPLICE_INDEX,
    357     NATIVE_OBJECT_OBSERVE_INDEX,
    358     NATIVE_OBJECT_GET_NOTIFIER_INDEX,
    359     NATIVE_OBJECT_NOTIFIER_PERFORM_CHANGE,
    360     SLOPPY_GENERATOR_FUNCTION_MAP_INDEX,
    361     STRICT_GENERATOR_FUNCTION_MAP_INDEX,
    362     GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX,
    363     ITERATOR_RESULT_MAP_INDEX,
    364     MAP_ITERATOR_MAP_INDEX,
    365     SET_ITERATOR_MAP_INDEX,
    366     ITERATOR_SYMBOL_INDEX,
    367 
    368     // Properties from here are treated as weak references by the full GC.
    369     // Scavenge treats them as strong references.
    370     OPTIMIZED_FUNCTIONS_LIST,  // Weak.
    371     OPTIMIZED_CODE_LIST,       // Weak.
    372     DEOPTIMIZED_CODE_LIST,     // Weak.
    373     MAP_CACHE_INDEX,           // Weak.
    374     NEXT_CONTEXT_LINK,         // Weak.
    375 
    376     // Total number of slots.
    377     NATIVE_CONTEXT_SLOTS,
    378 
    379     FIRST_WEAK_SLOT = OPTIMIZED_FUNCTIONS_LIST
    380   };
    381 
    382   // Direct slot access.
    383   JSFunction* closure() { return JSFunction::cast(get(CLOSURE_INDEX)); }
    384   void set_closure(JSFunction* closure) { set(CLOSURE_INDEX, closure); }
    385 
    386   Context* previous() {
    387     Object* result = unchecked_previous();
    388     ASSERT(IsBootstrappingOrValidParentContext(result, this));
    389     return reinterpret_cast<Context*>(result);
    390   }
    391   void set_previous(Context* context) { set(PREVIOUS_INDEX, context); }
    392 
    393   bool has_extension() { return extension() != NULL; }
    394   Object* extension() { return get(EXTENSION_INDEX); }
    395   void set_extension(Object* object) { set(EXTENSION_INDEX, object); }
    396 
    397   JSModule* module() { return JSModule::cast(get(EXTENSION_INDEX)); }
    398   void set_module(JSModule* module) { set(EXTENSION_INDEX, module); }
    399 
    400   // Get the context where var declarations will be hoisted to, which
    401   // may be the context itself.
    402   Context* declaration_context();
    403 
    404   GlobalObject* global_object() {
    405     Object* result = get(GLOBAL_OBJECT_INDEX);
    406     ASSERT(IsBootstrappingOrGlobalObject(this->GetIsolate(), result));
    407     return reinterpret_cast<GlobalObject*>(result);
    408   }
    409   void set_global_object(GlobalObject* object) {
    410     set(GLOBAL_OBJECT_INDEX, object);
    411   }
    412 
    413   // Returns a JSGlobalProxy object or null.
    414   JSObject* global_proxy();
    415   void set_global_proxy(JSObject* global);
    416 
    417   // The builtins object.
    418   JSBuiltinsObject* builtins();
    419 
    420   // Get the innermost global context by traversing the context chain.
    421   Context* global_context();
    422 
    423   // Compute the native context by traversing the context chain.
    424   Context* native_context();
    425 
    426   // Predicates for context types.  IsNativeContext is also defined on Object
    427   // because we frequently have to know if arbitrary objects are natives
    428   // contexts.
    429   bool IsNativeContext() {
    430     Map* map = this->map();
    431     return map == map->GetHeap()->native_context_map();
    432   }
    433   bool IsFunctionContext() {
    434     Map* map = this->map();
    435     return map == map->GetHeap()->function_context_map();
    436   }
    437   bool IsCatchContext() {
    438     Map* map = this->map();
    439     return map == map->GetHeap()->catch_context_map();
    440   }
    441   bool IsWithContext() {
    442     Map* map = this->map();
    443     return map == map->GetHeap()->with_context_map();
    444   }
    445   bool IsBlockContext() {
    446     Map* map = this->map();
    447     return map == map->GetHeap()->block_context_map();
    448   }
    449   bool IsModuleContext() {
    450     Map* map = this->map();
    451     return map == map->GetHeap()->module_context_map();
    452   }
    453   bool IsGlobalContext() {
    454     Map* map = this->map();
    455     return map == map->GetHeap()->global_context_map();
    456   }
    457 
    458   bool HasSameSecurityTokenAs(Context* that) {
    459     return this->global_object()->native_context()->security_token() ==
    460         that->global_object()->native_context()->security_token();
    461   }
    462 
    463   // A native context holds a list of all functions with optimized code.
    464   void AddOptimizedFunction(JSFunction* function);
    465   void RemoveOptimizedFunction(JSFunction* function);
    466   void SetOptimizedFunctionsListHead(Object* head);
    467   Object* OptimizedFunctionsListHead();
    468 
    469   // The native context also stores a list of all optimized code and a
    470   // list of all deoptimized code, which are needed by the deoptimizer.
    471   void AddOptimizedCode(Code* code);
    472   void SetOptimizedCodeListHead(Object* head);
    473   Object* OptimizedCodeListHead();
    474   void SetDeoptimizedCodeListHead(Object* head);
    475   Object* DeoptimizedCodeListHead();
    476 
    477   Handle<Object> ErrorMessageForCodeGenerationFromStrings();
    478 
    479 #define NATIVE_CONTEXT_FIELD_ACCESSORS(index, type, name) \
    480   void  set_##name(type* value) {                         \
    481     ASSERT(IsNativeContext());                            \
    482     set(index, value);                                    \
    483   }                                                       \
    484   bool is_##name(type* value) {                           \
    485     ASSERT(IsNativeContext());                            \
    486     return type::cast(get(index)) == value;               \
    487   }                                                       \
    488   type* name() {                                          \
    489     ASSERT(IsNativeContext());                            \
    490     return type::cast(get(index));                        \
    491   }
    492   NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELD_ACCESSORS)
    493 #undef NATIVE_CONTEXT_FIELD_ACCESSORS
    494 
    495   // Lookup the slot called name, starting with the current context.
    496   // There are three possibilities:
    497   //
    498   // 1) result->IsContext():
    499   //    The binding was found in a context.  *index is always the
    500   //    non-negative slot index.  *attributes is NONE for var and let
    501   //    declarations, READ_ONLY for const declarations (never ABSENT).
    502   //
    503   // 2) result->IsJSObject():
    504   //    The binding was found as a named property in a context extension
    505   //    object (i.e., was introduced via eval), as a property on the subject
    506   //    of with, or as a property of the global object.  *index is -1 and
    507   //    *attributes is not ABSENT.
    508   //
    509   // 3) result.is_null():
    510   //    There was no binding found, *index is always -1 and *attributes is
    511   //    always ABSENT.
    512   Handle<Object> Lookup(Handle<String> name,
    513                         ContextLookupFlags flags,
    514                         int* index,
    515                         PropertyAttributes* attributes,
    516                         BindingFlags* binding_flags);
    517 
    518   // Code generation support.
    519   static int SlotOffset(int index) {
    520     return kHeaderSize + index * kPointerSize - kHeapObjectTag;
    521   }
    522 
    523   static int FunctionMapIndex(StrictMode strict_mode, bool is_generator) {
    524     return is_generator
    525       ? (strict_mode == SLOPPY
    526          ? SLOPPY_GENERATOR_FUNCTION_MAP_INDEX
    527          : STRICT_GENERATOR_FUNCTION_MAP_INDEX)
    528       : (strict_mode == SLOPPY
    529          ? SLOPPY_FUNCTION_MAP_INDEX
    530          : STRICT_FUNCTION_MAP_INDEX);
    531   }
    532 
    533   static const int kSize = kHeaderSize + NATIVE_CONTEXT_SLOTS * kPointerSize;
    534 
    535   // GC support.
    536   typedef FixedBodyDescriptor<
    537       kHeaderSize, kSize, kSize> ScavengeBodyDescriptor;
    538 
    539   typedef FixedBodyDescriptor<
    540       kHeaderSize,
    541       kHeaderSize + FIRST_WEAK_SLOT * kPointerSize,
    542       kSize> MarkCompactBodyDescriptor;
    543 
    544  private:
    545   // Unchecked access to the slots.
    546   Object* unchecked_previous() { return get(PREVIOUS_INDEX); }
    547 
    548 #ifdef DEBUG
    549   // Bootstrapping-aware type checks.
    550   static bool IsBootstrappingOrValidParentContext(Object* object, Context* kid);
    551   static bool IsBootstrappingOrGlobalObject(Isolate* isolate, Object* object);
    552 #endif
    553 
    554   STATIC_ASSERT(kHeaderSize == Internals::kContextHeaderSize);
    555   STATIC_ASSERT(EMBEDDER_DATA_INDEX == Internals::kContextEmbedderDataIndex);
    556 };
    557 
    558 } }  // namespace v8::internal
    559 
    560 #endif  // V8_CONTEXTS_H_
    561