V8 Project
scopes.cc
Go to the documentation of this file.
1 // Copyright 2012 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/scopes.h"
8 
9 #include "src/accessors.h"
10 #include "src/bootstrapper.h"
11 #include "src/compiler.h"
12 #include "src/messages.h"
13 #include "src/scopeinfo.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 // ----------------------------------------------------------------------------
19 // Implementation of LocalsMap
20 //
21 // Note: We are storing the handle locations as key values in the hash map.
22 // When inserting a new variable via Declare(), we rely on the fact that
23 // the handle location remains alive for the duration of that variable
24 // use. Because a Variable holding a handle with the same location exists
25 // this is ensured.
26 
28  : ZoneHashMap(ZoneHashMap::PointersMatch, 8, ZoneAllocationPolicy(zone)),
29  zone_(zone) {}
31 
32 
34  VariableMode mode, bool is_valid_lhs,
35  Variable::Kind kind,
36  InitializationFlag initialization_flag,
37  MaybeAssignedFlag maybe_assigned_flag,
38  Interface* interface) {
39  // AstRawStrings are unambiguous, i.e., the same string is always represented
40  // by the same AstRawString*.
41  // FIXME(marja): fix the type of Lookup.
42  Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(),
43  true, ZoneAllocationPolicy(zone()));
44  if (p->value == NULL) {
45  // The variable has not been declared yet -> insert it.
46  DCHECK(p->key == name);
47  p->value = new (zone())
48  Variable(scope, name, mode, is_valid_lhs, kind, initialization_flag,
49  maybe_assigned_flag, interface);
50  }
51  return reinterpret_cast<Variable*>(p->value);
52 }
53 
54 
56  Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(),
57  false, ZoneAllocationPolicy(NULL));
58  if (p != NULL) {
59  DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name);
60  DCHECK(p->value != NULL);
61  return reinterpret_cast<Variable*>(p->value);
62  }
63  return NULL;
64 }
65 
66 
67 // ----------------------------------------------------------------------------
68 // Implementation of Scope
69 
70 Scope::Scope(Scope* outer_scope, ScopeType scope_type,
71  AstValueFactory* ast_value_factory, Zone* zone)
72  : isolate_(zone->isolate()),
73  inner_scopes_(4, zone),
74  variables_(zone),
75  internals_(4, zone),
76  temps_(4, zone),
77  params_(4, zone),
78  unresolved_(16, zone),
79  decls_(4, zone),
80  interface_(FLAG_harmony_modules &&
81  (scope_type == MODULE_SCOPE || scope_type == GLOBAL_SCOPE)
82  ? Interface::NewModule(zone) : NULL),
83  already_resolved_(false),
84  ast_value_factory_(ast_value_factory),
85  zone_(zone) {
87  // The outermost scope must be a global scope.
90 }
91 
92 
93 Scope::Scope(Scope* inner_scope,
94  ScopeType scope_type,
95  Handle<ScopeInfo> scope_info,
96  AstValueFactory* value_factory,
97  Zone* zone)
98  : isolate_(zone->isolate()),
99  inner_scopes_(4, zone),
100  variables_(zone),
101  internals_(4, zone),
102  temps_(4, zone),
103  params_(4, zone),
104  unresolved_(16, zone),
105  decls_(4, zone),
106  interface_(NULL),
107  already_resolved_(true),
108  ast_value_factory_(value_factory),
109  zone_(zone) {
110  SetDefaults(scope_type, NULL, scope_info);
111  if (!scope_info.is_null()) {
112  num_heap_slots_ = scope_info_->ContextLength();
113  }
114  // Ensure at least MIN_CONTEXT_SLOTS to indicate a materialized context.
116  static_cast<int>(Context::MIN_CONTEXT_SLOTS));
117  AddInnerScope(inner_scope);
118 }
119 
120 
121 Scope::Scope(Scope* inner_scope, const AstRawString* catch_variable_name,
122  AstValueFactory* value_factory, Zone* zone)
123  : isolate_(zone->isolate()),
124  inner_scopes_(1, zone),
125  variables_(zone),
126  internals_(0, zone),
127  temps_(0, zone),
128  params_(0, zone),
129  unresolved_(0, zone),
130  decls_(0, zone),
131  interface_(NULL),
132  already_resolved_(true),
133  ast_value_factory_(value_factory),
134  zone_(zone) {
136  AddInnerScope(inner_scope);
139  Variable* variable = variables_.Declare(this,
140  catch_variable_name,
141  VAR,
142  true, // Valid left-hand side.
145  AllocateHeapSlot(variable);
146 }
147 
148 
150  Scope* outer_scope,
151  Handle<ScopeInfo> scope_info) {
154  scope_name_ = ast_value_factory_->empty_string();
155  dynamics_ = NULL;
156  receiver_ = NULL;
157  function_ = NULL;
158  arguments_ = NULL;
160  scope_inside_with_ = false;
161  scope_contains_with_ = false;
162  scope_calls_eval_ = false;
163  asm_module_ = false;
165  // Inherit the strict mode from the parent scope.
168  inner_scope_calls_eval_ = false;
169  force_eager_compilation_ = false;
172  num_var_or_const_ = 0;
173  num_stack_slots_ = 0;
174  num_heap_slots_ = 0;
175  num_modules_ = 0;
176  module_var_ = NULL,
177  scope_info_ = scope_info;
180  if (!scope_info.is_null()) {
181  scope_calls_eval_ = scope_info->CallsEval();
182  strict_mode_ = scope_info->strict_mode();
183  }
184 }
185 
186 
188  Zone* zone) {
189  // Reconstruct the outer scope chain from a closure's context chain.
190  Scope* current_scope = NULL;
191  Scope* innermost_scope = NULL;
192  bool contains_with = false;
193  while (!context->IsNativeContext()) {
194  if (context->IsWithContext()) {
195  Scope* with_scope = new(zone) Scope(current_scope,
196  WITH_SCOPE,
198  global_scope->ast_value_factory_,
199  zone);
200  current_scope = with_scope;
201  // All the inner scopes are inside a with.
202  contains_with = true;
203  for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) {
204  s->scope_inside_with_ = true;
205  }
206  } else if (context->IsGlobalContext()) {
207  ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
208  current_scope = new(zone) Scope(current_scope,
209  GLOBAL_SCOPE,
210  Handle<ScopeInfo>(scope_info),
211  global_scope->ast_value_factory_,
212  zone);
213  } else if (context->IsModuleContext()) {
214  ScopeInfo* scope_info = ScopeInfo::cast(context->module()->scope_info());
215  current_scope = new(zone) Scope(current_scope,
216  MODULE_SCOPE,
217  Handle<ScopeInfo>(scope_info),
218  global_scope->ast_value_factory_,
219  zone);
220  } else if (context->IsFunctionContext()) {
221  ScopeInfo* scope_info = context->closure()->shared()->scope_info();
222  current_scope = new(zone) Scope(current_scope,
224  Handle<ScopeInfo>(scope_info),
225  global_scope->ast_value_factory_,
226  zone);
227  if (scope_info->IsAsmFunction()) current_scope->asm_function_ = true;
228  if (scope_info->IsAsmModule()) current_scope->asm_module_ = true;
229  } else if (context->IsBlockContext()) {
230  ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
231  current_scope = new(zone) Scope(current_scope,
232  BLOCK_SCOPE,
233  Handle<ScopeInfo>(scope_info),
234  global_scope->ast_value_factory_,
235  zone);
236  } else {
237  DCHECK(context->IsCatchContext());
238  String* name = String::cast(context->extension());
239  current_scope = new (zone) Scope(
240  current_scope,
242  global_scope->ast_value_factory_, zone);
243  }
244  if (contains_with) current_scope->RecordWithStatement();
245  if (innermost_scope == NULL) innermost_scope = current_scope;
246 
247  // Forget about a with when we move to a context for a different function.
248  if (context->previous()->closure() != context->closure()) {
249  contains_with = false;
250  }
251  context = context->previous();
252  }
253 
254  global_scope->AddInnerScope(current_scope);
255  global_scope->PropagateScopeInfo(false);
256  return (innermost_scope == NULL) ? global_scope : innermost_scope;
257 }
258 
259 
261  DCHECK(info->function() != NULL);
262  Scope* scope = info->function()->scope();
263  Scope* top = scope;
264 
265  // Traverse the scope tree up to the first unresolved scope or the global
266  // scope and start scope resolution and variable allocation from that scope.
267  while (!top->is_global_scope() &&
268  !top->outer_scope()->already_resolved()) {
269  top = top->outer_scope();
270  }
271 
272  // Allocate the variables.
273  {
274  AstNodeFactory<AstNullVisitor> ast_node_factory(
275  info->zone(), info->ast_value_factory(), info->ast_node_id_gen());
276  if (!top->AllocateVariables(info, &ast_node_factory)) return false;
277  }
278 
279 #ifdef DEBUG
280  if (info->isolate()->bootstrapper()->IsActive()
281  ? FLAG_print_builtin_scopes
282  : FLAG_print_scopes) {
283  scope->Print();
284  }
285 
286  if (FLAG_harmony_modules && FLAG_print_interfaces && top->is_global_scope()) {
287  PrintF("global : ");
288  top->interface()->Print();
289  }
290 #endif
291 
292  info->PrepareForCompilation(scope);
293  return true;
294 }
295 
296 
299 
300  // Add this scope as a new inner scope of the outer scope.
301  if (outer_scope_ != NULL) {
302  outer_scope_->inner_scopes_.Add(this, zone());
304  } else {
306  }
307 
308  // Declare convenience variables.
309  // Declare and allocate receiver (even for the global scope, and even
310  // if naccesses_ == 0).
311  // NOTE: When loading parameters in the global scope, we must take
312  // care not to access them as properties of the global object, but
313  // instead load them directly from the stack. Currently, the only
314  // such parameter is 'this' which is passed on the stack when
315  // invoking scripts
316  if (is_declaration_scope()) {
317  Variable* var =
318  variables_.Declare(this,
319  ast_value_factory_->this_string(),
320  VAR,
321  false,
325  receiver_ = var;
326  } else {
327  DCHECK(outer_scope() != NULL);
329  }
330 
331  if (is_function_scope()) {
332  // Declare 'arguments' variable which exists in all functions.
333  // Note that it might never be accessed, in which case it won't be
334  // allocated during variable allocation.
335  variables_.Declare(this,
336  ast_value_factory_->arguments_string(),
337  VAR,
338  true,
341  }
342 }
343 
344 
347  DCHECK(internals_.is_empty());
348  DCHECK(temps_.is_empty());
349  DCHECK(params_.is_empty());
350 
351  if (num_var_or_const() > 0) return this;
352 
353  // Remove this scope from outer scope.
354  for (int i = 0; i < outer_scope_->inner_scopes_.length(); i++) {
355  if (outer_scope_->inner_scopes_[i] == this) {
356  outer_scope_->inner_scopes_.Remove(i);
357  break;
358  }
359  }
360 
361  // Reparent inner scopes.
362  for (int i = 0; i < inner_scopes_.length(); i++) {
364  }
365 
366  // Move unresolved variables
367  for (int i = 0; i < unresolved_.length(); i++) {
369  }
370 
371  return NULL;
372 }
373 
374 
376  Variable* result = variables_.Lookup(name);
377  if (result != NULL || scope_info_.is_null()) {
378  return result;
379  }
380  // The Scope is backed up by ScopeInfo. This means it cannot operate in a
381  // heap-independent mode, and all strings must be internalized immediately. So
382  // it's ok to get the Handle<String> here.
383  Handle<String> name_handle = name->string();
384  // If we have a serialized scope info, we might find the variable there.
385  // There should be no local slot with the given name.
386  DCHECK(scope_info_->StackSlotIndex(*name_handle) < 0);
387 
388  // Check context slot lookup.
391  InitializationFlag init_flag;
392  MaybeAssignedFlag maybe_assigned_flag;
393  int index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode,
394  &init_flag, &maybe_assigned_flag);
395  if (index < 0) {
396  // Check parameters.
397  index = scope_info_->ParameterIndex(*name_handle);
398  if (index < 0) return NULL;
399 
400  mode = DYNAMIC;
401  location = Variable::LOOKUP;
402  init_flag = kCreatedInitialized;
403  // Be conservative and flag parameters as maybe assigned. Better information
404  // would require ScopeInfo to serialize the maybe_assigned bit also for
405  // parameters.
406  maybe_assigned_flag = kMaybeAssigned;
407  }
408 
409  Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL,
410  init_flag, maybe_assigned_flag);
411  var->AllocateTo(location, index);
412  return var;
413 }
414 
415 
418  if (function_ != NULL && function_->proxy()->raw_name() == name) {
419  return function_->proxy()->var();
420  } else if (!scope_info_.is_null()) {
421  // If we are backed by a scope info, try to lookup the variable there.
423  int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode);
424  if (index < 0) return NULL;
425  Variable* var = new(zone()) Variable(
426  this, name, mode, true /* is valid LHS */,
428  VariableProxy* proxy = factory->NewVariableProxy(var);
429  VariableDeclaration* declaration = factory->NewVariableDeclaration(
430  proxy, mode, this, RelocInfo::kNoPosition);
431  DeclareFunctionVar(declaration);
432  var->AllocateTo(Variable::CONTEXT, index);
433  return var;
434  } else {
435  return NULL;
436  }
437 }
438 
439 
441  for (Scope* scope = this;
442  scope != NULL;
443  scope = scope->outer_scope()) {
444  Variable* var = scope->LookupLocal(name);
445  if (var != NULL) return var;
446  }
447  return NULL;
448 }
449 
450 
454  Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL,
456  params_.Add(var, zone());
457  return var;
458 }
459 
460 
462  InitializationFlag init_flag,
463  MaybeAssignedFlag maybe_assigned_flag,
464  Interface* interface) {
466  // This function handles VAR, LET, and CONST modes. DYNAMIC variables are
467  // introduces during variable allocation, INTERNAL variables are allocated
468  // explicitly, and TEMPORARY variables are allocated via NewTemporary().
471  return variables_.Declare(this, name, mode, true, Variable::NORMAL, init_flag,
472  maybe_assigned_flag, interface);
473 }
474 
475 
478  return variables_.Declare(this,
479  name,
481  true,
484 }
485 
486 
487 void Scope::RemoveUnresolved(VariableProxy* var) {
488  // Most likely (always?) any variable we want to remove
489  // was just added before, so we search backwards.
490  for (int i = unresolved_.length(); i-- > 0;) {
491  if (unresolved_[i] == var) {
493  return;
494  }
495  }
496 }
497 
498 
501  Variable* var = new(zone()) Variable(this,
502  name,
503  INTERNAL,
504  false,
507  internals_.Add(var, zone());
508  return var;
509 }
510 
511 
514  Variable* var = new(zone()) Variable(this,
515  name,
516  TEMPORARY,
517  true,
520  temps_.Add(var, zone());
521  return var;
522 }
523 
524 
525 void Scope::AddDeclaration(Declaration* declaration) {
526  decls_.Add(declaration, zone());
527 }
528 
529 
531  // Record only the first illegal redeclaration.
532  if (!HasIllegalRedeclaration()) {
533  illegal_redecl_ = expression;
534  }
536 }
537 
538 
541  illegal_redecl_->Accept(visitor);
542 }
543 
544 
546  int length = decls_.length();
547  for (int i = 0; i < length; i++) {
548  Declaration* decl = decls_[i];
549  if (decl->mode() != VAR) continue;
550  const AstRawString* name = decl->proxy()->raw_name();
551 
552  // Iterate through all scopes until and including the declaration scope.
553  Scope* previous = NULL;
554  Scope* current = decl->scope();
555  do {
556  // There is a conflict if there exists a non-VAR binding.
557  Variable* other_var = current->variables_.Lookup(name);
558  if (other_var != NULL && other_var->mode() != VAR) {
559  return decl;
560  }
561  previous = current;
562  current = current->outer_scope_;
563  } while (!previous->is_declaration_scope());
564  }
565  return NULL;
566 }
567 
568 
569 class VarAndOrder {
570  public:
572  Variable* var() const { return var_; }
573  int order() const { return order_; }
574  static int Compare(const VarAndOrder* a, const VarAndOrder* b) {
575  return a->order_ - b->order_;
576  }
577 
578  private:
580  int order_;
581 };
582 
583 
585  ZoneList<Variable*>* context_locals) {
586  DCHECK(stack_locals != NULL);
587  DCHECK(context_locals != NULL);
588 
589  // Collect internals which are always allocated on the heap.
590  for (int i = 0; i < internals_.length(); i++) {
591  Variable* var = internals_[i];
592  if (var->is_used()) {
593  DCHECK(var->IsContextSlot());
594  context_locals->Add(var, zone());
595  }
596  }
597 
598  // Collect temporaries which are always allocated on the stack, unless the
599  // context as a whole has forced context allocation.
600  for (int i = 0; i < temps_.length(); i++) {
601  Variable* var = temps_[i];
602  if (var->is_used()) {
603  if (var->IsContextSlot()) {
605  context_locals->Add(var, zone());
606  } else {
607  DCHECK(var->IsStackLocal());
608  stack_locals->Add(var, zone());
609  }
610  }
611  }
612 
613  // Collect declared local variables.
615  for (VariableMap::Entry* p = variables_.Start();
616  p != NULL;
617  p = variables_.Next(p)) {
618  Variable* var = reinterpret_cast<Variable*>(p->value);
619  if (var->is_used()) {
620  vars.Add(VarAndOrder(var, p->order), zone());
621  }
622  }
624  int var_count = vars.length();
625  for (int i = 0; i < var_count; i++) {
626  Variable* var = vars[i].var();
627  if (var->IsStackLocal()) {
628  stack_locals->Add(var, zone());
629  } else if (var->IsContextSlot()) {
630  context_locals->Add(var, zone());
631  }
632  }
633 }
634 
635 
638  // 1) Propagate scope information.
639  bool outer_scope_calls_sloppy_eval = false;
640  if (outer_scope_ != NULL) {
644  }
646 
647  // 2) Allocate module instances.
648  if (FLAG_harmony_modules && (is_global_scope() || is_module_scope())) {
649  DCHECK(num_modules_ == 0);
651  }
652 
653  // 3) Resolve variables.
654  if (!ResolveVariablesRecursively(info, factory)) return false;
655 
656  // 4) Allocate variables.
658 
659  return true;
660 }
661 
662 
664  // A function scope has a trivial context if it always is the global
665  // context. We iteratively scan out the context chain to see if
666  // there is anything that makes this scope non-trivial; otherwise we
667  // return true.
668  for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) {
669  if (scope->is_eval_scope()) return false;
670  if (scope->scope_inside_with_) return false;
671  if (scope->num_heap_slots_ > 0) return false;
672  }
673  return true;
674 }
675 
676 
678  Scope* outer = outer_scope_;
679  if (outer == NULL) return true;
680  // Note that the outer context may be trivial in general, but the current
681  // scope may be inside a 'with' statement in which case the outer context
682  // for this scope is not trivial.
683  return !scope_inside_with_ && outer->HasTrivialContext();
684 }
685 
686 
688  Scope* outer = outer_scope_;
689  if (outer == NULL) return true;
690  // We have to prevent lazy compilation if this scope is inside a with scope
691  // and all declaration scopes between them have empty contexts. Such
692  // declaration scopes may become invisible during scope info deserialization.
693  outer = outer->DeclarationScope();
694  bool found_non_trivial_declarations = false;
695  for (const Scope* scope = outer; scope != NULL; scope = scope->outer_scope_) {
696  if (scope->is_with_scope() && !found_non_trivial_declarations) return false;
697  if (scope->is_declaration_scope() && scope->num_heap_slots() > 0) {
698  found_non_trivial_declarations = true;
699  }
700  }
701  return true;
702 }
703 
704 
707 }
708 
709 
712 }
713 
714 
716  int n = 0;
717  for (Scope* s = this; s != scope; s = s->outer_scope_) {
718  DCHECK(s != NULL); // scope must be in the scope chain
719  if (s->is_with_scope() || s->num_heap_slots() > 0) n++;
720  // Catch and module scopes always have heap slots.
721  DCHECK(!s->is_catch_scope() || s->num_heap_slots() > 0);
722  DCHECK(!s->is_module_scope() || s->num_heap_slots() > 0);
723  }
724  return n;
725 }
726 
727 
729  Scope* scope = this;
730  while (!scope->is_global_scope()) {
731  scope = scope->outer_scope();
732  }
733  return scope;
734 }
735 
736 
738  Scope* scope = this;
739  while (!scope->is_declaration_scope()) {
740  scope = scope->outer_scope();
741  }
742  return scope;
743 }
744 
745 
747  if (scope_info_.is_null()) {
749  }
750  return scope_info_;
751 }
752 
753 
755  List<Handle<ScopeInfo> >* chain,
756  int position) {
757  if (!is_eval_scope()) chain->Add(Handle<ScopeInfo>(GetScopeInfo()));
758 
759  for (int i = 0; i < inner_scopes_.length(); i++) {
760  Scope* scope = inner_scopes_[i];
761  int beg_pos = scope->start_position();
762  int end_pos = scope->end_position();
763  DCHECK(beg_pos >= 0 && end_pos >= 0);
764  if (beg_pos <= position && position < end_pos) {
765  scope->GetNestedScopeChain(chain, position);
766  return;
767  }
768  }
769 }
770 
771 
772 #ifdef DEBUG
773 static const char* Header(ScopeType scope_type) {
774  switch (scope_type) {
775  case EVAL_SCOPE: return "eval";
776  case FUNCTION_SCOPE: return "function";
777  case MODULE_SCOPE: return "module";
778  case GLOBAL_SCOPE: return "global";
779  case CATCH_SCOPE: return "catch";
780  case BLOCK_SCOPE: return "block";
781  case WITH_SCOPE: return "with";
782  }
783  UNREACHABLE();
784  return NULL;
785 }
786 
787 
788 static void Indent(int n, const char* str) {
789  PrintF("%*s%s", n, "", str);
790 }
791 
792 
793 static void PrintName(const AstRawString* name) {
794  PrintF("%.*s", name->length(), name->raw_data());
795 }
796 
797 
798 static void PrintLocation(Variable* var) {
799  switch (var->location()) {
801  break;
802  case Variable::PARAMETER:
803  PrintF("parameter[%d]", var->index());
804  break;
805  case Variable::LOCAL:
806  PrintF("local[%d]", var->index());
807  break;
808  case Variable::CONTEXT:
809  PrintF("context[%d]", var->index());
810  break;
811  case Variable::LOOKUP:
812  PrintF("lookup");
813  break;
814  }
815 }
816 
817 
818 static void PrintVar(int indent, Variable* var) {
819  if (var->is_used() || !var->IsUnallocated()) {
820  Indent(indent, Variable::Mode2String(var->mode()));
821  PrintF(" ");
822  PrintName(var->raw_name());
823  PrintF("; // ");
824  PrintLocation(var);
825  bool comma = !var->IsUnallocated();
826  if (var->has_forced_context_allocation()) {
827  if (comma) PrintF(", ");
828  PrintF("forced context allocation");
829  comma = true;
830  }
831  if (var->maybe_assigned() == kMaybeAssigned) {
832  if (comma) PrintF(", ");
833  PrintF("maybe assigned");
834  }
835  PrintF("\n");
836  }
837 }
838 
839 
840 static void PrintMap(int indent, VariableMap* map) {
841  for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) {
842  Variable* var = reinterpret_cast<Variable*>(p->value);
843  PrintVar(indent, var);
844  }
845 }
846 
847 
848 void Scope::Print(int n) {
849  int n0 = (n > 0 ? n : 0);
850  int n1 = n0 + 2; // indentation
851 
852  // Print header.
853  Indent(n0, Header(scope_type_));
854  if (!scope_name_->IsEmpty()) {
855  PrintF(" ");
856  PrintName(scope_name_);
857  }
858 
859  // Print parameters, if any.
860  if (is_function_scope()) {
861  PrintF(" (");
862  for (int i = 0; i < params_.length(); i++) {
863  if (i > 0) PrintF(", ");
864  PrintName(params_[i]->raw_name());
865  }
866  PrintF(")");
867  }
868 
869  PrintF(" { // (%d, %d)\n", start_position(), end_position());
870 
871  // Function name, if any (named function literals, only).
872  if (function_ != NULL) {
873  Indent(n1, "// (local) function name: ");
874  PrintName(function_->proxy()->raw_name());
875  PrintF("\n");
876  }
877 
878  // Scope info.
879  if (HasTrivialOuterContext()) {
880  Indent(n1, "// scope has trivial outer context\n");
881  }
882  if (strict_mode() == STRICT) {
883  Indent(n1, "// strict mode scope\n");
884  }
885  if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
886  if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");
887  if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
889  Indent(n1, "// outer scope calls 'eval' in sloppy context\n");
890  }
891  if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
892  if (num_stack_slots_ > 0) { Indent(n1, "// ");
893  PrintF("%d stack slots\n", num_stack_slots_); }
894  if (num_heap_slots_ > 0) { Indent(n1, "// ");
895  PrintF("%d heap slots\n", num_heap_slots_); }
896 
897  // Print locals.
898  if (function_ != NULL) {
899  Indent(n1, "// function var:\n");
900  PrintVar(n1, function_->proxy()->var());
901  }
902 
903  if (temps_.length() > 0) {
904  Indent(n1, "// temporary vars:\n");
905  for (int i = 0; i < temps_.length(); i++) {
906  PrintVar(n1, temps_[i]);
907  }
908  }
909 
910  if (internals_.length() > 0) {
911  Indent(n1, "// internal vars:\n");
912  for (int i = 0; i < internals_.length(); i++) {
913  PrintVar(n1, internals_[i]);
914  }
915  }
916 
917  if (variables_.Start() != NULL) {
918  Indent(n1, "// local vars:\n");
919  PrintMap(n1, &variables_);
920  }
921 
922  if (dynamics_ != NULL) {
923  Indent(n1, "// dynamic vars:\n");
924  PrintMap(n1, dynamics_->GetMap(DYNAMIC));
925  PrintMap(n1, dynamics_->GetMap(DYNAMIC_LOCAL));
926  PrintMap(n1, dynamics_->GetMap(DYNAMIC_GLOBAL));
927  }
928 
929  // Print inner scopes (disable by providing negative n).
930  if (n >= 0) {
931  for (int i = 0; i < inner_scopes_.length(); i++) {
932  PrintF("\n");
933  inner_scopes_[i]->Print(n1);
934  }
935  }
936 
937  Indent(n0, "}\n");
938 }
939 #endif // DEBUG
940 
941 
943  if (dynamics_ == NULL) dynamics_ = new (zone()) DynamicScopePart(zone());
945  Variable* var = map->Lookup(name);
946  if (var == NULL) {
947  // Declare a new non-local.
948  InitializationFlag init_flag = (mode == VAR)
950  var = map->Declare(NULL,
951  name,
952  mode,
953  true,
955  init_flag);
956  // Allocate it by giving it a dynamic lookup.
957  var->AllocateTo(Variable::LOOKUP, -1);
958  }
959  return var;
960 }
961 
962 
963 Variable* Scope::LookupRecursive(VariableProxy* proxy,
964  BindingKind* binding_kind,
966  DCHECK(binding_kind != NULL);
967  if (already_resolved() && is_with_scope()) {
968  // Short-cut: if the scope is deserialized from a scope info, variable
969  // allocation is already fixed. We can simply return with dynamic lookup.
970  *binding_kind = DYNAMIC_LOOKUP;
971  return NULL;
972  }
973 
974  // Try to find the variable in this scope.
975  Variable* var = LookupLocal(proxy->raw_name());
976 
977  // We found a variable and we are done. (Even if there is an 'eval' in
978  // this scope which introduces the same variable again, the resulting
979  // variable remains the same.)
980  if (var != NULL) {
981  *binding_kind = BOUND;
982  return var;
983  }
984 
985  // We did not find a variable locally. Check against the function variable,
986  // if any. We can do this for all scopes, since the function variable is
987  // only present - if at all - for function scopes.
988  *binding_kind = UNBOUND;
989  var = LookupFunctionVar(proxy->raw_name(), factory);
990  if (var != NULL) {
991  *binding_kind = BOUND;
992  } else if (outer_scope_ != NULL) {
993  var = outer_scope_->LookupRecursive(proxy, binding_kind, factory);
994  if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) {
995  var->ForceContextAllocation();
996  }
997  } else {
999  }
1000 
1001  if (is_with_scope()) {
1003  // The current scope is a with scope, so the variable binding can not be
1004  // statically resolved. However, note that it was necessary to do a lookup
1005  // in the outer scope anyway, because if a binding exists in an outer scope,
1006  // the associated variable has to be marked as potentially being accessed
1007  // from inside of an inner with scope (the property may not be in the 'with'
1008  // object).
1009  if (var != NULL && proxy->is_assigned()) var->set_maybe_assigned();
1010  *binding_kind = DYNAMIC_LOOKUP;
1011  return NULL;
1012  } else if (calls_sloppy_eval()) {
1013  // A variable binding may have been found in an outer scope, but the current
1014  // scope makes a sloppy 'eval' call, so the found variable may not be
1015  // the correct one (the 'eval' may introduce a binding with the same name).
1016  // In that case, change the lookup result to reflect this situation.
1017  if (*binding_kind == BOUND) {
1018  *binding_kind = BOUND_EVAL_SHADOWED;
1019  } else if (*binding_kind == UNBOUND) {
1020  *binding_kind = UNBOUND_EVAL_SHADOWED;
1021  }
1022  }
1023  return var;
1024 }
1025 
1026 
1028  VariableProxy* proxy,
1029  AstNodeFactory<AstNullVisitor>* factory) {
1030  DCHECK(info->global_scope()->is_global_scope());
1031 
1032  // If the proxy is already resolved there's nothing to do
1033  // (functions and consts may be resolved by the parser).
1034  if (proxy->var() != NULL) return true;
1035 
1036  // Otherwise, try to resolve the variable.
1037  BindingKind binding_kind;
1038  Variable* var = LookupRecursive(proxy, &binding_kind, factory);
1039  switch (binding_kind) {
1040  case BOUND:
1041  // We found a variable binding.
1042  break;
1043 
1044  case BOUND_EVAL_SHADOWED:
1045  // We either found a variable binding that might be shadowed by eval or
1046  // gave up on it (e.g. by encountering a local with the same in the outer
1047  // scope which was not promoted to a context, this can happen if we use
1048  // debugger to evaluate arbitrary expressions at a break point).
1049  if (var->IsGlobalObjectProperty()) {
1050  var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL);
1051  } else if (var->is_dynamic()) {
1052  var = NonLocal(proxy->raw_name(), DYNAMIC);
1053  } else {
1054  Variable* invalidated = var;
1055  var = NonLocal(proxy->raw_name(), DYNAMIC_LOCAL);
1056  var->set_local_if_not_shadowed(invalidated);
1057  }
1058  break;
1059 
1060  case UNBOUND:
1061  // No binding has been found. Declare a variable on the global object.
1062  var = info->global_scope()->DeclareDynamicGlobal(proxy->raw_name());
1063  break;
1064 
1065  case UNBOUND_EVAL_SHADOWED:
1066  // No binding has been found. But some scope makes a sloppy 'eval' call.
1067  var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL);
1068  break;
1069 
1070  case DYNAMIC_LOOKUP:
1071  // The variable could not be resolved statically.
1072  var = NonLocal(proxy->raw_name(), DYNAMIC);
1073  break;
1074  }
1075 
1076  DCHECK(var != NULL);
1077  if (proxy->is_assigned()) var->set_maybe_assigned();
1078 
1079  if (FLAG_harmony_scoping && strict_mode() == STRICT &&
1080  var->is_const_mode() && proxy->is_assigned()) {
1081  // Assignment to const. Throw a syntax error.
1082  MessageLocation location(
1083  info->script(), proxy->position(), proxy->position());
1084  Isolate* isolate = info->isolate();
1085  Factory* factory = isolate->factory();
1086  Handle<JSArray> array = factory->NewJSArray(0);
1087  Handle<Object> error;
1088  MaybeHandle<Object> maybe_error =
1089  factory->NewSyntaxError("harmony_const_assign", array);
1090  if (maybe_error.ToHandle(&error)) isolate->Throw(*error, &location);
1091  return false;
1092  }
1093 
1094  if (FLAG_harmony_modules) {
1095  bool ok;
1096 #ifdef DEBUG
1097  if (FLAG_print_interface_details) {
1098  PrintF("# Resolve %.*s:\n", var->raw_name()->length(),
1099  var->raw_name()->raw_data());
1100  }
1101 #endif
1102  proxy->interface()->Unify(var->interface(), zone(), &ok);
1103  if (!ok) {
1104 #ifdef DEBUG
1105  if (FLAG_print_interfaces) {
1106  PrintF("SCOPES TYPE ERROR\n");
1107  PrintF("proxy: ");
1108  proxy->interface()->Print();
1109  PrintF("var: ");
1110  var->interface()->Print();
1111  }
1112 #endif
1113 
1114  // Inconsistent use of module. Throw a syntax error.
1115  // TODO(rossberg): generate more helpful error message.
1116  MessageLocation location(
1117  info->script(), proxy->position(), proxy->position());
1118  Isolate* isolate = info->isolate();
1119  Factory* factory = isolate->factory();
1120  Handle<JSArray> array = factory->NewJSArray(1);
1121  JSObject::SetElement(array, 0, var->name(), NONE, STRICT).Assert();
1122  Handle<Object> error;
1123  MaybeHandle<Object> maybe_error =
1124  factory->NewSyntaxError("module_type_error", array);
1125  if (maybe_error.ToHandle(&error)) isolate->Throw(*error, &location);
1126  return false;
1127  }
1128  }
1129 
1130  proxy->BindTo(var);
1131 
1132  return true;
1133 }
1134 
1135 
1137  CompilationInfo* info,
1138  AstNodeFactory<AstNullVisitor>* factory) {
1139  DCHECK(info->global_scope()->is_global_scope());
1140 
1141  // Resolve unresolved variables for this scope.
1142  for (int i = 0; i < unresolved_.length(); i++) {
1143  if (!ResolveVariable(info, unresolved_[i], factory)) return false;
1144  }
1145 
1146  // Resolve unresolved variables for inner scopes.
1147  for (int i = 0; i < inner_scopes_.length(); i++) {
1148  if (!inner_scopes_[i]->ResolveVariablesRecursively(info, factory))
1149  return false;
1150  }
1151 
1152  return true;
1153 }
1154 
1155 
1156 void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) {
1159  }
1160 
1161  bool calls_sloppy_eval =
1163  for (int i = 0; i < inner_scopes_.length(); i++) {
1164  Scope* inner = inner_scopes_[i];
1166  if (inner->scope_calls_eval_ || inner->inner_scope_calls_eval_) {
1167  inner_scope_calls_eval_ = true;
1168  }
1169  if (inner->force_eager_compilation_) {
1170  force_eager_compilation_ = true;
1171  }
1172  if (asm_module_ && inner->scope_type() == FUNCTION_SCOPE) {
1173  inner->asm_function_ = true;
1174  }
1175  }
1176 }
1177 
1178 
1180  // Give var a read/write use if there is a chance it might be accessed
1181  // via an eval() call. This is only possible if the variable has a
1182  // visible name.
1183  if ((var->is_this() || !var->raw_name()->IsEmpty()) &&
1188  is_catch_scope() ||
1189  is_block_scope() ||
1190  is_module_scope() ||
1191  is_global_scope())) {
1192  var->set_is_used();
1194  }
1195  // Global variables do not need to be allocated.
1196  return !var->IsGlobalObjectProperty() && var->is_used();
1197 }
1198 
1199 
1201  // If var is accessed from an inner scope, or if there is a possibility
1202  // that it might be accessed from the current or an inner scope (through
1203  // an eval() call or a runtime with lookup), it must be allocated in the
1204  // context.
1205  //
1206  // Exceptions: If the scope as a whole has forced context allocation, all
1207  // variables will have context allocation, even temporaries. Otherwise
1208  // temporary variables are always stack-allocated. Catch-bound variables are
1209  // always context-allocated.
1210  if (has_forced_context_allocation()) return true;
1211  if (var->mode() == TEMPORARY) return false;
1212  if (var->mode() == INTERNAL) return true;
1213  if (is_catch_scope() || is_block_scope() || is_module_scope()) return true;
1214  if (is_global_scope() && IsLexicalVariableMode(var->mode())) return true;
1215  return var->has_forced_context_allocation() ||
1219 }
1220 
1221 
1223  for (int i = 0; i < params_.length(); i++) {
1224  if (params_[i]->name().is_identical_to(
1225  isolate_->factory()->arguments_string())) {
1226  return true;
1227  }
1228  }
1229  return false;
1230 }
1231 
1232 
1235 }
1236 
1237 
1240 }
1241 
1242 
1245  Variable* arguments = LookupLocal(ast_value_factory_->arguments_string());
1246  DCHECK(arguments != NULL); // functions have 'arguments' declared implicitly
1247 
1248  bool uses_sloppy_arguments = false;
1249 
1251  // 'arguments' is used. Unless there is also a parameter called
1252  // 'arguments', we must be conservative and allocate all parameters to
1253  // the context assuming they will be captured by the arguments object.
1254  // If we have a parameter named 'arguments', a (new) value is always
1255  // assigned to it via the function invocation. Then 'arguments' denotes
1256  // that specific parameter value and cannot be used to access the
1257  // parameters, which is why we don't need to allocate an arguments
1258  // object in that case.
1259 
1260  // We are using 'arguments'. Tell the code generator that is needs to
1261  // allocate the arguments object by setting 'arguments_'.
1263 
1264  // In strict mode 'arguments' does not alias formal parameters.
1265  // Therefore in strict mode we allocate parameters as if 'arguments'
1266  // were not used.
1267  uses_sloppy_arguments = strict_mode() == SLOPPY;
1268  }
1269 
1270  // The same parameter may occur multiple times in the parameters_ list.
1271  // If it does, and if it is not copied into the context object, it must
1272  // receive the highest parameter index for that parameter; thus iteration
1273  // order is relevant!
1274  for (int i = params_.length() - 1; i >= 0; --i) {
1275  Variable* var = params_[i];
1276  DCHECK(var->scope() == this);
1277  if (uses_sloppy_arguments || has_forced_context_allocation()) {
1278  // Force context allocation of the parameter.
1279  var->ForceContextAllocation();
1280  }
1281 
1282  if (MustAllocate(var)) {
1283  if (MustAllocateInContext(var)) {
1284  DCHECK(var->IsUnallocated() || var->IsContextSlot());
1285  if (var->IsUnallocated()) {
1286  AllocateHeapSlot(var);
1287  }
1288  } else {
1289  DCHECK(var->IsUnallocated() || var->IsParameter());
1290  if (var->IsUnallocated()) {
1292  }
1293  }
1294  }
1295  }
1296 }
1297 
1298 
1300  DCHECK(var->scope() == this);
1301  DCHECK(!var->IsVariable(isolate_->factory()->dot_result_string()) ||
1302  !var->IsStackLocal());
1303  if (var->IsUnallocated() && MustAllocate(var)) {
1304  if (MustAllocateInContext(var)) {
1305  AllocateHeapSlot(var);
1306  } else {
1307  AllocateStackSlot(var);
1308  }
1309  }
1310 }
1311 
1312 
1314  // All variables that have no rewrite yet are non-parameter locals.
1315  for (int i = 0; i < temps_.length(); i++) {
1317  }
1318 
1319  for (int i = 0; i < internals_.length(); i++) {
1321  }
1322 
1324  for (VariableMap::Entry* p = variables_.Start();
1325  p != NULL;
1326  p = variables_.Next(p)) {
1327  Variable* var = reinterpret_cast<Variable*>(p->value);
1328  vars.Add(VarAndOrder(var, p->order), zone());
1329  }
1330  vars.Sort(VarAndOrder::Compare);
1331  int var_count = vars.length();
1332  for (int i = 0; i < var_count; i++) {
1333  AllocateNonParameterLocal(vars[i].var());
1334  }
1335 
1336  // For now, function_ must be allocated at the very end. If it gets
1337  // allocated in the context, it must be the last slot in the context,
1338  // because of the current ScopeInfo implementation (see
1339  // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
1340  if (function_ != NULL) {
1341  AllocateNonParameterLocal(function_->proxy()->var());
1342  }
1343 }
1344 
1345 
1347  // Allocate variables for inner scopes.
1348  for (int i = 0; i < inner_scopes_.length(); i++) {
1349  inner_scopes_[i]->AllocateVariablesRecursively();
1350  }
1351 
1352  // If scope is already resolved, we still need to allocate
1353  // variables in inner scopes which might not had been resolved yet.
1354  if (already_resolved()) return;
1355  // The number of slots required for variables.
1356  num_stack_slots_ = 0;
1358 
1359  // Allocate variables for this scope.
1360  // Parameters must be allocated first, if any.
1363 
1364  // Force allocation of a context for this scope if necessary. For a 'with'
1365  // scope and for a function scope that makes an 'eval' call we need a context,
1366  // even if no local variables were statically allocated in the scope.
1367  // Likewise for modules.
1368  bool must_have_context = is_with_scope() || is_module_scope() ||
1369  (is_function_scope() && calls_eval());
1370 
1371  // If we didn't allocate any locals in the local context, then we only
1372  // need the minimal number of slots if we must have a context.
1373  if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) {
1374  num_heap_slots_ = 0;
1375  }
1376 
1377  // Allocation done.
1379 }
1380 
1381 
1383  if (already_resolved()) return;
1384  if (is_module_scope()) {
1386  DCHECK(module_var_ == NULL);
1387  module_var_ =
1388  host_scope->NewInternal(ast_value_factory_->dot_module_string());
1389  ++host_scope->num_modules_;
1390  }
1391 
1392  for (int i = 0; i < inner_scopes_.length(); i++) {
1393  Scope* inner_scope = inner_scopes_.at(i);
1394  inner_scope->AllocateModulesRecursively(host_scope);
1395  }
1396 }
1397 
1398 
1400  return num_stack_slots() -
1401  (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0);
1402 }
1403 
1404 
1406  if (num_heap_slots() == 0) return 0;
1408  (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0);
1409 }
1410 
1411 } } // namespace v8::internal
virtual void Accept(AstVisitor *v)=0
const unsigned char * raw_data() const
virtual int length() const OVERRIDE
const AstRawString * GetString(Handle< String > literal)
AstNode::IdGen * ast_node_id_gen()
Definition: compiler.h:395
void PrepareForCompilation(Scope *scope)
Definition: compiler.cc:276
Scope * global_scope() const
Definition: compiler.h:109
Handle< Script > script() const
Definition: compiler.h:113
AstValueFactory * ast_value_factory() const
Definition: compiler.h:388
FunctionLiteral * function() const
Definition: compiler.h:107
Isolate * isolate() const
Definition: compiler.h:96
Object * extension()
Definition: contexts.h:427
Context * previous()
Definition: contexts.h:419
JSModule * module()
Definition: contexts.h:430
bool IsFunctionContext()
Definition: contexts.h:466
JSFunction * closure()
Definition: contexts.h:416
VariableMode mode() const
Definition: ast.h:490
Scope * scope() const
Definition: ast.h:491
VariableProxy * proxy() const
Definition: ast.h:489
VariableMap * GetMap(VariableMode mode)
Definition: scopes.h:50
bool is_null() const
Definition: handles.h:124
Object * Throw(Object *exception, MessageLocation *location=NULL)
Definition: isolate.cc:832
Factory * factory()
Definition: isolate.h:982
Bootstrapper * bootstrapper()
Definition: isolate.h:856
static MUST_USE_RESULT MaybeHandle< Object > SetElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode, bool check_prototype=true, SetPropertyMode set_mode=SET_PROPERTY)
Definition: objects.cc:12336
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:17
T Remove(int i)
Definition: list-inl.h:103
void Sort(int(*cmp)(const T *x, const T *y))
Definition: list-inl.h:194
static const int kNoPosition
Definition: assembler.h:317
static int ContextSlotIndex(Handle< ScopeInfo > scope_info, Handle< String > name, VariableMode *mode, InitializationFlag *init_flag, MaybeAssignedFlag *maybe_assigned_flag)
Definition: scopeinfo.cc:296
static Handle< ScopeInfo > Create(Scope *scope, Zone *zone)
Definition: scopeinfo.cc:16
int ContextLocalCount() const
Definition: scopes.cc:1405
void SetDefaults(ScopeType type, Scope *outer_scope, Handle< ScopeInfo > scope_info)
Definition: scopes.cc:149
void AllocateNonParameterLocal(Variable *var)
Definition: scopes.cc:1299
int num_heap_slots() const
Definition: scopes.h:352
void AllocateHeapSlot(Variable *var)
Definition: scopes.cc:1238
bool outer_scope_calls_sloppy_eval_
Definition: scopes.h:482
StrictMode strict_mode_
Definition: scopes.h:476
bool contains_with() const
Definition: scopes.h:293
bool is_global_scope() const
Definition: scopes.h:267
bool AllowsLazyCompilationWithoutContext() const
Definition: scopes.cc:710
Variable * LookupFunctionVar(const AstRawString *name, AstNodeFactory< AstNullVisitor > *factory)
Definition: scopes.cc:416
ZoneList< Variable * > temps_
Definition: scopes.h:441
MUST_USE_RESULT bool AllocateVariables(CompilationInfo *info, AstNodeFactory< AstNullVisitor > *factory)
Definition: scopes.cc:636
bool force_eager_compilation_
Definition: scopes.h:484
static bool Analyze(CompilationInfo *info)
Definition: scopes.cc:260
Variable * Lookup(const AstRawString *name)
Definition: scopes.cc:440
void DeclareFunctionVar(VariableDeclaration *declaration)
Definition: scopes.h:120
const AstRawString * scope_name_
Definition: scopes.h:430
ScopeType scope_type_
Definition: scopes.h:427
ZoneList< VariableProxy * > unresolved_
Definition: scopes.h:447
void AllocateParameterLocals()
Definition: scopes.cc:1243
Handle< ScopeInfo > scope_info_
Definition: scopes.h:505
Scope * outer_scope() const
Definition: scopes.h:333
bool scope_calls_eval_
Definition: scopes.h:470
bool HasTrivialOuterContext() const
Definition: scopes.cc:677
Variable * DeclareDynamicGlobal(const AstRawString *name)
Definition: scopes.cc:476
Variable * module_var_
Definition: scopes.h:502
Variable * DeclareLocal(const AstRawString *name, VariableMode mode, InitializationFlag init_flag, MaybeAssignedFlag maybe_assigned_flag=kNotAssigned, Interface *interface=Interface::NewValue())
Definition: scopes.cc:461
void AllocateNonParameterLocals()
Definition: scopes.cc:1313
Variable * LookupRecursive(VariableProxy *proxy, BindingKind *binding_kind, AstNodeFactory< AstNullVisitor > *factory)
Definition: scopes.cc:963
bool HasLazyCompilableOuterContext() const
Definition: scopes.cc:687
int ContextChainLength(Scope *scope)
Definition: scopes.cc:715
Scope * outer_scope_
Definition: scopes.h:423
ZoneList< Scope * > inner_scopes_
Definition: scopes.h:424
bool HasTrivialContext() const
Definition: scopes.cc:663
bool calls_sloppy_eval()
Definition: scopes.h:281
void AllocateVariablesRecursively()
Definition: scopes.cc:1346
Variable * NewInternal(const AstRawString *name)
Definition: scopes.cc:499
VariableMap variables_
Definition: scopes.h:437
void AddInnerScope(Scope *inner_scope)
Definition: scopes.h:612
bool scope_inside_with_
Definition: scopes.h:465
void PropagateScopeInfo(bool outer_scope_calls_sloppy_eval)
Definition: scopes.cc:1156
bool calls_eval() const
Definition: scopes.h:280
ZoneList< Variable * > params_
Definition: scopes.h:443
bool HasIllegalRedeclaration() const
Definition: scopes.h:198
Variable * receiver()
Definition: scopes.h:305
bool is_eval_scope() const
Definition: scopes.h:264
void SetIllegalRedeclaration(Expression *expression)
Definition: scopes.cc:530
void CollectStackAndContextLocals(ZoneList< Variable * > *stack_locals, ZoneList< Variable * > *context_locals)
Definition: scopes.cc:584
bool is_function_scope() const
Definition: scopes.h:265
ZoneList< Declaration * > decls_
Definition: scopes.h:449
ScopeType scope_type() const
Definition: scopes.h:299
bool AllowsLazyCompilation() const
Definition: scopes.cc:705
void AllocateStackSlot(Variable *var)
Definition: scopes.cc:1233
MUST_USE_RESULT bool ResolveVariable(CompilationInfo *info, VariableProxy *proxy, AstNodeFactory< AstNullVisitor > *factory)
Definition: scopes.cc:1027
bool MustAllocateInContext(Variable *var)
Definition: scopes.cc:1200
bool outer_scope_calls_sloppy_eval() const
Definition: scopes.h:284
void VisitIllegalRedeclaration(AstVisitor *visitor)
Definition: scopes.cc:539
Isolate *const isolate_
Definition: scopes.h:420
bool HasArgumentsParameter()
Definition: scopes.cc:1222
Variable * receiver_
Definition: scopes.h:451
void AllocateModulesRecursively(Scope *host_scope)
Definition: scopes.cc:1382
void RemoveUnresolved(VariableProxy *var)
Definition: scopes.cc:487
Variable * NonLocal(const AstRawString *name, VariableMode mode)
Definition: scopes.cc:942
ZoneList< Variable * > internals_
Definition: scopes.h:439
Scope * DeclarationScope()
Definition: scopes.cc:737
Variable * arguments() const
Definition: scopes.h:324
Expression * illegal_redecl_
Definition: scopes.h:460
Variable * NewTemporary(const AstRawString *name)
Definition: scopes.cc:512
Zone * zone() const
Definition: scopes.h:98
DynamicScopePart * dynamics_
Definition: scopes.h:445
bool inner_scope_calls_eval_
Definition: scopes.h:483
bool is_with_scope() const
Definition: scopes.h:270
bool scope_contains_with_
Definition: scopes.h:467
AstValueFactory * ast_value_factory_
Definition: scopes.h:623
Scope * GlobalScope()
Definition: scopes.cc:728
Scope(Scope *outer_scope, ScopeType scope_type, AstValueFactory *value_factory, Zone *zone)
Definition: scopes.cc:70
bool is_block_scope() const
Definition: scopes.h:269
Scope * FinalizeBlockScope()
Definition: scopes.cc:345
int num_stack_slots() const
Definition: scopes.h:351
StrictMode strict_mode() const
Definition: scopes.h:302
Declaration * CheckConflictingVarDeclarations()
Definition: scopes.cc:545
int end_position() const
Definition: scopes.h:246
bool has_forced_context_allocation() const
Definition: scopes.h:256
bool MustAllocate(Variable *var)
Definition: scopes.cc:1179
Variable * DeclareParameter(const AstRawString *name, VariableMode mode)
Definition: scopes.cc:451
VariableDeclaration * function_
Definition: scopes.h:453
Interface * interface() const
Definition: scopes.h:336
void RecordWithStatement()
Definition: scopes.h:209
bool already_resolved()
Definition: scopes.h:506
bool force_context_allocation_
Definition: scopes.h:485
Handle< ScopeInfo > GetScopeInfo()
Definition: scopes.cc:746
int num_var_or_const()
Definition: scopes.h:348
void AddDeclaration(Declaration *declaration)
Definition: scopes.cc:525
static Scope * DeserializeScopeChain(Context *context, Scope *global_scope, Zone *zone)
Definition: scopes.cc:187
Variable * arguments_
Definition: scopes.h:455
Interface * interface_
Definition: scopes.h:457
bool is_catch_scope() const
Definition: scopes.h:268
int start_position() const
Definition: scopes.h:242
bool is_module_scope() const
Definition: scopes.h:266
void GetNestedScopeChain(List< Handle< ScopeInfo > > *chain, int statement_position)
Definition: scopes.cc:754
MUST_USE_RESULT bool ResolveVariablesRecursively(CompilationInfo *info, AstNodeFactory< AstNullVisitor > *factory)
Definition: scopes.cc:1136
int StackLocalCount() const
Definition: scopes.cc:1399
bool is_declaration_scope() const
Definition: scopes.h:271
Variable * LookupLocal(const AstRawString *name)
Definition: scopes.cc:375
Entry * Next(Entry *p) const
Definition: hashmap.h:226
uint32_t occupancy() const
Definition: hashmap.h:61
Entry * Lookup(void *key, uint32_t hash, bool insert, ZoneAllocationPolicy allocator=ZoneAllocationPolicy())
Definition: hashmap.h:114
static int Compare(const VarAndOrder *a, const VarAndOrder *b)
Definition: scopes.cc:574
VarAndOrder(Variable *var, int order)
Definition: scopes.cc:571
Variable * var() const
Definition: scopes.cc:572
Variable * Declare(Scope *scope, const AstRawString *name, VariableMode mode, bool is_valid_lhs, Variable::Kind kind, InitializationFlag initialization_flag, MaybeAssignedFlag maybe_assigned_flag=kNotAssigned, Interface *interface=Interface::NewValue())
Definition: scopes.cc:33
Zone * zone() const
Definition: scopes.h:32
Variable * Lookup(const AstRawString *name)
Definition: scopes.cc:55
virtual ~VariableMap()
Definition: scopes.cc:30
VariableMap(Zone *zone)
Definition: scopes.cc:27
Handle< String > name() const
Definition: variables.h:71
bool is_dynamic() const
Definition: variables.h:101
static const char * Mode2String(VariableMode mode)
Definition: variables.cc:17
VariableMode mode() const
Definition: variables.h:73
bool is_const_mode() const
Definition: variables.h:102
Interface * interface() const
Definition: variables.h:129
bool IsParameter() const
Definition: variables.h:94
bool is_this() const
Definition: variables.h:107
Scope * scope() const
Definition: variables.h:69
bool IsVariable(Handle< String > n) const
Definition: variables.h:89
void AllocateTo(Location location, int index)
Definition: variables.h:131
void set_local_if_not_shadowed(Variable *local)
Definition: variables.h:120
bool has_forced_context_allocation() const
Definition: variables.h:74
bool IsGlobalObjectProperty() const
Definition: variables.cc:58
bool IsStackLocal() const
Definition: variables.h:95
const AstRawString * raw_name() const
Definition: variables.h:72
void ForceContextAllocation()
Definition: variables.h:77
bool IsContextSlot() const
Definition: variables.h:97
bool IsUnallocated() const
Definition: variables.h:93
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 map
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 true
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 DCHECK(condition)
Definition: logging.h:205
InitializationFlag
Definition: globals.h:751
@ kNeedsInitialization
Definition: globals.h:752
@ kCreatedInitialized
Definition: globals.h:753
bool IsLexicalVariableMode(VariableMode mode)
Definition: globals.h:710
bool IsDeclaredVariableMode(VariableMode mode)
Definition: globals.h:705
@ kMaybeAssigned
Definition: globals.h:757
@ DYNAMIC_GLOBAL
Definition: globals.h:689
@ DYNAMIC_LOCAL
Definition: globals.h:693
static LifetimePosition Max(LifetimePosition a, LifetimePosition b)
void PrintF(const char *format,...)
Definition: utils.cc:80
@ FUNCTION_SCOPE
Definition: globals.h:647
@ MODULE_SCOPE
Definition: globals.h:648
@ GLOBAL_SCOPE
Definition: globals.h:649
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
@ NONE