1 // Copyright 2006-2008 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 // Heap-allocated activation contexts. 48 // 49 // Contexts are implemented as FixedArray objects; the Context 50 // class is a convenience interface casted on a FixedArray object. 51 // 52 // Note: Context must have no virtual functions and Context objects 53 // must always be allocated via Heap::AllocateContext() or 54 // Factory::NewContext. 55 56 #define GLOBAL_CONTEXT_FIELDS(V) \ 57 V(GLOBAL_PROXY_INDEX, JSObject, global_proxy_object) \ 58 V(SECURITY_TOKEN_INDEX, Object, security_token) \ 59 V(BOOLEAN_FUNCTION_INDEX, JSFunction, boolean_function) \ 60 V(NUMBER_FUNCTION_INDEX, JSFunction, number_function) \ 61 V(STRING_FUNCTION_INDEX, JSFunction, string_function) \ 62 V(STRING_FUNCTION_PROTOTYPE_MAP_INDEX, Map, string_function_prototype_map) \ 63 V(OBJECT_FUNCTION_INDEX, JSFunction, object_function) \ 64 V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \ 65 V(DATE_FUNCTION_INDEX, JSFunction, date_function) \ 66 V(JSON_OBJECT_INDEX, JSObject, json_object) \ 67 V(REGEXP_FUNCTION_INDEX, JSFunction, regexp_function) \ 68 V(INITIAL_OBJECT_PROTOTYPE_INDEX, JSObject, initial_object_prototype) \ 69 V(CREATE_DATE_FUN_INDEX, JSFunction, create_date_fun) \ 70 V(TO_NUMBER_FUN_INDEX, JSFunction, to_number_fun) \ 71 V(TO_STRING_FUN_INDEX, JSFunction, to_string_fun) \ 72 V(TO_DETAIL_STRING_FUN_INDEX, JSFunction, to_detail_string_fun) \ 73 V(TO_OBJECT_FUN_INDEX, JSFunction, to_object_fun) \ 74 V(TO_INTEGER_FUN_INDEX, JSFunction, to_integer_fun) \ 75 V(TO_UINT32_FUN_INDEX, JSFunction, to_uint32_fun) \ 76 V(TO_INT32_FUN_INDEX, JSFunction, to_int32_fun) \ 77 V(GLOBAL_EVAL_FUN_INDEX, JSFunction, global_eval_fun) \ 78 V(INSTANTIATE_FUN_INDEX, JSFunction, instantiate_fun) \ 79 V(CONFIGURE_INSTANCE_FUN_INDEX, JSFunction, configure_instance_fun) \ 80 V(FUNCTION_MAP_INDEX, Map, function_map) \ 81 V(STRICT_MODE_FUNCTION_MAP_INDEX, Map, strict_mode_function_map) \ 82 V(FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, function_without_prototype_map) \ 83 V(STRICT_MODE_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, \ 84 strict_mode_function_without_prototype_map) \ 85 V(FUNCTION_INSTANCE_MAP_INDEX, Map, function_instance_map) \ 86 V(STRICT_MODE_FUNCTION_INSTANCE_MAP_INDEX, Map, \ 87 strict_mode_function_instance_map) \ 88 V(JS_ARRAY_MAP_INDEX, Map, js_array_map)\ 89 V(REGEXP_RESULT_MAP_INDEX, Map, regexp_result_map)\ 90 V(ARGUMENTS_BOILERPLATE_INDEX, JSObject, arguments_boilerplate) \ 91 V(STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX, JSObject, \ 92 strict_mode_arguments_boilerplate) \ 93 V(MESSAGE_LISTENERS_INDEX, JSObject, message_listeners) \ 94 V(MAKE_MESSAGE_FUN_INDEX, JSFunction, make_message_fun) \ 95 V(GET_STACK_TRACE_LINE_INDEX, JSFunction, get_stack_trace_line_fun) \ 96 V(CONFIGURE_GLOBAL_INDEX, JSFunction, configure_global_fun) \ 97 V(FUNCTION_CACHE_INDEX, JSObject, function_cache) \ 98 V(JSFUNCTION_RESULT_CACHES_INDEX, FixedArray, jsfunction_result_caches) \ 99 V(NORMALIZED_MAP_CACHE_INDEX, NormalizedMapCache, normalized_map_cache) \ 100 V(RUNTIME_CONTEXT_INDEX, Context, runtime_context) \ 101 V(CALL_AS_FUNCTION_DELEGATE_INDEX, JSFunction, call_as_function_delegate) \ 102 V(CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, JSFunction, \ 103 call_as_constructor_delegate) \ 104 V(SCRIPT_FUNCTION_INDEX, JSFunction, script_function) \ 105 V(OPAQUE_REFERENCE_FUNCTION_INDEX, JSFunction, opaque_reference_function) \ 106 V(CONTEXT_EXTENSION_FUNCTION_INDEX, JSFunction, context_extension_function) \ 107 V(OUT_OF_MEMORY_INDEX, Object, out_of_memory) \ 108 V(MAP_CACHE_INDEX, Object, map_cache) \ 109 V(CONTEXT_DATA_INDEX, Object, data) 110 111 // JSFunctions are pairs (context, function code), sometimes also called 112 // closures. A Context object is used to represent function contexts and 113 // dynamically pushed 'with' contexts (or 'scopes' in ECMA-262 speak). 114 // 115 // At runtime, the contexts build a stack in parallel to the execution 116 // stack, with the top-most context being the current context. All contexts 117 // have the following slots: 118 // 119 // [ closure ] This is the current function. It is the same for all 120 // contexts inside a function. It provides access to the 121 // incoming context (i.e., the outer context, which may 122 // or may not become the current function's context), and 123 // it provides access to the functions code and thus it's 124 // scope information, which in turn contains the names of 125 // statically allocated context slots. The names are needed 126 // for dynamic lookups in the presence of 'with' or 'eval'. 127 // 128 // [ fcontext ] A pointer to the innermost enclosing function context. 129 // It is the same for all contexts *allocated* inside a 130 // function, and the function context's fcontext points 131 // to itself. It is only needed for fast access of the 132 // function context (used for declarations, and static 133 // context slot access). 134 // 135 // [ previous ] A pointer to the previous context. It is NULL for 136 // function contexts, and non-NULL for 'with' contexts. 137 // Used to implement the 'with' statement. 138 // 139 // [ extension ] A pointer to an extension JSObject, or NULL. Used to 140 // implement 'with' statements and dynamic declarations 141 // (through 'eval'). The object in a 'with' statement is 142 // stored in the extension slot of a 'with' context. 143 // Dynamically declared variables/functions are also added 144 // to lazily allocated extension object. Context::Lookup 145 // searches the extension object for properties. 146 // 147 // [ global ] A pointer to the global object. Provided for quick 148 // access to the global object from inside the code (since 149 // we always have a context pointer). 150 // 151 // In addition, function contexts may have statically allocated context slots 152 // to store local variables/functions that are accessed from inner functions 153 // (via static context addresses) or through 'eval' (dynamic context lookups). 154 // Finally, the global context contains additional slots for fast access to 155 // global properties. 156 // 157 // We may be able to simplify the implementation: 158 // 159 // - We may be able to get rid of 'fcontext': We can always use the fact that 160 // previous == NULL for function contexts and so we can search for them. They 161 // are only needed when doing dynamic declarations, and the context chains 162 // tend to be very very short (depth of nesting of 'with' statements). At 163 // the moment we also use it in generated code for context slot accesses - 164 // and there we don't want a loop because of code bloat - but we may not 165 // need it there after all (see comment in codegen_*.cc). 166 // 167 // - If we cannot get rid of fcontext, consider making 'previous' never NULL 168 // except for the global context. This could simplify Context::Lookup. 169 170 class Context: public FixedArray { 171 public: 172 // Conversions. 173 static Context* cast(Object* context) { 174 ASSERT(context->IsContext()); 175 return reinterpret_cast<Context*>(context); 176 } 177 178 // The default context slot layout; indices are FixedArray slot indices. 179 enum { 180 // These slots are in all contexts. 181 CLOSURE_INDEX, 182 FCONTEXT_INDEX, 183 PREVIOUS_INDEX, 184 EXTENSION_INDEX, 185 GLOBAL_INDEX, 186 MIN_CONTEXT_SLOTS, 187 188 // These slots are only in global contexts. 189 GLOBAL_PROXY_INDEX = MIN_CONTEXT_SLOTS, 190 SECURITY_TOKEN_INDEX, 191 ARGUMENTS_BOILERPLATE_INDEX, 192 STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX, 193 JS_ARRAY_MAP_INDEX, 194 REGEXP_RESULT_MAP_INDEX, 195 FUNCTION_MAP_INDEX, 196 STRICT_MODE_FUNCTION_MAP_INDEX, 197 FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, 198 STRICT_MODE_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, 199 FUNCTION_INSTANCE_MAP_INDEX, 200 STRICT_MODE_FUNCTION_INSTANCE_MAP_INDEX, 201 INITIAL_OBJECT_PROTOTYPE_INDEX, 202 BOOLEAN_FUNCTION_INDEX, 203 NUMBER_FUNCTION_INDEX, 204 STRING_FUNCTION_INDEX, 205 STRING_FUNCTION_PROTOTYPE_MAP_INDEX, 206 OBJECT_FUNCTION_INDEX, 207 ARRAY_FUNCTION_INDEX, 208 DATE_FUNCTION_INDEX, 209 JSON_OBJECT_INDEX, 210 REGEXP_FUNCTION_INDEX, 211 CREATE_DATE_FUN_INDEX, 212 TO_NUMBER_FUN_INDEX, 213 TO_STRING_FUN_INDEX, 214 TO_DETAIL_STRING_FUN_INDEX, 215 TO_OBJECT_FUN_INDEX, 216 TO_INTEGER_FUN_INDEX, 217 TO_UINT32_FUN_INDEX, 218 TO_INT32_FUN_INDEX, 219 TO_BOOLEAN_FUN_INDEX, 220 GLOBAL_EVAL_FUN_INDEX, 221 INSTANTIATE_FUN_INDEX, 222 CONFIGURE_INSTANCE_FUN_INDEX, 223 MESSAGE_LISTENERS_INDEX, 224 MAKE_MESSAGE_FUN_INDEX, 225 GET_STACK_TRACE_LINE_INDEX, 226 CONFIGURE_GLOBAL_INDEX, 227 FUNCTION_CACHE_INDEX, 228 JSFUNCTION_RESULT_CACHES_INDEX, 229 NORMALIZED_MAP_CACHE_INDEX, 230 RUNTIME_CONTEXT_INDEX, 231 CALL_AS_FUNCTION_DELEGATE_INDEX, 232 CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, 233 SCRIPT_FUNCTION_INDEX, 234 OPAQUE_REFERENCE_FUNCTION_INDEX, 235 CONTEXT_EXTENSION_FUNCTION_INDEX, 236 OUT_OF_MEMORY_INDEX, 237 MAP_CACHE_INDEX, 238 CONTEXT_DATA_INDEX, 239 240 // Properties from here are treated as weak references by the full GC. 241 // Scavenge treats them as strong references. 242 OPTIMIZED_FUNCTIONS_LIST, // Weak. 243 NEXT_CONTEXT_LINK, // Weak. 244 245 // Total number of slots. 246 GLOBAL_CONTEXT_SLOTS, 247 248 FIRST_WEAK_SLOT = OPTIMIZED_FUNCTIONS_LIST 249 }; 250 251 // Direct slot access. 252 JSFunction* closure() { return JSFunction::cast(get(CLOSURE_INDEX)); } 253 void set_closure(JSFunction* closure) { set(CLOSURE_INDEX, closure); } 254 255 Context* fcontext() { return Context::cast(get(FCONTEXT_INDEX)); } 256 void set_fcontext(Context* context) { set(FCONTEXT_INDEX, context); } 257 258 Context* previous() { 259 Object* result = unchecked_previous(); 260 ASSERT(IsBootstrappingOrContext(result)); 261 return reinterpret_cast<Context*>(result); 262 } 263 void set_previous(Context* context) { set(PREVIOUS_INDEX, context); } 264 265 bool has_extension() { return unchecked_extension() != NULL; } 266 JSObject* extension() { return JSObject::cast(unchecked_extension()); } 267 void set_extension(JSObject* object) { set(EXTENSION_INDEX, object); } 268 269 GlobalObject* global() { 270 Object* result = get(GLOBAL_INDEX); 271 ASSERT(IsBootstrappingOrGlobalObject(result)); 272 return reinterpret_cast<GlobalObject*>(result); 273 } 274 void set_global(GlobalObject* global) { set(GLOBAL_INDEX, global); } 275 276 // Returns a JSGlobalProxy object or null. 277 JSObject* global_proxy(); 278 void set_global_proxy(JSObject* global); 279 280 // The builtins object. 281 JSBuiltinsObject* builtins(); 282 283 // Compute the global context by traversing the context chain. 284 Context* global_context(); 285 286 // Tells if this is a function context (as opposed to a 'with' context). 287 bool is_function_context() { return unchecked_previous() == NULL; } 288 289 // Tells whether the global context is marked with out of memory. 290 inline bool has_out_of_memory(); 291 292 // Mark the global context with out of memory. 293 inline void mark_out_of_memory(); 294 295 // The exception holder is the object used as a with object in 296 // the implementation of a catch block. 297 bool is_exception_holder(Object* object) { 298 return IsCatchContext() && extension() == object; 299 } 300 301 // A global context hold a list of all functions which have been optimized. 302 void AddOptimizedFunction(JSFunction* function); 303 void RemoveOptimizedFunction(JSFunction* function); 304 Object* OptimizedFunctionsListHead(); 305 void ClearOptimizedFunctions(); 306 307 #define GLOBAL_CONTEXT_FIELD_ACCESSORS(index, type, name) \ 308 void set_##name(type* value) { \ 309 ASSERT(IsGlobalContext()); \ 310 set(index, value); \ 311 } \ 312 type* name() { \ 313 ASSERT(IsGlobalContext()); \ 314 return type::cast(get(index)); \ 315 } 316 GLOBAL_CONTEXT_FIELDS(GLOBAL_CONTEXT_FIELD_ACCESSORS) 317 #undef GLOBAL_CONTEXT_FIELD_ACCESSORS 318 319 // Lookup the the slot called name, starting with the current context. 320 // There are 4 possible outcomes: 321 // 322 // 1) index_ >= 0 && result->IsContext(): 323 // most common case, the result is a Context, and index is the 324 // context slot index, and the slot exists. 325 // attributes == READ_ONLY for the function name variable, NONE otherwise. 326 // 327 // 2) index_ >= 0 && result->IsJSObject(): 328 // the result is the JSObject arguments object, the index is the parameter 329 // index, i.e., key into the arguments object, and the property exists. 330 // attributes != ABSENT. 331 // 332 // 3) index_ < 0 && result->IsJSObject(): 333 // the result is the JSObject extension context or the global object, 334 // and the name is the property name, and the property exists. 335 // attributes != ABSENT. 336 // 337 // 4) index_ < 0 && result.is_null(): 338 // there was no context found with the corresponding property. 339 // attributes == ABSENT. 340 Handle<Object> Lookup(Handle<String> name, ContextLookupFlags flags, 341 int* index_, PropertyAttributes* attributes); 342 343 // Determine if a local variable with the given name exists in a 344 // context. Do not consider context extension objects. This is 345 // used for compiling code using eval. If the context surrounding 346 // the eval call does not have a local variable with this name and 347 // does not contain a with statement the property is global unless 348 // it is shadowed by a property in an extension object introduced by 349 // eval. 350 bool GlobalIfNotShadowedByEval(Handle<String> name); 351 352 // Code generation support. 353 static int SlotOffset(int index) { 354 return kHeaderSize + index * kPointerSize - kHeapObjectTag; 355 } 356 357 static const int kSize = kHeaderSize + GLOBAL_CONTEXT_SLOTS * kPointerSize; 358 359 // GC support. 360 typedef FixedBodyDescriptor< 361 kHeaderSize, kSize, kSize> ScavengeBodyDescriptor; 362 363 typedef FixedBodyDescriptor< 364 kHeaderSize, 365 kHeaderSize + FIRST_WEAK_SLOT * kPointerSize, 366 kSize> MarkCompactBodyDescriptor; 367 368 private: 369 // Unchecked access to the slots. 370 Object* unchecked_previous() { return get(PREVIOUS_INDEX); } 371 Object* unchecked_extension() { return get(EXTENSION_INDEX); } 372 373 #ifdef DEBUG 374 // Bootstrapping-aware type checks. 375 static bool IsBootstrappingOrContext(Object* object); 376 static bool IsBootstrappingOrGlobalObject(Object* object); 377 #endif 378 }; 379 380 } } // namespace v8::internal 381 382 #endif // V8_CONTEXTS_H_ 383