• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
cast(Object * context)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.
closure()305    JSFunction* closure() { return JSFunction::cast(get(CLOSURE_INDEX)); }
set_closure(JSFunction * closure)306    void set_closure(JSFunction* closure) { set(CLOSURE_INDEX, closure); }
307  
previous()308    Context* previous() {
309      Object* result = unchecked_previous();
310      ASSERT(IsBootstrappingOrContext(result));
311      return reinterpret_cast<Context*>(result);
312    }
set_previous(Context * context)313    void set_previous(Context* context) { set(PREVIOUS_INDEX, context); }
314  
has_extension()315    bool has_extension() { return extension() != NULL; }
extension()316    Object* extension() { return get(EXTENSION_INDEX); }
set_extension(Object * object)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  
global()323    GlobalObject* global() {
324      Object* result = get(GLOBAL_INDEX);
325      ASSERT(IsBootstrappingOrGlobalObject(result));
326      return reinterpret_cast<GlobalObject*>(result);
327    }
set_global(GlobalObject * global)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.
IsFunctionContext()343    bool IsFunctionContext() {
344      Map* map = this->map();
345      return map == map->GetHeap()->function_context_map();
346    }
IsCatchContext()347    bool IsCatchContext() {
348      Map* map = this->map();
349      return map == map->GetHeap()->catch_context_map();
350    }
IsWithContext()351    bool IsWithContext() {
352      Map* map = this->map();
353      return map == map->GetHeap()->with_context_map();
354    }
IsBlockContext()355    bool IsBlockContext() {
356      Map* map = this->map();
357      return map == map->GetHeap()->block_context_map();
358    }
IsModuleContext()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  
GetContextMapIndexFromElementsKind(ElementsKind elements_kind)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.
SlotOffset(int index)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.
unchecked_previous()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