• 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