OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 | 89 |
90 // Heap-allocated activation contexts. | 90 // Heap-allocated activation contexts. |
91 // | 91 // |
92 // Contexts are implemented as FixedArray objects; the Context | 92 // Contexts are implemented as FixedArray objects; the Context |
93 // class is a convenience interface casted on a FixedArray object. | 93 // class is a convenience interface casted on a FixedArray object. |
94 // | 94 // |
95 // Note: Context must have no virtual functions and Context objects | 95 // Note: Context must have no virtual functions and Context objects |
96 // must always be allocated via Heap::AllocateContext() or | 96 // must always be allocated via Heap::AllocateContext() or |
97 // Factory::NewContext. | 97 // Factory::NewContext. |
98 | 98 |
99 #define NATIVE_CONTEXT_FIELDS(V) \ | 99 #define GLOBAL_CONTEXT_FIELDS(V) \ |
100 V(GLOBAL_PROXY_INDEX, JSObject, global_proxy_object) \ | 100 V(GLOBAL_PROXY_INDEX, JSObject, global_proxy_object) \ |
101 V(SECURITY_TOKEN_INDEX, Object, security_token) \ | 101 V(SECURITY_TOKEN_INDEX, Object, security_token) \ |
102 V(BOOLEAN_FUNCTION_INDEX, JSFunction, boolean_function) \ | 102 V(BOOLEAN_FUNCTION_INDEX, JSFunction, boolean_function) \ |
103 V(NUMBER_FUNCTION_INDEX, JSFunction, number_function) \ | 103 V(NUMBER_FUNCTION_INDEX, JSFunction, number_function) \ |
104 V(STRING_FUNCTION_INDEX, JSFunction, string_function) \ | 104 V(STRING_FUNCTION_INDEX, JSFunction, string_function) \ |
105 V(STRING_FUNCTION_PROTOTYPE_MAP_INDEX, Map, string_function_prototype_map) \ | 105 V(STRING_FUNCTION_PROTOTYPE_MAP_INDEX, Map, string_function_prototype_map) \ |
106 V(OBJECT_FUNCTION_INDEX, JSFunction, object_function) \ | 106 V(OBJECT_FUNCTION_INDEX, JSFunction, object_function) \ |
107 V(INTERNAL_ARRAY_FUNCTION_INDEX, JSFunction, internal_array_function) \ | 107 V(INTERNAL_ARRAY_FUNCTION_INDEX, JSFunction, internal_array_function) \ |
108 V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \ | 108 V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \ |
109 V(JS_ARRAY_MAPS_INDEX, Object, js_array_maps) \ | 109 V(JS_ARRAY_MAPS_INDEX, Object, js_array_maps) \ |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 // [ extension ] A pointer to an extension JSObject, or NULL. Used to | 186 // [ extension ] A pointer to an extension JSObject, or NULL. Used to |
187 // implement 'with' statements and dynamic declarations | 187 // implement 'with' statements and dynamic declarations |
188 // (through 'eval'). The object in a 'with' statement is | 188 // (through 'eval'). The object in a 'with' statement is |
189 // stored in the extension slot of a 'with' context. | 189 // stored in the extension slot of a 'with' context. |
190 // Dynamically declared variables/functions are also added | 190 // Dynamically declared variables/functions are also added |
191 // to lazily allocated extension object. Context::Lookup | 191 // to lazily allocated extension object. Context::Lookup |
192 // searches the extension object for properties. | 192 // searches the extension object for properties. |
193 // For block contexts, contains the respective ScopeInfo. | 193 // For block contexts, contains the respective ScopeInfo. |
194 // For module contexts, points back to the respective JSModule. | 194 // For module contexts, points back to the respective JSModule. |
195 // | 195 // |
196 // [ global_object ] A pointer to the global object. Provided for quick | 196 // [ global ] A pointer to the global object. Provided for quick |
197 // access to the global object from inside the code (since | 197 // access to the global object from inside the code (since |
198 // we always have a context pointer). | 198 // we always have a context pointer). |
199 // | 199 // |
200 // In addition, function contexts may have statically allocated context slots | 200 // In addition, function contexts may have statically allocated context slots |
201 // to store local variables/functions that are accessed from inner functions | 201 // to store local variables/functions that are accessed from inner functions |
202 // (via static context addresses) or through 'eval' (dynamic context lookups). | 202 // (via static context addresses) or through 'eval' (dynamic context lookups). |
203 // Finally, the native context contains additional slots for fast access to | 203 // Finally, the global context contains additional slots for fast access to |
204 // native properties. | 204 // global properties. |
205 | 205 |
206 class Context: public FixedArray { | 206 class Context: public FixedArray { |
207 public: | 207 public: |
208 // Conversions. | 208 // Conversions. |
209 static Context* cast(Object* context) { | 209 static Context* cast(Object* context) { |
210 ASSERT(context->IsContext()); | 210 ASSERT(context->IsContext()); |
211 return reinterpret_cast<Context*>(context); | 211 return reinterpret_cast<Context*>(context); |
212 } | 212 } |
213 | 213 |
214 // The default context slot layout; indices are FixedArray slot indices. | 214 // The default context slot layout; indices are FixedArray slot indices. |
215 enum { | 215 enum { |
216 // These slots are in all contexts. | 216 // These slots are in all contexts. |
217 CLOSURE_INDEX, | 217 CLOSURE_INDEX, |
218 PREVIOUS_INDEX, | 218 PREVIOUS_INDEX, |
219 // The extension slot is used for either the global object (in global | 219 // The extension slot is used for either the global object (in global |
220 // contexts), eval extension object (function contexts), subject of with | 220 // contexts), eval extension object (function contexts), subject of with |
221 // (with contexts), or the variable name (catch contexts), the serialized | 221 // (with contexts), or the variable name (catch contexts), the serialized |
222 // scope info (block contexts), or the module instance (module contexts). | 222 // scope info (block contexts), or the module instance (module contexts). |
223 EXTENSION_INDEX, | 223 EXTENSION_INDEX, |
224 GLOBAL_OBJECT_INDEX, | 224 GLOBAL_INDEX, |
225 MIN_CONTEXT_SLOTS, | 225 MIN_CONTEXT_SLOTS, |
226 | 226 |
227 // This slot holds the thrown value in catch contexts. | 227 // This slot holds the thrown value in catch contexts. |
228 THROWN_OBJECT_INDEX = MIN_CONTEXT_SLOTS, | 228 THROWN_OBJECT_INDEX = MIN_CONTEXT_SLOTS, |
229 | 229 |
230 // These slots are only in native contexts. | 230 // These slots are only in global contexts. |
231 GLOBAL_PROXY_INDEX = MIN_CONTEXT_SLOTS, | 231 GLOBAL_PROXY_INDEX = MIN_CONTEXT_SLOTS, |
232 SECURITY_TOKEN_INDEX, | 232 SECURITY_TOKEN_INDEX, |
233 ARGUMENTS_BOILERPLATE_INDEX, | 233 ARGUMENTS_BOILERPLATE_INDEX, |
234 ALIASED_ARGUMENTS_BOILERPLATE_INDEX, | 234 ALIASED_ARGUMENTS_BOILERPLATE_INDEX, |
235 STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX, | 235 STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX, |
236 REGEXP_RESULT_MAP_INDEX, | 236 REGEXP_RESULT_MAP_INDEX, |
237 FUNCTION_MAP_INDEX, | 237 FUNCTION_MAP_INDEX, |
238 STRICT_MODE_FUNCTION_MAP_INDEX, | 238 STRICT_MODE_FUNCTION_MAP_INDEX, |
239 FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, | 239 FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, |
240 STRICT_MODE_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, | 240 STRICT_MODE_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 PROXY_ENUMERATE, | 287 PROXY_ENUMERATE, |
288 RANDOM_SEED_INDEX, | 288 RANDOM_SEED_INDEX, |
289 | 289 |
290 // Properties from here are treated as weak references by the full GC. | 290 // Properties from here are treated as weak references by the full GC. |
291 // Scavenge treats them as strong references. | 291 // Scavenge treats them as strong references. |
292 OPTIMIZED_FUNCTIONS_LIST, // Weak. | 292 OPTIMIZED_FUNCTIONS_LIST, // Weak. |
293 MAP_CACHE_INDEX, // Weak. | 293 MAP_CACHE_INDEX, // Weak. |
294 NEXT_CONTEXT_LINK, // Weak. | 294 NEXT_CONTEXT_LINK, // Weak. |
295 | 295 |
296 // Total number of slots. | 296 // Total number of slots. |
297 NATIVE_CONTEXT_SLOTS, | 297 GLOBAL_CONTEXT_SLOTS, |
298 | 298 |
299 FIRST_WEAK_SLOT = OPTIMIZED_FUNCTIONS_LIST | 299 FIRST_WEAK_SLOT = OPTIMIZED_FUNCTIONS_LIST |
300 }; | 300 }; |
301 | 301 |
302 // Direct slot access. | 302 // Direct slot access. |
303 JSFunction* closure() { return JSFunction::cast(get(CLOSURE_INDEX)); } | 303 JSFunction* closure() { return JSFunction::cast(get(CLOSURE_INDEX)); } |
304 void set_closure(JSFunction* closure) { set(CLOSURE_INDEX, closure); } | 304 void set_closure(JSFunction* closure) { set(CLOSURE_INDEX, closure); } |
305 | 305 |
306 Context* previous() { | 306 Context* previous() { |
307 Object* result = unchecked_previous(); | 307 Object* result = unchecked_previous(); |
308 ASSERT(IsBootstrappingOrValidParentContext(result, this)); | 308 ASSERT(IsBootstrappingOrValidParentContext(result, this)); |
309 return reinterpret_cast<Context*>(result); | 309 return reinterpret_cast<Context*>(result); |
310 } | 310 } |
311 void set_previous(Context* context) { set(PREVIOUS_INDEX, context); } | 311 void set_previous(Context* context) { set(PREVIOUS_INDEX, context); } |
312 | 312 |
313 bool has_extension() { return extension() != NULL; } | 313 bool has_extension() { return extension() != NULL; } |
314 Object* extension() { return get(EXTENSION_INDEX); } | 314 Object* extension() { return get(EXTENSION_INDEX); } |
315 void set_extension(Object* object) { set(EXTENSION_INDEX, object); } | 315 void set_extension(Object* object) { set(EXTENSION_INDEX, object); } |
316 | 316 |
317 JSModule* module() { return JSModule::cast(get(EXTENSION_INDEX)); } | 317 JSModule* module() { return JSModule::cast(get(EXTENSION_INDEX)); } |
318 void set_module(JSModule* module) { set(EXTENSION_INDEX, module); } | 318 void set_module(JSModule* module) { set(EXTENSION_INDEX, module); } |
319 | 319 |
320 // Get the context where var declarations will be hoisted to, which | 320 // Get the context where var declarations will be hoisted to, which |
321 // may be the context itself. | 321 // may be the context itself. |
322 Context* declaration_context(); | 322 Context* declaration_context(); |
323 | 323 |
324 GlobalObject* global_object() { | 324 GlobalObject* global() { |
325 Object* result = get(GLOBAL_OBJECT_INDEX); | 325 Object* result = get(GLOBAL_INDEX); |
326 ASSERT(IsBootstrappingOrGlobalObject(result)); | 326 ASSERT(IsBootstrappingOrGlobalObject(result)); |
327 return reinterpret_cast<GlobalObject*>(result); | 327 return reinterpret_cast<GlobalObject*>(result); |
328 } | 328 } |
329 void set_global_object(GlobalObject* object) { | 329 void set_global(GlobalObject* global) { set(GLOBAL_INDEX, global); } |
330 set(GLOBAL_OBJECT_INDEX, object); | |
331 } | |
332 | 330 |
333 // Returns a JSGlobalProxy object or null. | 331 // Returns a JSGlobalProxy object or null. |
334 JSObject* global_proxy(); | 332 JSObject* global_proxy(); |
335 void set_global_proxy(JSObject* global); | 333 void set_global_proxy(JSObject* global); |
336 | 334 |
337 // The builtins object. | 335 // The builtins object. |
338 JSBuiltinsObject* builtins(); | 336 JSBuiltinsObject* builtins(); |
339 | 337 |
340 // Compute the native context by traversing the context chain. | 338 // Compute the global context by traversing the context chain. |
341 Context* native_context(); | 339 Context* global_context(); |
342 | 340 |
343 // Predicates for context types. IsNativeContext is defined on Object | 341 // Predicates for context types. IsGlobalContext is defined on Object |
344 // because we frequently have to know if arbitrary objects are natives | 342 // because we frequently have to know if arbitrary objects are global |
345 // contexts. | 343 // contexts. |
346 bool IsFunctionContext() { | 344 bool IsFunctionContext() { |
347 Map* map = this->map(); | 345 Map* map = this->map(); |
348 return map == map->GetHeap()->function_context_map(); | 346 return map == map->GetHeap()->function_context_map(); |
349 } | 347 } |
350 bool IsCatchContext() { | 348 bool IsCatchContext() { |
351 Map* map = this->map(); | 349 Map* map = this->map(); |
352 return map == map->GetHeap()->catch_context_map(); | 350 return map == map->GetHeap()->catch_context_map(); |
353 } | 351 } |
354 bool IsWithContext() { | 352 bool IsWithContext() { |
355 Map* map = this->map(); | 353 Map* map = this->map(); |
356 return map == map->GetHeap()->with_context_map(); | 354 return map == map->GetHeap()->with_context_map(); |
357 } | 355 } |
358 bool IsBlockContext() { | 356 bool IsBlockContext() { |
359 Map* map = this->map(); | 357 Map* map = this->map(); |
360 return map == map->GetHeap()->block_context_map(); | 358 return map == map->GetHeap()->block_context_map(); |
361 } | 359 } |
362 bool IsModuleContext() { | 360 bool IsModuleContext() { |
363 Map* map = this->map(); | 361 Map* map = this->map(); |
364 return map == map->GetHeap()->module_context_map(); | 362 return map == map->GetHeap()->module_context_map(); |
365 } | 363 } |
366 | 364 |
367 // Tells whether the native context is marked with out of memory. | 365 // Tells whether the global context is marked with out of memory. |
368 inline bool has_out_of_memory(); | 366 inline bool has_out_of_memory(); |
369 | 367 |
370 // Mark the native context with out of memory. | 368 // Mark the global context with out of memory. |
371 inline void mark_out_of_memory(); | 369 inline void mark_out_of_memory(); |
372 | 370 |
373 // A native context hold a list of all functions which have been optimized. | 371 // A global context hold a list of all functions which have been optimized. |
374 void AddOptimizedFunction(JSFunction* function); | 372 void AddOptimizedFunction(JSFunction* function); |
375 void RemoveOptimizedFunction(JSFunction* function); | 373 void RemoveOptimizedFunction(JSFunction* function); |
376 Object* OptimizedFunctionsListHead(); | 374 Object* OptimizedFunctionsListHead(); |
377 void ClearOptimizedFunctions(); | 375 void ClearOptimizedFunctions(); |
378 | 376 |
379 #define NATIVE_CONTEXT_FIELD_ACCESSORS(index, type, name) \ | 377 #define GLOBAL_CONTEXT_FIELD_ACCESSORS(index, type, name) \ |
380 void set_##name(type* value) { \ | 378 void set_##name(type* value) { \ |
381 ASSERT(IsNativeContext()); \ | 379 ASSERT(IsGlobalContext()); \ |
382 set(index, value); \ | 380 set(index, value); \ |
383 } \ | 381 } \ |
384 type* name() { \ | 382 type* name() { \ |
385 ASSERT(IsNativeContext()); \ | 383 ASSERT(IsGlobalContext()); \ |
386 return type::cast(get(index)); \ | 384 return type::cast(get(index)); \ |
387 } | 385 } |
388 NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELD_ACCESSORS) | 386 GLOBAL_CONTEXT_FIELDS(GLOBAL_CONTEXT_FIELD_ACCESSORS) |
389 #undef NATIVE_CONTEXT_FIELD_ACCESSORS | 387 #undef GLOBAL_CONTEXT_FIELD_ACCESSORS |
390 | 388 |
391 // Lookup the slot called name, starting with the current context. | 389 // Lookup the slot called name, starting with the current context. |
392 // There are three possibilities: | 390 // There are three possibilities: |
393 // | 391 // |
394 // 1) result->IsContext(): | 392 // 1) result->IsContext(): |
395 // The binding was found in a context. *index is always the | 393 // The binding was found in a context. *index is always the |
396 // non-negative slot index. *attributes is NONE for var and let | 394 // non-negative slot index. *attributes is NONE for var and let |
397 // declarations, READ_ONLY for const declarations (never ABSENT). | 395 // declarations, READ_ONLY for const declarations (never ABSENT). |
398 // | 396 // |
399 // 2) result->IsJSObject(): | 397 // 2) result->IsJSObject(): |
400 // The binding was found as a named property in a context extension | 398 // The binding was found as a named property in a context extension |
401 // object (i.e., was introduced via eval), as a property on the subject | 399 // object (i.e., was introduced via eval), as a property on the subject |
402 // of with, or as a property of the global object. *index is -1 and | 400 // of with, or as a property of the global object. *index is -1 and |
403 // *attributes is not ABSENT. | 401 // *attributes is not ABSENT. |
404 // | 402 // |
405 // 3) result.is_null(): | 403 // 3) result.is_null(): |
406 // There was no binding found, *index is always -1 and *attributes is | 404 // There was no binding found, *index is always -1 and *attributes is |
407 // always ABSENT. | 405 // always ABSENT. |
408 Handle<Object> Lookup(Handle<String> name, | 406 Handle<Object> Lookup(Handle<String> name, |
409 ContextLookupFlags flags, | 407 ContextLookupFlags flags, |
410 int* index, | 408 int* index, |
411 PropertyAttributes* attributes, | 409 PropertyAttributes* attributes, |
412 BindingFlags* binding_flags); | 410 BindingFlags* binding_flags); |
413 | 411 |
414 // Code generation support. | 412 // Code generation support. |
415 static int SlotOffset(int index) { | 413 static int SlotOffset(int index) { |
416 return kHeaderSize + index * kPointerSize - kHeapObjectTag; | 414 return kHeaderSize + index * kPointerSize - kHeapObjectTag; |
417 } | 415 } |
418 | 416 |
419 static const int kSize = kHeaderSize + NATIVE_CONTEXT_SLOTS * kPointerSize; | 417 static const int kSize = kHeaderSize + GLOBAL_CONTEXT_SLOTS * kPointerSize; |
420 | 418 |
421 // GC support. | 419 // GC support. |
422 typedef FixedBodyDescriptor< | 420 typedef FixedBodyDescriptor< |
423 kHeaderSize, kSize, kSize> ScavengeBodyDescriptor; | 421 kHeaderSize, kSize, kSize> ScavengeBodyDescriptor; |
424 | 422 |
425 typedef FixedBodyDescriptor< | 423 typedef FixedBodyDescriptor< |
426 kHeaderSize, | 424 kHeaderSize, |
427 kHeaderSize + FIRST_WEAK_SLOT * kPointerSize, | 425 kHeaderSize + FIRST_WEAK_SLOT * kPointerSize, |
428 kSize> MarkCompactBodyDescriptor; | 426 kSize> MarkCompactBodyDescriptor; |
429 | 427 |
430 private: | 428 private: |
431 // Unchecked access to the slots. | 429 // Unchecked access to the slots. |
432 Object* unchecked_previous() { return get(PREVIOUS_INDEX); } | 430 Object* unchecked_previous() { return get(PREVIOUS_INDEX); } |
433 | 431 |
434 #ifdef DEBUG | 432 #ifdef DEBUG |
435 // Bootstrapping-aware type checks. | 433 // Bootstrapping-aware type checks. |
436 static bool IsBootstrappingOrValidParentContext(Object* object, Context* kid); | 434 static bool IsBootstrappingOrValidParentContext(Object* object, Context* kid); |
437 static bool IsBootstrappingOrGlobalObject(Object* object); | 435 static bool IsBootstrappingOrGlobalObject(Object* object); |
438 #endif | 436 #endif |
439 }; | 437 }; |
440 | 438 |
441 } } // namespace v8::internal | 439 } } // namespace v8::internal |
442 | 440 |
443 #endif // V8_CONTEXTS_H_ | 441 #endif // V8_CONTEXTS_H_ |
OLD | NEW |