V8 Project
contexts.cc
Go to the documentation of this file.
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/v8.h"
6 
7 #include "src/bootstrapper.h"
8 #include "src/debug.h"
9 #include "src/scopeinfo.h"
10 
11 namespace v8 {
12 namespace internal {
13 
15  Context* current = this;
16  while (!current->IsFunctionContext() && !current->IsNativeContext()) {
17  current = current->previous();
18  DCHECK(current->closure() == closure());
19  }
20  return current;
21 }
22 
23 
25  GlobalObject* object = global_object();
26  if (object->IsJSGlobalObject()) {
27  return JSGlobalObject::cast(object)->builtins();
28  } else {
29  DCHECK(object->IsJSBuiltinsObject());
30  return JSBuiltinsObject::cast(object);
31  }
32 }
33 
34 
36  Context* current = this;
37  while (!current->IsGlobalContext()) {
38  current = current->previous();
39  }
40  return current;
41 }
42 
43 
45  // Fast case: the global object for this context has been set. In
46  // that case, the global object has a direct pointer to the global
47  // context.
48  if (global_object()->IsGlobalObject()) {
49  return global_object()->native_context();
50  }
51 
52  // During bootstrapping, the global object might not be set and we
53  // have to search the context chain to find the native context.
54  DCHECK(this->GetIsolate()->bootstrapper()->IsActive());
55  Context* current = this;
56  while (!current->IsNativeContext()) {
57  JSFunction* closure = JSFunction::cast(current->closure());
58  current = Context::cast(closure->context());
59  }
60  return current;
61 }
62 
63 
65  return native_context()->global_proxy_object();
66 }
67 
68 
70  native_context()->set_global_proxy_object(object);
71 }
72 
73 
74 /**
75  * Lookups a property in an object environment, taking the unscopables into
76  * account. This is used For HasBinding spec algorithms for ObjectEnvironment.
77  */
78 static Maybe<PropertyAttributes> UnscopableLookup(LookupIterator* it) {
79  Isolate* isolate = it->isolate();
80 
82  DCHECK(attrs.has_value || isolate->has_pending_exception());
83  if (!attrs.has_value || attrs.value == ABSENT) return attrs;
84 
85  Handle<Symbol> unscopables_symbol(
86  isolate->native_context()->unscopables_symbol(), isolate);
87  Handle<Object> receiver = it->GetReceiver();
88  Handle<Object> unscopables;
89  MaybeHandle<Object> maybe_unscopables =
90  Object::GetProperty(receiver, unscopables_symbol);
91  if (!maybe_unscopables.ToHandle(&unscopables)) {
93  }
94  if (!unscopables->IsSpecObject()) return attrs;
96  Handle<JSReceiver>::cast(unscopables), it->name());
97  if (!blacklist.has_value) {
98  DCHECK(isolate->has_pending_exception());
100  }
101  if (blacklist.value) return maybe(ABSENT);
102  return attrs;
103 }
104 
105 
108  int* index,
109  PropertyAttributes* attributes,
110  BindingFlags* binding_flags) {
111  Isolate* isolate = GetIsolate();
112  Handle<Context> context(this, isolate);
113 
114  bool follow_context_chain = (flags & FOLLOW_CONTEXT_CHAIN) != 0;
115  *index = -1;
116  *attributes = ABSENT;
117  *binding_flags = MISSING_BINDING;
118 
119  if (FLAG_trace_contexts) {
120  PrintF("Context::Lookup(");
121  name->ShortPrint();
122  PrintF(")\n");
123  }
124 
125  do {
126  if (FLAG_trace_contexts) {
127  PrintF(" - looking in context %p", reinterpret_cast<void*>(*context));
128  if (context->IsNativeContext()) PrintF(" (native context)");
129  PrintF("\n");
130  }
131 
132  // 1. Check global objects, subjects of with, and extension objects.
133  if (context->IsNativeContext() ||
134  context->IsWithContext() ||
135  (context->IsFunctionContext() && context->has_extension())) {
136  Handle<JSReceiver> object(
137  JSReceiver::cast(context->extension()), isolate);
138  // Context extension objects needs to behave as if they have no
139  // prototype. So even if we want to follow prototype chains, we need
140  // to only do a local lookup for context extension objects.
142  if ((flags & FOLLOW_PROTOTYPE_CHAIN) == 0 ||
143  object->IsJSContextExtensionObject()) {
145  } else if (context->IsWithContext()) {
146  LookupIterator it(object, name);
147  maybe = UnscopableLookup(&it);
148  } else {
150  }
151 
152  if (!maybe.has_value) return Handle<Object>();
153  DCHECK(!isolate->has_pending_exception());
154  *attributes = maybe.value;
155 
156  if (maybe.value != ABSENT) {
157  if (FLAG_trace_contexts) {
158  PrintF("=> found property in context object %p\n",
159  reinterpret_cast<void*>(*object));
160  }
161  return object;
162  }
163  }
164 
165  // 2. Check the context proper if it has slots.
166  if (context->IsFunctionContext() || context->IsBlockContext()) {
167  // Use serialized scope information of functions and blocks to search
168  // for the context index.
169  Handle<ScopeInfo> scope_info;
170  if (context->IsFunctionContext()) {
171  scope_info = Handle<ScopeInfo>(
172  context->closure()->shared()->scope_info(), isolate);
173  } else {
174  scope_info = Handle<ScopeInfo>(
175  ScopeInfo::cast(context->extension()), isolate);
176  }
178  InitializationFlag init_flag;
179  // TODO(sigurds) Figure out whether maybe_assigned_flag should
180  // be used to compute binding_flags.
181  MaybeAssignedFlag maybe_assigned_flag;
182  int slot_index = ScopeInfo::ContextSlotIndex(
183  scope_info, name, &mode, &init_flag, &maybe_assigned_flag);
184  DCHECK(slot_index < 0 || slot_index >= MIN_CONTEXT_SLOTS);
185  if (slot_index >= 0) {
186  if (FLAG_trace_contexts) {
187  PrintF("=> found local in context slot %d (mode = %d)\n",
188  slot_index, mode);
189  }
190  *index = slot_index;
191  // Note: Fixed context slots are statically allocated by the compiler.
192  // Statically allocated variables always have a statically known mode,
193  // which is the mode with which they were declared when added to the
194  // scope. Thus, the DYNAMIC mode (which corresponds to dynamically
195  // declared variables that were introduced through declaration nodes)
196  // must not appear here.
197  switch (mode) {
198  case INTERNAL: // Fall through.
199  case VAR:
200  *attributes = NONE;
201  *binding_flags = MUTABLE_IS_INITIALIZED;
202  break;
203  case LET:
204  *attributes = NONE;
205  *binding_flags = (init_flag == kNeedsInitialization)
207  break;
208  case CONST_LEGACY:
209  *attributes = READ_ONLY;
210  *binding_flags = (init_flag == kNeedsInitialization)
212  break;
213  case CONST:
214  *attributes = READ_ONLY;
215  *binding_flags = (init_flag == kNeedsInitialization)
218  break;
219  case MODULE:
220  *attributes = READ_ONLY;
221  *binding_flags = IMMUTABLE_IS_INITIALIZED_HARMONY;
222  break;
223  case DYNAMIC:
224  case DYNAMIC_GLOBAL:
225  case DYNAMIC_LOCAL:
226  case TEMPORARY:
227  UNREACHABLE();
228  break;
229  }
230  return context;
231  }
232 
233  // Check the slot corresponding to the intermediate context holding
234  // only the function name variable.
235  if (follow_context_chain && context->IsFunctionContext()) {
237  int function_index = scope_info->FunctionContextSlotIndex(*name, &mode);
238  if (function_index >= 0) {
239  if (FLAG_trace_contexts) {
240  PrintF("=> found intermediate function in context slot %d\n",
241  function_index);
242  }
243  *index = function_index;
244  *attributes = READ_ONLY;
245  DCHECK(mode == CONST_LEGACY || mode == CONST);
246  *binding_flags = (mode == CONST_LEGACY)
248  return context;
249  }
250  }
251 
252  } else if (context->IsCatchContext()) {
253  // Catch contexts have the variable name in the extension slot.
254  if (String::Equals(name, handle(String::cast(context->extension())))) {
255  if (FLAG_trace_contexts) {
256  PrintF("=> found in catch context\n");
257  }
259  *attributes = NONE;
260  *binding_flags = MUTABLE_IS_INITIALIZED;
261  return context;
262  }
263  }
264 
265  // 3. Prepare to continue with the previous (next outermost) context.
266  if (context->IsNativeContext()) {
267  follow_context_chain = false;
268  } else {
269  context = Handle<Context>(context->previous(), isolate);
270  }
271  } while (follow_context_chain);
272 
273  if (FLAG_trace_contexts) {
274  PrintF("=> no property/slot found\n");
275  }
276  return Handle<Object>::null();
277 }
278 
279 
282 #ifdef ENABLE_SLOW_DCHECKS
284  Object* element = get(OPTIMIZED_FUNCTIONS_LIST);
285  while (!element->IsUndefined()) {
286  CHECK(element != function);
287  element = JSFunction::cast(element)->next_function_link();
288  }
289  }
290 
291  // Check that the context belongs to the weak native contexts list.
292  bool found = false;
293  Object* context = GetHeap()->native_contexts_list();
294  while (!context->IsUndefined()) {
295  if (context == this) {
296  found = true;
297  break;
298  }
299  context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
300  }
301  CHECK(found);
302 #endif
303 
304  // If the function link field is already used then the function was
305  // enqueued as a code flushing candidate and we remove it now.
306  if (!function->next_function_link()->IsUndefined()) {
308  flusher->EvictCandidate(function);
309  }
310 
311  DCHECK(function->next_function_link()->IsUndefined());
312 
313  function->set_next_function_link(get(OPTIMIZED_FUNCTIONS_LIST));
314  set(OPTIMIZED_FUNCTIONS_LIST, function);
315 }
316 
317 
320  Object* element = get(OPTIMIZED_FUNCTIONS_LIST);
321  JSFunction* prev = NULL;
322  while (!element->IsUndefined()) {
323  JSFunction* element_function = JSFunction::cast(element);
324  DCHECK(element_function->next_function_link()->IsUndefined() ||
325  element_function->next_function_link()->IsJSFunction());
326  if (element_function == function) {
327  if (prev == NULL) {
328  set(OPTIMIZED_FUNCTIONS_LIST, element_function->next_function_link());
329  } else {
330  prev->set_next_function_link(element_function->next_function_link());
331  }
332  element_function->set_next_function_link(GetHeap()->undefined_value());
333  return;
334  }
335  prev = element_function;
336  element = element_function->next_function_link();
337  }
338  UNREACHABLE();
339 }
340 
341 
345 }
346 
347 
351 }
352 
353 
356  DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
357  DCHECK(code->next_code_link()->IsUndefined());
358  code->set_next_code_link(get(OPTIMIZED_CODE_LIST));
359  set(OPTIMIZED_CODE_LIST, code);
360 }
361 
362 
365  set(OPTIMIZED_CODE_LIST, head);
366 }
367 
368 
371  return get(OPTIMIZED_CODE_LIST);
372 }
373 
374 
377  set(DEOPTIMIZED_CODE_LIST, head);
378 }
379 
380 
383  return get(DEOPTIMIZED_CODE_LIST);
384 }
385 
386 
388  Isolate* isolate = GetIsolate();
389  Handle<Object> result(error_message_for_code_gen_from_strings(), isolate);
390  if (!result->IsUndefined()) return result;
391  return isolate->factory()->NewStringFromStaticChars(
392  "Code generation from strings disallowed for this context");
393 }
394 
395 
396 #ifdef DEBUG
397 bool Context::IsBootstrappingOrValidParentContext(
398  Object* object, Context* child) {
399  // During bootstrapping we allow all objects to pass as
400  // contexts. This is necessary to fix circular dependencies.
401  if (child->GetIsolate()->bootstrapper()->IsActive()) return true;
402  if (!object->IsContext()) return false;
403  Context* context = Context::cast(object);
404  return context->IsNativeContext() || context->IsGlobalContext() ||
405  context->IsModuleContext() || !child->IsModuleContext();
406 }
407 
408 
409 bool Context::IsBootstrappingOrGlobalObject(Isolate* isolate, Object* object) {
410  // During bootstrapping we allow all objects to pass as global
411  // objects. This is necessary to fix circular dependencies.
412  return isolate->heap()->gc_state() != Heap::NOT_IN_GC ||
413  isolate->bootstrapper()->IsActive() ||
414  object->IsGlobalObject();
415 }
416 #endif
417 
418 } } // namespace v8::internal
Isolate represents an isolated instance of the V8 engine.
Definition: v8.h:4356
A JavaScript object (ECMA-262, 4.3.3)
Definition: v8.h:2283
void EvictCandidate(SharedFunctionInfo *shared_info)
Object * OptimizedCodeListHead()
Definition: contexts.cc:369
JSObject * global_proxy()
Definition: contexts.cc:64
void set_global_proxy(JSObject *global)
Definition: contexts.cc:69
Object * OptimizedFunctionsListHead()
Definition: contexts.cc:348
static Context * cast(Object *context)
Definition: contexts.h:255
void AddOptimizedCode(Code *code)
Definition: contexts.cc:354
Context * previous()
Definition: contexts.h:419
void SetOptimizedCodeListHead(Object *head)
Definition: contexts.cc:363
Handle< Object > ErrorMessageForCodeGenerationFromStrings()
Definition: contexts.cc:387
Handle< Object > Lookup(Handle< String > name, ContextLookupFlags flags, int *index, PropertyAttributes *attributes, BindingFlags *binding_flags)
Definition: contexts.cc:106
Context * native_context()
Definition: contexts.cc:44
void SetOptimizedFunctionsListHead(Object *head)
Definition: contexts.cc:342
JSBuiltinsObject * builtins()
Definition: contexts.cc:24
Context * global_context()
Definition: contexts.cc:35
void AddOptimizedFunction(JSFunction *function)
Definition: contexts.cc:280
void RemoveOptimizedFunction(JSFunction *function)
Definition: contexts.cc:318
Object * DeoptimizedCodeListHead()
Definition: contexts.cc:381
GlobalObject * global_object()
Definition: contexts.h:437
bool IsFunctionContext()
Definition: contexts.h:466
Context * declaration_context()
Definition: contexts.cc:14
void SetDeoptimizedCodeListHead(Object *head)
Definition: contexts.cc:375
JSFunction * closure()
Definition: contexts.h:416
Object * get(int index)
Definition: objects-inl.h:2165
void set(int index, Object *value)
Definition: objects-inl.h:2190
static Handle< T > null()
Definition: handles.h:123
Heap * GetHeap() const
Definition: objects-inl.h:1379
Isolate * GetIsolate() const
Definition: objects-inl.h:1387
Object * native_contexts_list() const
Definition: heap.h:793
MarkCompactCollector * mark_compact_collector()
Definition: heap.h:1197
Handle< Context > native_context()
Definition: isolate.cc:1339
Factory * factory()
Definition: isolate.h:982
Bootstrapper * bootstrapper()
Definition: isolate.h:856
bool has_pending_exception()
Definition: isolate.h:581
static MUST_USE_RESULT Maybe< PropertyAttributes > GetPropertyAttributes(Handle< JSReceiver > object, Handle< Name > name)
Definition: objects-inl.h:6670
static MUST_USE_RESULT Maybe< PropertyAttributes > GetOwnPropertyAttributes(Handle< JSReceiver > object, Handle< Name > name)
Definition: objects.cc:3983
static MUST_USE_RESULT Maybe< bool > HasProperty(Handle< JSReceiver > object, Handle< Name > name)
Definition: objects-inl.h:6646
friend class LookupIterator
Definition: objects.h:1226
static MUST_USE_RESULT MaybeHandle< Object > GetProperty(LookupIterator *it)
Definition: objects.cc:109
static int ContextSlotIndex(Handle< ScopeInfo > scope_info, Handle< String > name, VariableMode *mode, InitializationFlag *init_flag, MaybeAssignedFlag *maybe_assigned_flag)
Definition: scopeinfo.cc:296
bool Equals(String *other)
Definition: objects-inl.h:3336
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define UNREACHABLE()
Definition: logging.h:30
#define CHECK(condition)
Definition: logging.h:36
#define DCHECK(condition)
Definition: logging.h:205
InitializationFlag
Definition: globals.h:751
@ kNeedsInitialization
Definition: globals.h:752
@ IMMUTABLE_CHECK_INITIALIZED
Definition: contexts.h:60
@ MUTABLE_IS_INITIALIZED
Definition: contexts.h:57
@ MISSING_BINDING
Definition: contexts.h:63
@ IMMUTABLE_CHECK_INITIALIZED_HARMONY
Definition: contexts.h:62
@ MUTABLE_CHECK_INITIALIZED
Definition: contexts.h:58
@ IMMUTABLE_IS_INITIALIZED_HARMONY
Definition: contexts.h:61
@ IMMUTABLE_IS_INITIALIZED
Definition: contexts.h:59
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:146
const bool FLAG_enable_slow_asserts
Definition: checks.h:31
@ DYNAMIC_GLOBAL
Definition: globals.h:689
@ DYNAMIC_LOCAL
Definition: globals.h:693
@ CONST_LEGACY
Definition: globals.h:671
void PrintF(const char *format,...)
Definition: utils.cc:80
ContextLookupFlags
Definition: contexts.h:15
@ FOLLOW_CONTEXT_CHAIN
Definition: contexts.h:16
@ FOLLOW_PROTOTYPE_CHAIN
Definition: contexts.h:17
static Maybe< PropertyAttributes > UnscopableLookup(LookupIterator *it)
Lookups a property in an object environment, taking the unscopables into account.
Definition: contexts.cc:78
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
Maybe< T > maybe(T t)
Definition: v8.h:902
PropertyAttributes
@ ABSENT
@ NONE
@ READ_ONLY
A simple Maybe type, representing an object which may or may not have a value.
Definition: v8.h:890
T value
Definition: v8.h:896
bool has_value
Definition: v8.h:895