v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
scopes.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "v8.h"
29 
30 #include "scopes.h"
31 
32 #include "accessors.h"
33 #include "bootstrapper.h"
34 #include "compiler.h"
35 #include "messages.h"
36 #include "scopeinfo.h"
37 
38 namespace v8 {
39 namespace internal {
40 
41 // ----------------------------------------------------------------------------
42 // Implementation of LocalsMap
43 //
44 // Note: We are storing the handle locations as key values in the hash map.
45 // When inserting a new variable via Declare(), we rely on the fact that
46 // the handle location remains alive for the duration of that variable
47 // use. Because a Variable holding a handle with the same location exists
48 // this is ensured.
49 
50 static bool Match(void* key1, void* key2) {
51  String* name1 = *reinterpret_cast<String**>(key1);
52  String* name2 = *reinterpret_cast<String**>(key2);
53  ASSERT(name1->IsInternalizedString());
54  ASSERT(name2->IsInternalizedString());
55  return name1 == name2;
56 }
57 
58 
60  : ZoneHashMap(Match, 8, ZoneAllocationPolicy(zone)),
61  zone_(zone) {}
63 
64 
66  Scope* scope,
69  bool is_valid_lhs,
70  Variable::Kind kind,
71  InitializationFlag initialization_flag,
73  Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), true,
75  if (p->value == NULL) {
76  // The variable has not been declared yet -> insert it.
77  ASSERT(p->key == name.location());
78  p->value = new(zone()) Variable(scope,
79  name,
80  mode,
81  is_valid_lhs,
82  kind,
83  initialization_flag,
84  interface);
85  }
86  return reinterpret_cast<Variable*>(p->value);
87 }
88 
89 
91  Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), false,
93  if (p != NULL) {
94  ASSERT(*reinterpret_cast<String**>(p->key) == *name);
95  ASSERT(p->value != NULL);
96  return reinterpret_cast<Variable*>(p->value);
97  }
98  return NULL;
99 }
100 
101 
102 // ----------------------------------------------------------------------------
103 // Implementation of Scope
104 
105 Scope::Scope(Scope* outer_scope, ScopeType scope_type, Zone* zone)
106  : isolate_(zone->isolate()),
107  inner_scopes_(4, zone),
108  variables_(zone),
109  internals_(4, zone),
110  temps_(4, zone),
111  params_(4, zone),
112  unresolved_(16, zone),
113  decls_(4, zone),
114  interface_(FLAG_harmony_modules &&
115  (scope_type == MODULE_SCOPE || scope_type == GLOBAL_SCOPE)
116  ? Interface::NewModule(zone) : NULL),
117  already_resolved_(false),
118  zone_(zone) {
119  SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null());
120  // The outermost scope must be a global scope.
121  ASSERT(scope_type == GLOBAL_SCOPE || outer_scope != NULL);
123 }
124 
125 
126 Scope::Scope(Scope* inner_scope,
127  ScopeType scope_type,
128  Handle<ScopeInfo> scope_info,
129  Zone* zone)
130  : isolate_(zone->isolate()),
131  inner_scopes_(4, zone),
132  variables_(zone),
133  internals_(4, zone),
134  temps_(4, zone),
135  params_(4, zone),
136  unresolved_(16, zone),
137  decls_(4, zone),
138  interface_(NULL),
139  already_resolved_(true),
140  zone_(zone) {
141  SetDefaults(scope_type, NULL, scope_info);
142  if (!scope_info.is_null()) {
143  num_heap_slots_ = scope_info_->ContextLength();
144  }
145  // Ensure at least MIN_CONTEXT_SLOTS to indicate a materialized context.
147  static_cast<int>(Context::MIN_CONTEXT_SLOTS));
148  AddInnerScope(inner_scope);
149 }
150 
151 
152 Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone)
153  : isolate_(zone->isolate()),
154  inner_scopes_(1, zone),
155  variables_(zone),
156  internals_(0, zone),
157  temps_(0, zone),
158  params_(0, zone),
159  unresolved_(0, zone),
160  decls_(0, zone),
161  interface_(NULL),
162  already_resolved_(true),
163  zone_(zone) {
164  SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null());
165  AddInnerScope(inner_scope);
168  Variable* variable = variables_.Declare(this,
169  catch_variable_name,
170  VAR,
171  true, // Valid left-hand side.
174  AllocateHeapSlot(variable);
175 }
176 
177 
178 void Scope::SetDefaults(ScopeType scope_type,
179  Scope* outer_scope,
180  Handle<ScopeInfo> scope_info) {
183  scope_name_ = isolate_->factory()->empty_string();
184  dynamics_ = NULL;
185  receiver_ = NULL;
186  function_ = NULL;
187  arguments_ = NULL;
189  scope_inside_with_ = false;
190  scope_contains_with_ = false;
191  scope_calls_eval_ = false;
192  // Inherit the strict mode from the parent scope.
193  strict_mode_ = outer_scope != NULL ? outer_scope->strict_mode_ : SLOPPY;
195  inner_scope_calls_eval_ = false;
196  force_eager_compilation_ = false;
197  force_context_allocation_ = (outer_scope != NULL && !is_function_scope())
198  ? outer_scope->has_forced_context_allocation() : false;
199  num_var_or_const_ = 0;
200  num_stack_slots_ = 0;
201  num_heap_slots_ = 0;
202  num_modules_ = 0;
203  module_var_ = NULL,
204  scope_info_ = scope_info;
205  start_position_ = RelocInfo::kNoPosition;
206  end_position_ = RelocInfo::kNoPosition;
207  if (!scope_info.is_null()) {
208  scope_calls_eval_ = scope_info->CallsEval();
209  strict_mode_ = scope_info->strict_mode();
210  }
211 }
212 
213 
215  Zone* zone) {
216  // Reconstruct the outer scope chain from a closure's context chain.
217  Scope* current_scope = NULL;
218  Scope* innermost_scope = NULL;
219  bool contains_with = false;
220  while (!context->IsNativeContext()) {
221  if (context->IsWithContext()) {
222  Scope* with_scope = new(zone) Scope(current_scope,
223  WITH_SCOPE,
225  zone);
226  current_scope = with_scope;
227  // All the inner scopes are inside a with.
228  contains_with = true;
229  for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) {
230  s->scope_inside_with_ = true;
231  }
232  } else if (context->IsGlobalContext()) {
233  ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
234  current_scope = new(zone) Scope(current_scope,
235  GLOBAL_SCOPE,
236  Handle<ScopeInfo>(scope_info),
237  zone);
238  } else if (context->IsModuleContext()) {
239  ScopeInfo* scope_info = ScopeInfo::cast(context->module()->scope_info());
240  current_scope = new(zone) Scope(current_scope,
241  MODULE_SCOPE,
242  Handle<ScopeInfo>(scope_info),
243  zone);
244  } else if (context->IsFunctionContext()) {
245  ScopeInfo* scope_info = context->closure()->shared()->scope_info();
246  current_scope = new(zone) Scope(current_scope,
248  Handle<ScopeInfo>(scope_info),
249  zone);
250  } else if (context->IsBlockContext()) {
251  ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
252  current_scope = new(zone) Scope(current_scope,
253  BLOCK_SCOPE,
254  Handle<ScopeInfo>(scope_info),
255  zone);
256  } else {
257  ASSERT(context->IsCatchContext());
258  String* name = String::cast(context->extension());
259  current_scope = new(zone) Scope(
260  current_scope, Handle<String>(name), zone);
261  }
262  if (contains_with) current_scope->RecordWithStatement();
263  if (innermost_scope == NULL) innermost_scope = current_scope;
264 
265  // Forget about a with when we move to a context for a different function.
266  if (context->previous()->closure() != context->closure()) {
267  contains_with = false;
268  }
269  context = context->previous();
270  }
271 
272  global_scope->AddInnerScope(current_scope);
273  global_scope->PropagateScopeInfo(false);
274  return (innermost_scope == NULL) ? global_scope : innermost_scope;
275 }
276 
277 
279  ASSERT(info->function() != NULL);
280  Scope* scope = info->function()->scope();
281  Scope* top = scope;
282 
283  // Traverse the scope tree up to the first unresolved scope or the global
284  // scope and start scope resolution and variable allocation from that scope.
285  while (!top->is_global_scope() &&
286  !top->outer_scope()->already_resolved()) {
287  top = top->outer_scope();
288  }
289 
290  // Allocate the variables.
291  {
292  AstNodeFactory<AstNullVisitor> ast_node_factory(info->zone());
293  if (!top->AllocateVariables(info, &ast_node_factory)) return false;
294  }
295 
296 #ifdef DEBUG
297  if (info->isolate()->bootstrapper()->IsActive()
298  ? FLAG_print_builtin_scopes
299  : FLAG_print_scopes) {
300  scope->Print();
301  }
302 
303  if (FLAG_harmony_modules && FLAG_print_interfaces && top->is_global_scope()) {
304  PrintF("global : ");
305  top->interface()->Print();
306  }
307 #endif
308 
309  info->PrepareForCompilation(scope);
310  return true;
311 }
312 
313 
316 
317  // Add this scope as a new inner scope of the outer scope.
318  if (outer_scope_ != NULL) {
319  outer_scope_->inner_scopes_.Add(this, zone());
321  } else {
323  }
324 
325  // Declare convenience variables.
326  // Declare and allocate receiver (even for the global scope, and even
327  // if naccesses_ == 0).
328  // NOTE: When loading parameters in the global scope, we must take
329  // care not to access them as properties of the global object, but
330  // instead load them directly from the stack. Currently, the only
331  // such parameter is 'this' which is passed on the stack when
332  // invoking scripts
333  if (is_declaration_scope()) {
334  Variable* var =
335  variables_.Declare(this,
336  isolate_->factory()->this_string(),
337  VAR,
338  false,
342  receiver_ = var;
343  } else {
344  ASSERT(outer_scope() != NULL);
346  }
347 
348  if (is_function_scope()) {
349  // Declare 'arguments' variable which exists in all functions.
350  // Note that it might never be accessed, in which case it won't be
351  // allocated during variable allocation.
352  variables_.Declare(this,
353  isolate_->factory()->arguments_string(),
354  VAR,
355  true,
358  }
359 }
360 
361 
364  ASSERT(internals_.is_empty());
365  ASSERT(temps_.is_empty());
366  ASSERT(params_.is_empty());
367 
368  if (num_var_or_const() > 0) return this;
369 
370  // Remove this scope from outer scope.
371  for (int i = 0; i < outer_scope_->inner_scopes_.length(); i++) {
372  if (outer_scope_->inner_scopes_[i] == this) {
373  outer_scope_->inner_scopes_.Remove(i);
374  break;
375  }
376  }
377 
378  // Reparent inner scopes.
379  for (int i = 0; i < inner_scopes_.length(); i++) {
380  outer_scope()->AddInnerScope(inner_scopes_[i]);
381  }
382 
383  // Move unresolved variables
384  for (int i = 0; i < unresolved_.length(); i++) {
386  }
387 
388  return NULL;
389 }
390 
391 
393  Variable* result = variables_.Lookup(name);
394  if (result != NULL || scope_info_.is_null()) {
395  return result;
396  }
397  // If we have a serialized scope info, we might find the variable there.
398  // There should be no local slot with the given name.
399  ASSERT(scope_info_->StackSlotIndex(*name) < 0);
400 
401  // Check context slot lookup.
404  InitializationFlag init_flag;
405  int index = scope_info_->ContextSlotIndex(*name, &mode, &init_flag);
406  if (index < 0) {
407  // Check parameters.
408  index = scope_info_->ParameterIndex(*name);
409  if (index < 0) return NULL;
410 
411  mode = DYNAMIC;
412  location = Variable::LOOKUP;
413  init_flag = kCreatedInitialized;
414  }
415 
416  Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL,
417  init_flag);
418  var->AllocateTo(location, index);
419  return var;
420 }
421 
422 
425  if (function_ != NULL && function_->proxy()->name().is_identical_to(name)) {
426  return function_->proxy()->var();
427  } else if (!scope_info_.is_null()) {
428  // If we are backed by a scope info, try to lookup the variable there.
430  int index = scope_info_->FunctionContextSlotIndex(*name, &mode);
431  if (index < 0) return NULL;
432  Variable* var = new(zone()) Variable(
433  this, name, mode, true /* is valid LHS */,
435  VariableProxy* proxy = factory->NewVariableProxy(var);
436  VariableDeclaration* declaration = factory->NewVariableDeclaration(
437  proxy, mode, this, RelocInfo::kNoPosition);
438  DeclareFunctionVar(declaration);
439  var->AllocateTo(Variable::CONTEXT, index);
440  return var;
441  } else {
442  return NULL;
443  }
444 }
445 
446 
448  for (Scope* scope = this;
449  scope != NULL;
450  scope = scope->outer_scope()) {
451  Variable* var = scope->LocalLookup(name);
452  if (var != NULL) return var;
453  }
454  return NULL;
455 }
456 
457 
461  Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL,
463  params_.Add(var, zone());
464 }
465 
466 
469  InitializationFlag init_flag,
470  Interface* interface) {
472  // This function handles VAR, LET, and CONST modes. DYNAMIC variables are
473  // introduces during variable allocation, INTERNAL variables are allocated
474  // explicitly, and TEMPORARY variables are allocated via NewTemporary().
477  return variables_.Declare(
478  this, name, mode, true, Variable::NORMAL, init_flag, interface);
479 }
480 
481 
484  return variables_.Declare(this,
485  name,
487  true,
490 }
491 
492 
493 void Scope::RemoveUnresolved(VariableProxy* var) {
494  // Most likely (always?) any variable we want to remove
495  // was just added before, so we search backwards.
496  for (int i = unresolved_.length(); i-- > 0;) {
497  if (unresolved_[i] == var) {
498  unresolved_.Remove(i);
499  return;
500  }
501  }
502 }
503 
504 
507  Variable* var = new(zone()) Variable(this,
508  name,
509  INTERNAL,
510  false,
513  internals_.Add(var, zone());
514  return var;
515 }
516 
517 
520  Variable* var = new(zone()) Variable(this,
521  name,
522  TEMPORARY,
523  true,
526  temps_.Add(var, zone());
527  return var;
528 }
529 
530 
531 void Scope::AddDeclaration(Declaration* declaration) {
532  decls_.Add(declaration, zone());
533 }
534 
535 
537  // Record only the first illegal redeclaration.
538  if (!HasIllegalRedeclaration()) {
539  illegal_redecl_ = expression;
540  }
542 }
543 
544 
545 void Scope::VisitIllegalRedeclaration(AstVisitor* visitor) {
547  illegal_redecl_->Accept(visitor);
548 }
549 
550 
552  int length = decls_.length();
553  for (int i = 0; i < length; i++) {
554  Declaration* decl = decls_[i];
555  if (decl->mode() != VAR) continue;
556  Handle<String> name = decl->proxy()->name();
557 
558  // Iterate through all scopes until and including the declaration scope.
559  Scope* previous = NULL;
560  Scope* current = decl->scope();
561  do {
562  // There is a conflict if there exists a non-VAR binding.
563  Variable* other_var = current->variables_.Lookup(name);
564  if (other_var != NULL && other_var->mode() != VAR) {
565  return decl;
566  }
567  previous = current;
568  current = current->outer_scope_;
569  } while (!previous->is_declaration_scope());
570  }
571  return NULL;
572 }
573 
574 
575 class VarAndOrder {
576  public:
577  VarAndOrder(Variable* var, int order) : var_(var), order_(order) { }
578  Variable* var() const { return var_; }
579  int order() const { return order_; }
580  static int Compare(const VarAndOrder* a, const VarAndOrder* b) {
581  return a->order_ - b->order_;
582  }
583 
584  private:
585  Variable* var_;
586  int order_;
587 };
588 
589 
591  ZoneList<Variable*>* context_locals) {
592  ASSERT(stack_locals != NULL);
593  ASSERT(context_locals != NULL);
594 
595  // Collect internals which are always allocated on the heap.
596  for (int i = 0; i < internals_.length(); i++) {
597  Variable* var = internals_[i];
598  if (var->is_used()) {
599  ASSERT(var->IsContextSlot());
600  context_locals->Add(var, zone());
601  }
602  }
603 
604  // Collect temporaries which are always allocated on the stack, unless the
605  // context as a whole has forced context allocation.
606  for (int i = 0; i < temps_.length(); i++) {
607  Variable* var = temps_[i];
608  if (var->is_used()) {
609  if (var->IsContextSlot()) {
611  context_locals->Add(var, zone());
612  } else {
613  ASSERT(var->IsStackLocal());
614  stack_locals->Add(var, zone());
615  }
616  }
617  }
618 
619  // Collect declared local variables.
621  for (VariableMap::Entry* p = variables_.Start();
622  p != NULL;
623  p = variables_.Next(p)) {
624  Variable* var = reinterpret_cast<Variable*>(p->value);
625  if (var->is_used()) {
626  vars.Add(VarAndOrder(var, p->order), zone());
627  }
628  }
629  vars.Sort(VarAndOrder::Compare);
630  int var_count = vars.length();
631  for (int i = 0; i < var_count; i++) {
632  Variable* var = vars[i].var();
633  if (var->IsStackLocal()) {
634  stack_locals->Add(var, zone());
635  } else if (var->IsContextSlot()) {
636  context_locals->Add(var, zone());
637  }
638  }
639 }
640 
641 
644  // 1) Propagate scope information.
645  bool outer_scope_calls_sloppy_eval = false;
646  if (outer_scope_ != NULL) {
647  outer_scope_calls_sloppy_eval =
650  }
651  PropagateScopeInfo(outer_scope_calls_sloppy_eval);
652 
653  // 2) Allocate module instances.
654  if (FLAG_harmony_modules && (is_global_scope() || is_module_scope())) {
655  ASSERT(num_modules_ == 0);
657  }
658 
659  // 3) Resolve variables.
660  if (!ResolveVariablesRecursively(info, factory)) return false;
661 
662  // 4) Allocate variables.
664 
665  return true;
666 }
667 
668 
670  // A function scope has a trivial context if it always is the global
671  // context. We iteratively scan out the context chain to see if
672  // there is anything that makes this scope non-trivial; otherwise we
673  // return true.
674  for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) {
675  if (scope->is_eval_scope()) return false;
676  if (scope->scope_inside_with_) return false;
677  if (scope->num_heap_slots_ > 0) return false;
678  }
679  return true;
680 }
681 
682 
684  Scope* outer = outer_scope_;
685  if (outer == NULL) return true;
686  // Note that the outer context may be trivial in general, but the current
687  // scope may be inside a 'with' statement in which case the outer context
688  // for this scope is not trivial.
689  return !scope_inside_with_ && outer->HasTrivialContext();
690 }
691 
692 
694  Scope* outer = outer_scope_;
695  if (outer == NULL) return true;
696  // We have to prevent lazy compilation if this scope is inside a with scope
697  // and all declaration scopes between them have empty contexts. Such
698  // declaration scopes may become invisible during scope info deserialization.
699  outer = outer->DeclarationScope();
700  bool found_non_trivial_declarations = false;
701  for (const Scope* scope = outer; scope != NULL; scope = scope->outer_scope_) {
702  if (scope->is_with_scope() && !found_non_trivial_declarations) return false;
703  if (scope->is_declaration_scope() && scope->num_heap_slots() > 0) {
704  found_non_trivial_declarations = true;
705  }
706  }
707  return true;
708 }
709 
710 
713 }
714 
715 
718 }
719 
720 
722  int n = 0;
723  for (Scope* s = this; s != scope; s = s->outer_scope_) {
724  ASSERT(s != NULL); // scope must be in the scope chain
725  if (s->is_with_scope() || s->num_heap_slots() > 0) n++;
726  // Catch and module scopes always have heap slots.
727  ASSERT(!s->is_catch_scope() || s->num_heap_slots() > 0);
728  ASSERT(!s->is_module_scope() || s->num_heap_slots() > 0);
729  }
730  return n;
731 }
732 
733 
735  Scope* scope = this;
736  while (!scope->is_global_scope()) {
737  scope = scope->outer_scope();
738  }
739  return scope;
740 }
741 
742 
744  Scope* scope = this;
745  while (!scope->is_declaration_scope()) {
746  scope = scope->outer_scope();
747  }
748  return scope;
749 }
750 
751 
753  if (scope_info_.is_null()) {
754  scope_info_ = ScopeInfo::Create(this, zone());
755  }
756  return scope_info_;
757 }
758 
759 
761  List<Handle<ScopeInfo> >* chain,
762  int position) {
763  if (!is_eval_scope()) chain->Add(Handle<ScopeInfo>(GetScopeInfo()));
764 
765  for (int i = 0; i < inner_scopes_.length(); i++) {
766  Scope* scope = inner_scopes_[i];
767  int beg_pos = scope->start_position();
768  int end_pos = scope->end_position();
769  ASSERT(beg_pos >= 0 && end_pos >= 0);
770  if (beg_pos <= position && position < end_pos) {
771  scope->GetNestedScopeChain(chain, position);
772  return;
773  }
774  }
775 }
776 
777 
778 #ifdef DEBUG
779 static const char* Header(ScopeType scope_type) {
780  switch (scope_type) {
781  case EVAL_SCOPE: return "eval";
782  case FUNCTION_SCOPE: return "function";
783  case MODULE_SCOPE: return "module";
784  case GLOBAL_SCOPE: return "global";
785  case CATCH_SCOPE: return "catch";
786  case BLOCK_SCOPE: return "block";
787  case WITH_SCOPE: return "with";
788  }
789  UNREACHABLE();
790  return NULL;
791 }
792 
793 
794 static void Indent(int n, const char* str) {
795  PrintF("%*s%s", n, "", str);
796 }
797 
798 
799 static void PrintName(Handle<String> name) {
800  SmartArrayPointer<char> s = name->ToCString(DISALLOW_NULLS);
801  PrintF("%s", s.get());
802 }
803 
804 
805 static void PrintLocation(Variable* var) {
806  switch (var->location()) {
808  break;
809  case Variable::PARAMETER:
810  PrintF("parameter[%d]", var->index());
811  break;
812  case Variable::LOCAL:
813  PrintF("local[%d]", var->index());
814  break;
815  case Variable::CONTEXT:
816  PrintF("context[%d]", var->index());
817  break;
818  case Variable::LOOKUP:
819  PrintF("lookup");
820  break;
821  }
822 }
823 
824 
825 static void PrintVar(int indent, Variable* var) {
826  if (var->is_used() || !var->IsUnallocated()) {
827  Indent(indent, Variable::Mode2String(var->mode()));
828  PrintF(" ");
829  PrintName(var->name());
830  PrintF("; // ");
831  PrintLocation(var);
832  if (var->has_forced_context_allocation()) {
833  if (!var->IsUnallocated()) PrintF(", ");
834  PrintF("forced context allocation");
835  }
836  PrintF("\n");
837  }
838 }
839 
840 
841 static void PrintMap(int indent, VariableMap* map) {
842  for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) {
843  Variable* var = reinterpret_cast<Variable*>(p->value);
844  PrintVar(indent, var);
845  }
846 }
847 
848 
849 void Scope::Print(int n) {
850  int n0 = (n > 0 ? n : 0);
851  int n1 = n0 + 2; // indentation
852 
853  // Print header.
854  Indent(n0, Header(scope_type_));
855  if (scope_name_->length() > 0) {
856  PrintF(" ");
857  PrintName(scope_name_);
858  }
859 
860  // Print parameters, if any.
861  if (is_function_scope()) {
862  PrintF(" (");
863  for (int i = 0; i < params_.length(); i++) {
864  if (i > 0) PrintF(", ");
865  PrintName(params_[i]->name());
866  }
867  PrintF(")");
868  }
869 
870  PrintF(" { // (%d, %d)\n", start_position(), end_position());
871 
872  // Function name, if any (named function literals, only).
873  if (function_ != NULL) {
874  Indent(n1, "// (local) function name: ");
875  PrintName(function_->proxy()->name());
876  PrintF("\n");
877  }
878 
879  // Scope info.
880  if (HasTrivialOuterContext()) {
881  Indent(n1, "// scope has trivial outer context\n");
882  }
883  if (strict_mode() == STRICT) {
884  Indent(n1, "// strict mode scope\n");
885  }
886  if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
887  if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");
888  if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
890  Indent(n1, "// outer scope calls 'eval' in sloppy context\n");
891  }
892  if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
893  if (num_stack_slots_ > 0) { Indent(n1, "// ");
894  PrintF("%d stack slots\n", num_stack_slots_); }
895  if (num_heap_slots_ > 0) { Indent(n1, "// ");
896  PrintF("%d heap slots\n", num_heap_slots_); }
897 
898  // Print locals.
899  if (function_ != NULL) {
900  Indent(n1, "// function var:\n");
901  PrintVar(n1, function_->proxy()->var());
902  }
903 
904  if (temps_.length() > 0) {
905  Indent(n1, "// temporary vars:\n");
906  for (int i = 0; i < temps_.length(); i++) {
907  PrintVar(n1, temps_[i]);
908  }
909  }
910 
911  if (internals_.length() > 0) {
912  Indent(n1, "// internal vars:\n");
913  for (int i = 0; i < internals_.length(); i++) {
914  PrintVar(n1, internals_[i]);
915  }
916  }
917 
918  if (variables_.Start() != NULL) {
919  Indent(n1, "// local vars:\n");
920  PrintMap(n1, &variables_);
921  }
922 
923  if (dynamics_ != NULL) {
924  Indent(n1, "// dynamic vars:\n");
928  }
929 
930  // Print inner scopes (disable by providing negative n).
931  if (n >= 0) {
932  for (int i = 0; i < inner_scopes_.length(); i++) {
933  PrintF("\n");
934  inner_scopes_[i]->Print(n1);
935  }
936  }
937 
938  Indent(n0, "}\n");
939 }
940 #endif // DEBUG
941 
942 
944  if (dynamics_ == NULL) dynamics_ = new(zone()) DynamicScopePart(zone());
945  VariableMap* map = dynamics_->GetMap(mode);
946  Variable* var = map->Lookup(name);
947  if (var == NULL) {
948  // Declare a new non-local.
949  InitializationFlag init_flag = (mode == VAR)
951  var = map->Declare(NULL,
952  name,
953  mode,
954  true,
956  init_flag);
957  // Allocate it by giving it a dynamic lookup.
958  var->AllocateTo(Variable::LOOKUP, -1);
959  }
960  return var;
961 }
962 
963 
965  BindingKind* binding_kind,
967  ASSERT(binding_kind != NULL);
968  if (already_resolved() && is_with_scope()) {
969  // Short-cut: if the scope is deserialized from a scope info, variable
970  // allocation is already fixed. We can simply return with dynamic lookup.
971  *binding_kind = DYNAMIC_LOOKUP;
972  return NULL;
973  }
974 
975  // Try to find the variable in this scope.
976  Variable* var = LocalLookup(name);
977 
978  // We found a variable and we are done. (Even if there is an 'eval' in
979  // this scope which introduces the same variable again, the resulting
980  // variable remains the same.)
981  if (var != NULL) {
982  *binding_kind = BOUND;
983  return var;
984  }
985 
986  // We did not find a variable locally. Check against the function variable,
987  // if any. We can do this for all scopes, since the function variable is
988  // only present - if at all - for function scopes.
989  *binding_kind = UNBOUND;
990  var = LookupFunctionVar(name, factory);
991  if (var != NULL) {
992  *binding_kind = BOUND;
993  } else if (outer_scope_ != NULL) {
994  var = outer_scope_->LookupRecursive(name, binding_kind, factory);
995  if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) {
996  var->ForceContextAllocation();
997  }
998  } else {
1000  }
1001 
1002  if (is_with_scope()) {
1004  // The current scope is a with scope, so the variable binding can not be
1005  // statically resolved. However, note that it was necessary to do a lookup
1006  // in the outer scope anyway, because if a binding exists in an outer scope,
1007  // the associated variable has to be marked as potentially being accessed
1008  // from inside of an inner with scope (the property may not be in the 'with'
1009  // object).
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  ASSERT(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->name(), &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->name(), DYNAMIC_GLOBAL);
1051  } else if (var->is_dynamic()) {
1052  var = NonLocal(proxy->name(), DYNAMIC);
1053  } else {
1054  Variable* invalidated = var;
1055  var = NonLocal(proxy->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->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->name(), DYNAMIC_GLOBAL);
1068  break;
1069 
1070  case DYNAMIC_LOOKUP:
1071  // The variable could not be resolved statically.
1072  var = NonLocal(proxy->name(), DYNAMIC);
1073  break;
1074  }
1075 
1076  ASSERT(var != NULL);
1077 
1078  if (FLAG_harmony_scoping && strict_mode() == STRICT &&
1079  var->is_const_mode() && proxy->IsLValue()) {
1080  // Assignment to const. Throw a syntax error.
1081  MessageLocation location(
1082  info->script(), proxy->position(), proxy->position());
1083  Isolate* isolate = info->isolate();
1084  Factory* factory = isolate->factory();
1085  Handle<JSArray> array = factory->NewJSArray(0);
1086  Handle<Object> result =
1087  factory->NewSyntaxError("harmony_const_assign", array);
1088  isolate->Throw(*result, &location);
1089  return false;
1090  }
1091 
1092  if (FLAG_harmony_modules) {
1093  bool ok;
1094 #ifdef DEBUG
1095  if (FLAG_print_interface_details)
1096  PrintF("# Resolve %s:\n", var->name()->ToAsciiArray());
1097 #endif
1098  proxy->interface()->Unify(var->interface(), zone(), &ok);
1099  if (!ok) {
1100 #ifdef DEBUG
1101  if (FLAG_print_interfaces) {
1102  PrintF("SCOPES TYPE ERROR\n");
1103  PrintF("proxy: ");
1104  proxy->interface()->Print();
1105  PrintF("var: ");
1106  var->interface()->Print();
1107  }
1108 #endif
1109 
1110  // Inconsistent use of module. Throw a syntax error.
1111  // TODO(rossberg): generate more helpful error message.
1112  MessageLocation location(
1113  info->script(), proxy->position(), proxy->position());
1114  Isolate* isolate = info->isolate();
1115  Factory* factory = isolate->factory();
1116  Handle<JSArray> array = factory->NewJSArray(1);
1117  USE(JSObject::SetElement(array, 0, var->name(), NONE, STRICT));
1118  Handle<Object> result =
1119  factory->NewSyntaxError("module_type_error", array);
1120  isolate->Throw(*result, &location);
1121  return false;
1122  }
1123  }
1124 
1125  proxy->BindTo(var);
1126 
1127  return true;
1128 }
1129 
1130 
1133  AstNodeFactory<AstNullVisitor>* factory) {
1134  ASSERT(info->global_scope()->is_global_scope());
1135 
1136  // Resolve unresolved variables for this scope.
1137  for (int i = 0; i < unresolved_.length(); i++) {
1138  if (!ResolveVariable(info, unresolved_[i], factory)) return false;
1139  }
1140 
1141  // Resolve unresolved variables for inner scopes.
1142  for (int i = 0; i < inner_scopes_.length(); i++) {
1143  if (!inner_scopes_[i]->ResolveVariablesRecursively(info, factory))
1144  return false;
1145  }
1146 
1147  return true;
1148 }
1149 
1150 
1151 bool Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) {
1152  if (outer_scope_calls_sloppy_eval) {
1154  }
1155 
1156  bool calls_sloppy_eval =
1158  for (int i = 0; i < inner_scopes_.length(); i++) {
1159  Scope* inner_scope = inner_scopes_[i];
1160  if (inner_scope->PropagateScopeInfo(calls_sloppy_eval)) {
1161  inner_scope_calls_eval_ = true;
1162  }
1163  if (inner_scope->force_eager_compilation_) {
1164  force_eager_compilation_ = true;
1165  }
1166  }
1167 
1169 }
1170 
1171 
1173  // Give var a read/write use if there is a chance it might be accessed
1174  // via an eval() call. This is only possible if the variable has a
1175  // visible name.
1176  if ((var->is_this() || var->name()->length() > 0) &&
1181  is_catch_scope() ||
1182  is_block_scope() ||
1183  is_module_scope() ||
1184  is_global_scope())) {
1185  var->set_is_used(true);
1186  }
1187  // Global variables do not need to be allocated.
1188  return !var->IsGlobalObjectProperty() && var->is_used();
1189 }
1190 
1191 
1193  // If var is accessed from an inner scope, or if there is a possibility
1194  // that it might be accessed from the current or an inner scope (through
1195  // an eval() call or a runtime with lookup), it must be allocated in the
1196  // context.
1197  //
1198  // Exceptions: If the scope as a whole has forced context allocation, all
1199  // variables will have context allocation, even temporaries. Otherwise
1200  // temporary variables are always stack-allocated. Catch-bound variables are
1201  // always context-allocated.
1202  if (has_forced_context_allocation()) return true;
1203  if (var->mode() == TEMPORARY) return false;
1204  if (var->mode() == INTERNAL) return true;
1205  if (is_catch_scope() || is_block_scope() || is_module_scope()) return true;
1206  if (is_global_scope() && IsLexicalVariableMode(var->mode())) return true;
1207  return var->has_forced_context_allocation() ||
1211 }
1212 
1213 
1215  for (int i = 0; i < params_.length(); i++) {
1216  if (params_[i]->name().is_identical_to(
1217  isolate_->factory()->arguments_string())) {
1218  return true;
1219  }
1220  }
1221  return false;
1222 }
1223 
1224 
1227 }
1228 
1229 
1232 }
1233 
1234 
1237  Variable* arguments = LocalLookup(isolate_->factory()->arguments_string());
1238  ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly
1239 
1240  bool uses_sloppy_arguments = false;
1241 
1242  if (MustAllocate(arguments) && !HasArgumentsParameter()) {
1243  // 'arguments' is used. Unless there is also a parameter called
1244  // 'arguments', we must be conservative and allocate all parameters to
1245  // the context assuming they will be captured by the arguments object.
1246  // If we have a parameter named 'arguments', a (new) value is always
1247  // assigned to it via the function invocation. Then 'arguments' denotes
1248  // that specific parameter value and cannot be used to access the
1249  // parameters, which is why we don't need to allocate an arguments
1250  // object in that case.
1251 
1252  // We are using 'arguments'. Tell the code generator that is needs to
1253  // allocate the arguments object by setting 'arguments_'.
1255 
1256  // In strict mode 'arguments' does not alias formal parameters.
1257  // Therefore in strict mode we allocate parameters as if 'arguments'
1258  // were not used.
1259  uses_sloppy_arguments = strict_mode() == SLOPPY;
1260  }
1261 
1262  // The same parameter may occur multiple times in the parameters_ list.
1263  // If it does, and if it is not copied into the context object, it must
1264  // receive the highest parameter index for that parameter; thus iteration
1265  // order is relevant!
1266  for (int i = params_.length() - 1; i >= 0; --i) {
1267  Variable* var = params_[i];
1268  ASSERT(var->scope() == this);
1269  if (uses_sloppy_arguments) {
1270  // Force context allocation of the parameter.
1271  var->ForceContextAllocation();
1272  }
1273 
1274  if (MustAllocate(var)) {
1275  if (MustAllocateInContext(var)) {
1276  ASSERT(var->IsUnallocated() || var->IsContextSlot());
1277  if (var->IsUnallocated()) {
1278  AllocateHeapSlot(var);
1279  }
1280  } else {
1281  ASSERT(var->IsUnallocated() || var->IsParameter());
1282  if (var->IsUnallocated()) {
1284  }
1285  }
1286  }
1287  }
1288 }
1289 
1290 
1292  ASSERT(var->scope() == this);
1293  ASSERT(!var->IsVariable(isolate_->factory()->dot_result_string()) ||
1294  !var->IsStackLocal());
1295  if (var->IsUnallocated() && MustAllocate(var)) {
1296  if (MustAllocateInContext(var)) {
1297  AllocateHeapSlot(var);
1298  } else {
1299  AllocateStackSlot(var);
1300  }
1301  }
1302 }
1303 
1304 
1306  // All variables that have no rewrite yet are non-parameter locals.
1307  for (int i = 0; i < temps_.length(); i++) {
1309  }
1310 
1311  for (int i = 0; i < internals_.length(); i++) {
1313  }
1314 
1316  for (VariableMap::Entry* p = variables_.Start();
1317  p != NULL;
1318  p = variables_.Next(p)) {
1319  Variable* var = reinterpret_cast<Variable*>(p->value);
1320  vars.Add(VarAndOrder(var, p->order), zone());
1321  }
1322  vars.Sort(VarAndOrder::Compare);
1323  int var_count = vars.length();
1324  for (int i = 0; i < var_count; i++) {
1325  AllocateNonParameterLocal(vars[i].var());
1326  }
1327 
1328  // For now, function_ must be allocated at the very end. If it gets
1329  // allocated in the context, it must be the last slot in the context,
1330  // because of the current ScopeInfo implementation (see
1331  // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
1332  if (function_ != NULL) {
1333  AllocateNonParameterLocal(function_->proxy()->var());
1334  }
1335 }
1336 
1337 
1339  // Allocate variables for inner scopes.
1340  for (int i = 0; i < inner_scopes_.length(); i++) {
1341  inner_scopes_[i]->AllocateVariablesRecursively();
1342  }
1343 
1344  // If scope is already resolved, we still need to allocate
1345  // variables in inner scopes which might not had been resolved yet.
1346  if (already_resolved()) return;
1347  // The number of slots required for variables.
1348  num_stack_slots_ = 0;
1350 
1351  // Allocate variables for this scope.
1352  // Parameters must be allocated first, if any.
1355 
1356  // Force allocation of a context for this scope if necessary. For a 'with'
1357  // scope and for a function scope that makes an 'eval' call we need a context,
1358  // even if no local variables were statically allocated in the scope.
1359  // Likewise for modules.
1360  bool must_have_context = is_with_scope() || is_module_scope() ||
1361  (is_function_scope() && calls_eval());
1362 
1363  // If we didn't allocate any locals in the local context, then we only
1364  // need the minimal number of slots if we must have a context.
1365  if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) {
1366  num_heap_slots_ = 0;
1367  }
1368 
1369  // Allocation done.
1371 }
1372 
1373 
1375  if (already_resolved()) return;
1376  if (is_module_scope()) {
1379  STATIC_ASCII_VECTOR(".module"));
1380  ASSERT(module_var_ == NULL);
1381  module_var_ = host_scope->NewInternal(name);
1382  ++host_scope->num_modules_;
1383  }
1384 
1385  for (int i = 0; i < inner_scopes_.length(); i++) {
1386  Scope* inner_scope = inner_scopes_.at(i);
1387  inner_scope->AllocateModulesRecursively(host_scope);
1388  }
1389 }
1390 
1391 
1393  return num_stack_slots() -
1394  (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0);
1395 }
1396 
1397 
1399  if (num_heap_slots() == 0) return 0;
1401  (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0);
1402 }
1403 
1404 } } // namespace v8::internal
bool PropagateScopeInfo(bool outer_scope_calls_sloppy_eval)
Definition: scopes.cc:1151
bool is_global_scope() const
Definition: scopes.h:286
void AllocateTo(Location location, int index)
Definition: variables.h:153
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
static Handle< 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:12410
Scope * DeclarationScope()
Definition: scopes.cc:743
bool scope_contains_with_
Definition: scopes.h:484
Declaration * CheckConflictingVarDeclarations()
Definition: scopes.cc:551
bool scope_calls_eval_
Definition: scopes.h:487
virtual ~VariableMap()
Definition: scopes.cc:62
bool calls_eval() const
Definition: scopes.h:299
void PrepareForCompilation(Scope *scope)
Definition: compiler.cc:249
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths true
Definition: flags.cc:208
JSModule * module()
Definition: contexts.h:381
void PrintF(const char *format,...)
Definition: v8utils.cc:40
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf map
Definition: flags.cc:350
bool outer_scope_calls_sloppy_eval_
Definition: scopes.h:495
void ForceContextAllocation()
Definition: variables.h:101
static String * cast(Object *obj)
Context * previous()
Definition: contexts.h:370
Handle< ScopeInfo > GetScopeInfo()
Definition: scopes.cc:752
ZoneList< Scope * > inner_scopes_
Definition: scopes.h:441
Variable * receiver()
Definition: scopes.h:322
bool already_resolved()
Definition: scopes.h:519
bool force_eager_compilation_
Definition: scopes.h:497
VarAndOrder(Variable *var, int order)
Definition: scopes.cc:577
void CollectStackAndContextLocals(ZoneList< Variable * > *stack_locals, ZoneList< Variable * > *context_locals)
Definition: scopes.cc:590
Scope * FinalizeBlockScope()
Definition: scopes.cc:362
Handle< Script > script() const
Definition: compiler.h:83
Variable * arguments_
Definition: scopes.h:472
static bool Analyze(CompilationInfo *info)
Definition: scopes.cc:278
Scope * outer_scope() const
Definition: scopes.h:350
bool HasIllegalRedeclaration() const
Definition: scopes.h:220
ZoneList< VariableProxy * > unresolved_
Definition: scopes.h:464
Expression * illegal_redecl_
Definition: scopes.h:477
void set_local_if_not_shadowed(Variable *local)
Definition: variables.h:142
Scope(Scope *outer_scope, ScopeType scope_type, Zone *zone)
Definition: scopes.cc:105
Bootstrapper * bootstrapper()
Definition: isolate.h:858
Handle< String > scope_name_
Definition: scopes.h:447
Zone * zone() const
Definition: scopes.h:57
void DeclareParameter(Handle< String > name, VariableMode mode)
Definition: scopes.cc:458
Isolate * isolate() const
Definition: compiler.h:67
bool HasTrivialContext() const
Definition: scopes.cc:669
#define ASSERT(condition)
Definition: checks.h:329
Variable * NewTemporary(Handle< String > name)
Definition: scopes.cc:518
bool is_const_mode() const
Definition: variables.h:124
Interface * interface() const
Definition: variables.h:151
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV 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 expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage including on console Map counters to a file Enable debugger compile events enable GDBJIT interface(disables compacting GC)") DEFINE_bool(gdbjit_full
bool is_this() const
Definition: variables.h:129
VariableMap * GetMap(VariableMode mode)
Definition: scopes.h:75
VariableDeclaration * function_
Definition: scopes.h:470
bool has_forced_context_allocation() const
Definition: scopes.h:275
Variable * LookupRecursive(Handle< String > name, BindingKind *binding_kind, AstNodeFactory< AstNullVisitor > *factory)
Definition: scopes.cc:964
Variable * var() const
Definition: scopes.cc:578
Factory * factory()
Definition: isolate.h:995
StrictMode strict_mode() const
Definition: scopes.h:319
bool is_block_scope() const
Definition: scopes.h:288
Handle< String > name() const
Definition: variables.h:96
static Handle< ScopeInfo > Create(Scope *scope, Zone *zone)
Definition: scopeinfo.cc:39
bool MustAllocateInContext(Variable *var)
Definition: scopes.cc:1192
ZoneList< Declaration * > decls_
Definition: scopes.h:466
Handle< ScopeInfo > scope_info_
Definition: scopes.h:518
int ContextChainLength(Scope *scope)
Definition: scopes.cc:721
static ScopeInfo * cast(Object *object)
bool HasTrivialOuterContext() const
Definition: scopes.cc:683
bool is_dynamic() const
Definition: variables.h:123
bool AllowsLazyCompilation() const
Definition: scopes.cc:711
void DeclareFunctionVar(VariableDeclaration *declaration)
Definition: scopes.h:142
void AllocateNonParameterLocal(Variable *var)
Definition: scopes.cc:1291
static int Compare(const VarAndOrder *a, const VarAndOrder *b)
Definition: scopes.cc:580
int start_position() const
Definition: scopes.h:261
Variable * DeclareLocal(Handle< String > name, VariableMode mode, InitializationFlag init_flag, Interface *interface=Interface::NewValue())
Definition: scopes.cc:467
#define UNREACHABLE()
Definition: checks.h:52
VariableProxy * proxy() const
Definition: ast.h:486
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV 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_string(expose_natives_as
void AllocateVariablesRecursively()
Definition: scopes.cc:1338
VariableMode mode() const
Definition: variables.h:97
bool is_eval_scope() const
Definition: scopes.h:283
bool HasArgumentsParameter()
Definition: scopes.cc:1214
Variable * arguments() const
Definition: scopes.h:341
int num_stack_slots() const
Definition: scopes.h:368
Isolate *const isolate_
Definition: scopes.h:437
bool has_forced_context_allocation() const
Definition: variables.h:98
void GetNestedScopeChain(List< Handle< ScopeInfo > > *chain, int statement_position)
Definition: scopes.cc:760
void AllocateHeapSlot(Variable *var)
Definition: scopes.cc:1230
bool force_context_allocation_
Definition: scopes.h:498
ScopeType scope_type() const
Definition: scopes.h:316
uint32_t occupancy() const
Definition: hashmap.h:83
Scope * scope() const
Definition: variables.h:94
FunctionLiteral * function() const
Definition: compiler.h:77
void PrintMap(map< string, string > *m)
Definition: process.cc:637
T Remove(int i)
Definition: list-inl.h:125
bool is_declaration_scope() const
Definition: scopes.h:290
ZoneList< Variable * > internals_
Definition: scopes.h:456
bool HasLazyCompilableOuterContext() const
Definition: scopes.cc:693
bool inner_scope_calls_eval_
Definition: scopes.h:496
Interface * interface_
Definition: scopes.h:474
Entry * Lookup(void *key, uint32_t hash, bool insert, ZoneAllocationPolicyallocator=ZoneAllocationPolicy())
void AllocateStackSlot(Variable *var)
Definition: scopes.cc:1225
bool IsLexicalVariableMode(VariableMode mode)
Definition: v8globals.h:508
Variable * receiver_
Definition: scopes.h:468
Scope * global_scope() const
Definition: compiler.h:79
bool IsContextSlot() const
Definition: variables.h:119
static const char * Mode2String(VariableMode mode)
Definition: variables.cc:40
bool MustAllocate(Variable *var)
Definition: scopes.cc:1172
Variable * LocalLookup(Handle< String > name)
Definition: scopes.cc:392
bool IsVariable(Handle< String > n) const
Definition: variables.h:111
int end_position() const
Definition: scopes.h:265
#define STATIC_ASCII_VECTOR(x)
Definition: utils.h:570
bool IsDeclaredVariableMode(VariableMode mode)
Definition: v8globals.h:503
bool IsStackLocal() const
Definition: variables.h:117
ZoneList< Variable * > params_
Definition: scopes.h:460
Variable * NewInternal(Handle< String > name)
Definition: scopes.cc:505
Interface * interface() const
Definition: scopes.h:353
Scope * GlobalScope()
Definition: scopes.cc:734
void AllocateParameterLocals()
Definition: scopes.cc:1235
int StackLocalCount() const
Definition: scopes.cc:1392
VariableMap variables_
Definition: scopes.h:454
Handle< Object > NewSyntaxError(const char *message, Handle< JSArray > args)
Definition: factory.cc:1061
void AddDeclaration(Declaration *declaration)
Definition: scopes.cc:531
bool calls_sloppy_eval()
Definition: scopes.h:300
int num_heap_slots() const
Definition: scopes.h:369
StrictMode strict_mode_
Definition: scopes.h:489
ScopeType scope_type_
Definition: scopes.h:444
void VisitIllegalRedeclaration(AstVisitor *visitor)
Definition: scopes.cc:545
Handle< String > InternalizeOneByteString(Vector< const uint8_t > str)
Definition: factory.cc:232
Scope * scope() const
Definition: ast.h:488
bool is_null() const
Definition: handles.h:81
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
Definition: flags.cc:317
int order() const
Definition: scopes.cc:579
bool IsParameter() const
Definition: variables.h:116
bool is_with_scope() const
Definition: scopes.h:289
void AllocateNonParameterLocals()
Definition: scopes.cc:1305
ZoneList< Variable * > temps_
Definition: scopes.h:458
int num_var_or_const()
Definition: scopes.h:365
bool contains_with() const
Definition: scopes.h:310
bool AllowsLazyCompilationWithoutContext() const
Definition: scopes.cc:716
bool IsFunctionContext()
Definition: contexts.h:417
Zone * zone() const
Definition: scopes.h:120
bool IsUnallocated() const
Definition: variables.h:115
Variable * DeclareDynamicGlobal(Handle< String > name)
Definition: scopes.cc:482
int ContextLocalCount() const
Definition: scopes.cc:1398
Variable * Lookup(Handle< String > name)
Definition: scopes.cc:90
Object * extension()
Definition: contexts.h:378
void USE(T)
Definition: globals.h:341
void set_is_used(bool flag)
Definition: variables.h:106
MUST_USE_RESULT bool AllocateVariables(CompilationInfo *info, AstNodeFactory< AstNullVisitor > *factory)
Definition: scopes.cc:642
void Print(const v8::FunctionCallbackInfo< v8::Value > &args)
Variable * NonLocal(Handle< String > name, VariableMode mode)
Definition: scopes.cc:943
bool IsGlobalObjectProperty() const
Definition: variables.cc:85
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:39
bool outer_scope_calls_sloppy_eval() const
Definition: scopes.h:303
MUST_USE_RESULT bool ResolveVariable(CompilationInfo *info, VariableProxy *proxy, AstNodeFactory< AstNullVisitor > *factory)
Definition: scopes.cc:1027
Variable * module_var_
Definition: scopes.h:515
DynamicScopePart * dynamics_
Definition: scopes.h:462
void AllocateModulesRecursively(Scope *host_scope)
Definition: scopes.cc:1374
JSFunction * closure()
Definition: contexts.h:367
bool is_function_scope() const
Definition: scopes.h:284
Variable * Lookup(Handle< String > name)
Definition: scopes.cc:447
virtual void Accept(AstVisitor *v)=0
VariableMode mode() const
Definition: ast.h:487
VariableMap(Zone *zone)
Definition: scopes.cc:59
Variable * Declare(Scope *scope, Handle< String > name, VariableMode mode, bool is_valid_lhs, Variable::Kind kind, InitializationFlag initialization_flag, Interface *interface=Interface::NewValue())
Definition: scopes.cc:65
void RecordWithStatement()
Definition: scopes.h:231
bool is_module_scope() const
Definition: scopes.h:285
bool is_catch_scope() const
Definition: scopes.h:287
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV 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 expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
Definition: flags.cc:505
static Scope * DeserializeScopeChain(Context *context, Scope *global_scope, Zone *zone)
Definition: scopes.cc:214
Scope * outer_scope_
Definition: scopes.h:440
void RemoveUnresolved(VariableProxy *var)
Definition: scopes.cc:493
Entry * Next(Entry *p) const
Definition: hashmap.h:243
Handle< JSArray > NewJSArray(ElementsKind elements_kind, int length, int capacity, ArrayStorageAllocationMode mode=INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:1437
Variable * LookupFunctionVar(Handle< String > name, AstNodeFactory< AstNullVisitor > *factory)
Definition: scopes.cc:423
bool scope_inside_with_
Definition: scopes.h:482
MUST_USE_RESULT bool ResolveVariablesRecursively(CompilationInfo *info, AstNodeFactory< AstNullVisitor > *factory)
Definition: scopes.cc:1131
void SetIllegalRedeclaration(Expression *expression)
Definition: scopes.cc:536