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
34namespace v8 {
35namespace internal {
36
37
38enum 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.
79enum 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
206class 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