Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: src/scopes.cc

Issue 1481613002: Create ast/ and parsing/ subdirectories and move appropriate files (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/scopes.h ('k') | src/snapshot/serialize.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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/scopes.h"
6
7 #include "src/accessors.h"
8 #include "src/bootstrapper.h"
9 #include "src/messages.h"
10 #include "src/parser.h"
11 #include "src/scopeinfo.h"
12
13 namespace v8 {
14 namespace internal {
15
16 // ----------------------------------------------------------------------------
17 // Implementation of LocalsMap
18 //
19 // Note: We are storing the handle locations as key values in the hash map.
20 // When inserting a new variable via Declare(), we rely on the fact that
21 // the handle location remains alive for the duration of that variable
22 // use. Because a Variable holding a handle with the same location exists
23 // this is ensured.
24
25 VariableMap::VariableMap(Zone* zone)
26 : ZoneHashMap(ZoneHashMap::PointersMatch, 8, ZoneAllocationPolicy(zone)),
27 zone_(zone) {}
28 VariableMap::~VariableMap() {}
29
30
31 Variable* VariableMap::Declare(Scope* scope, const AstRawString* name,
32 VariableMode mode, Variable::Kind kind,
33 InitializationFlag initialization_flag,
34 MaybeAssignedFlag maybe_assigned_flag,
35 int declaration_group_start) {
36 // AstRawStrings are unambiguous, i.e., the same string is always represented
37 // by the same AstRawString*.
38 // FIXME(marja): fix the type of Lookup.
39 Entry* p =
40 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(),
41 ZoneAllocationPolicy(zone()));
42 if (p->value == NULL) {
43 // The variable has not been declared yet -> insert it.
44 DCHECK(p->key == name);
45 if (kind == Variable::CLASS) {
46 p->value = new (zone())
47 ClassVariable(scope, name, mode, initialization_flag,
48 maybe_assigned_flag, declaration_group_start);
49 } else {
50 p->value = new (zone()) Variable(
51 scope, name, mode, kind, initialization_flag, maybe_assigned_flag);
52 }
53 }
54 return reinterpret_cast<Variable*>(p->value);
55 }
56
57
58 Variable* VariableMap::Lookup(const AstRawString* name) {
59 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash());
60 if (p != NULL) {
61 DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name);
62 DCHECK(p->value != NULL);
63 return reinterpret_cast<Variable*>(p->value);
64 }
65 return NULL;
66 }
67
68
69 SloppyBlockFunctionMap::SloppyBlockFunctionMap(Zone* zone)
70 : ZoneHashMap(ZoneHashMap::PointersMatch, 8, ZoneAllocationPolicy(zone)),
71 zone_(zone) {}
72 SloppyBlockFunctionMap::~SloppyBlockFunctionMap() {}
73
74
75 void SloppyBlockFunctionMap::Declare(const AstRawString* name,
76 SloppyBlockFunctionStatement* stmt) {
77 // AstRawStrings are unambiguous, i.e., the same string is always represented
78 // by the same AstRawString*.
79 Entry* p =
80 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(),
81 ZoneAllocationPolicy(zone_));
82 if (p->value == nullptr) {
83 p->value = new (zone_->New(sizeof(Vector))) Vector(zone_);
84 }
85 Vector* delegates = static_cast<Vector*>(p->value);
86 delegates->push_back(stmt);
87 }
88
89
90 // ----------------------------------------------------------------------------
91 // Implementation of Scope
92
93 Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type,
94 AstValueFactory* ast_value_factory, FunctionKind function_kind)
95 : inner_scopes_(4, zone),
96 variables_(zone),
97 temps_(4, zone),
98 params_(4, zone),
99 unresolved_(16, zone),
100 decls_(4, zone),
101 module_descriptor_(
102 scope_type == MODULE_SCOPE ? ModuleDescriptor::New(zone) : NULL),
103 sloppy_block_function_map_(zone),
104 already_resolved_(false),
105 ast_value_factory_(ast_value_factory),
106 zone_(zone),
107 class_declaration_group_start_(-1) {
108 SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null(),
109 function_kind);
110 // The outermost scope must be a script scope.
111 DCHECK(scope_type == SCRIPT_SCOPE || outer_scope != NULL);
112 DCHECK(!HasIllegalRedeclaration());
113 }
114
115
116 Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type,
117 Handle<ScopeInfo> scope_info, AstValueFactory* value_factory)
118 : inner_scopes_(4, zone),
119 variables_(zone),
120 temps_(4, zone),
121 params_(4, zone),
122 unresolved_(16, zone),
123 decls_(4, zone),
124 module_descriptor_(NULL),
125 sloppy_block_function_map_(zone),
126 already_resolved_(true),
127 ast_value_factory_(value_factory),
128 zone_(zone),
129 class_declaration_group_start_(-1) {
130 SetDefaults(scope_type, NULL, scope_info);
131 if (!scope_info.is_null()) {
132 num_heap_slots_ = scope_info_->ContextLength();
133 }
134 // Ensure at least MIN_CONTEXT_SLOTS to indicate a materialized context.
135 num_heap_slots_ = Max(num_heap_slots_,
136 static_cast<int>(Context::MIN_CONTEXT_SLOTS));
137 AddInnerScope(inner_scope);
138 }
139
140
141 Scope::Scope(Zone* zone, Scope* inner_scope,
142 const AstRawString* catch_variable_name,
143 AstValueFactory* value_factory)
144 : inner_scopes_(1, zone),
145 variables_(zone),
146 temps_(0, zone),
147 params_(0, zone),
148 unresolved_(0, zone),
149 decls_(0, zone),
150 module_descriptor_(NULL),
151 sloppy_block_function_map_(zone),
152 already_resolved_(true),
153 ast_value_factory_(value_factory),
154 zone_(zone),
155 class_declaration_group_start_(-1) {
156 SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null());
157 AddInnerScope(inner_scope);
158 ++num_var_or_const_;
159 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
160 Variable* variable = variables_.Declare(this,
161 catch_variable_name,
162 VAR,
163 Variable::NORMAL,
164 kCreatedInitialized);
165 AllocateHeapSlot(variable);
166 }
167
168
169 void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope,
170 Handle<ScopeInfo> scope_info,
171 FunctionKind function_kind) {
172 outer_scope_ = outer_scope;
173 scope_type_ = scope_type;
174 is_declaration_scope_ =
175 is_eval_scope() || is_function_scope() ||
176 is_module_scope() || is_script_scope();
177 function_kind_ = function_kind;
178 scope_name_ = ast_value_factory_->empty_string();
179 dynamics_ = nullptr;
180 receiver_ = nullptr;
181 new_target_ = nullptr;
182 function_ = nullptr;
183 arguments_ = nullptr;
184 this_function_ = nullptr;
185 illegal_redecl_ = nullptr;
186 scope_inside_with_ = false;
187 scope_contains_with_ = false;
188 scope_calls_eval_ = false;
189 scope_uses_arguments_ = false;
190 scope_uses_super_property_ = false;
191 asm_module_ = false;
192 asm_function_ = outer_scope != NULL && outer_scope->asm_module_;
193 // Inherit the language mode from the parent scope.
194 language_mode_ = outer_scope != NULL ? outer_scope->language_mode_ : SLOPPY;
195 outer_scope_calls_sloppy_eval_ = false;
196 inner_scope_calls_eval_ = false;
197 scope_nonlinear_ = false;
198 force_eager_compilation_ = false;
199 force_context_allocation_ = (outer_scope != NULL && !is_function_scope())
200 ? outer_scope->has_forced_context_allocation() : false;
201 num_var_or_const_ = 0;
202 num_stack_slots_ = 0;
203 num_heap_slots_ = 0;
204 num_global_slots_ = 0;
205 num_modules_ = 0;
206 module_var_ = NULL;
207 arity_ = 0;
208 has_simple_parameters_ = true;
209 rest_parameter_ = NULL;
210 rest_index_ = -1;
211 scope_info_ = scope_info;
212 start_position_ = RelocInfo::kNoPosition;
213 end_position_ = RelocInfo::kNoPosition;
214 if (!scope_info.is_null()) {
215 scope_calls_eval_ = scope_info->CallsEval();
216 language_mode_ = scope_info->language_mode();
217 is_declaration_scope_ = scope_info->is_declaration_scope();
218 function_kind_ = scope_info->function_kind();
219 }
220 }
221
222
223 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
224 Context* context, Scope* script_scope) {
225 // Reconstruct the outer scope chain from a closure's context chain.
226 Scope* current_scope = NULL;
227 Scope* innermost_scope = NULL;
228 bool contains_with = false;
229 while (!context->IsNativeContext()) {
230 if (context->IsWithContext()) {
231 Scope* with_scope = new (zone)
232 Scope(zone, current_scope, WITH_SCOPE, Handle<ScopeInfo>::null(),
233 script_scope->ast_value_factory_);
234 current_scope = with_scope;
235 // All the inner scopes are inside a with.
236 contains_with = true;
237 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) {
238 s->scope_inside_with_ = true;
239 }
240 } else if (context->IsScriptContext()) {
241 ScopeInfo* scope_info = context->scope_info();
242 current_scope = new (zone) Scope(zone, current_scope, SCRIPT_SCOPE,
243 Handle<ScopeInfo>(scope_info),
244 script_scope->ast_value_factory_);
245 } else if (context->IsModuleContext()) {
246 ScopeInfo* scope_info = context->module()->scope_info();
247 current_scope = new (zone) Scope(zone, current_scope, MODULE_SCOPE,
248 Handle<ScopeInfo>(scope_info),
249 script_scope->ast_value_factory_);
250 } else if (context->IsFunctionContext()) {
251 ScopeInfo* scope_info = context->closure()->shared()->scope_info();
252 current_scope = new (zone) Scope(zone, current_scope, FUNCTION_SCOPE,
253 Handle<ScopeInfo>(scope_info),
254 script_scope->ast_value_factory_);
255 if (scope_info->IsAsmFunction()) current_scope->asm_function_ = true;
256 if (scope_info->IsAsmModule()) current_scope->asm_module_ = true;
257 } else if (context->IsBlockContext()) {
258 ScopeInfo* scope_info = context->scope_info();
259 current_scope = new (zone)
260 Scope(zone, current_scope, BLOCK_SCOPE, Handle<ScopeInfo>(scope_info),
261 script_scope->ast_value_factory_);
262 } else {
263 DCHECK(context->IsCatchContext());
264 String* name = context->catch_name();
265 current_scope = new (zone) Scope(
266 zone, current_scope,
267 script_scope->ast_value_factory_->GetString(Handle<String>(name)),
268 script_scope->ast_value_factory_);
269 }
270 if (contains_with) current_scope->RecordWithStatement();
271 if (innermost_scope == NULL) innermost_scope = current_scope;
272
273 // Forget about a with when we move to a context for a different function.
274 if (context->previous()->closure() != context->closure()) {
275 contains_with = false;
276 }
277 context = context->previous();
278 }
279
280 script_scope->AddInnerScope(current_scope);
281 script_scope->PropagateScopeInfo(false);
282 return (innermost_scope == NULL) ? script_scope : innermost_scope;
283 }
284
285
286 bool Scope::Analyze(ParseInfo* info) {
287 DCHECK(info->literal() != NULL);
288 DCHECK(info->scope() == NULL);
289 Scope* scope = info->literal()->scope();
290 Scope* top = scope;
291
292 // Traverse the scope tree up to the first unresolved scope or the global
293 // scope and start scope resolution and variable allocation from that scope.
294 while (!top->is_script_scope() &&
295 !top->outer_scope()->already_resolved()) {
296 top = top->outer_scope();
297 }
298
299 // Allocate the variables.
300 {
301 AstNodeFactory ast_node_factory(info->ast_value_factory());
302 if (!top->AllocateVariables(info, &ast_node_factory)) {
303 DCHECK(top->pending_error_handler_.has_pending_error());
304 top->pending_error_handler_.ThrowPendingError(info->isolate(),
305 info->script());
306 return false;
307 }
308 }
309
310 #ifdef DEBUG
311 bool native = info->isolate()->bootstrapper()->IsActive();
312 if (!info->shared_info().is_null()) {
313 Object* script = info->shared_info()->script();
314 native = script->IsScript() &&
315 Script::cast(script)->type() == Script::TYPE_NATIVE;
316 }
317
318 if (native ? FLAG_print_builtin_scopes : FLAG_print_scopes) scope->Print();
319 #endif
320
321 info->set_scope(scope);
322 return true;
323 }
324
325
326 void Scope::Initialize() {
327 DCHECK(!already_resolved());
328
329 // Add this scope as a new inner scope of the outer scope.
330 if (outer_scope_ != NULL) {
331 outer_scope_->inner_scopes_.Add(this, zone());
332 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope();
333 } else {
334 scope_inside_with_ = is_with_scope();
335 }
336
337 // Declare convenience variables and the receiver.
338 if (is_declaration_scope() && has_this_declaration()) {
339 bool subclass_constructor = IsSubclassConstructor(function_kind_);
340 Variable* var = variables_.Declare(
341 this, ast_value_factory_->this_string(),
342 subclass_constructor ? CONST : VAR, Variable::THIS,
343 subclass_constructor ? kNeedsInitialization : kCreatedInitialized);
344 receiver_ = var;
345 }
346
347 if (is_function_scope() && !is_arrow_scope()) {
348 // Declare 'arguments' variable which exists in all non arrow functions.
349 // Note that it might never be accessed, in which case it won't be
350 // allocated during variable allocation.
351 variables_.Declare(this, ast_value_factory_->arguments_string(), VAR,
352 Variable::ARGUMENTS, kCreatedInitialized);
353
354 variables_.Declare(this, ast_value_factory_->new_target_string(), CONST,
355 Variable::NORMAL, kCreatedInitialized);
356
357 if (IsConciseMethod(function_kind_) || IsClassConstructor(function_kind_) ||
358 IsAccessorFunction(function_kind_)) {
359 variables_.Declare(this, ast_value_factory_->this_function_string(),
360 CONST, Variable::NORMAL, kCreatedInitialized);
361 }
362 }
363 }
364
365
366 Scope* Scope::FinalizeBlockScope() {
367 DCHECK(is_block_scope());
368 DCHECK(temps_.is_empty());
369 DCHECK(params_.is_empty());
370
371 if (num_var_or_const() > 0 ||
372 (is_declaration_scope() && calls_sloppy_eval())) {
373 return this;
374 }
375
376 // Remove this scope from outer scope.
377 outer_scope()->RemoveInnerScope(this);
378
379 // Reparent inner scopes.
380 for (int i = 0; i < inner_scopes_.length(); i++) {
381 outer_scope()->AddInnerScope(inner_scopes_[i]);
382 }
383
384 // Move unresolved variables
385 for (int i = 0; i < unresolved_.length(); i++) {
386 outer_scope()->unresolved_.Add(unresolved_[i], zone());
387 }
388
389 PropagateUsageFlagsToScope(outer_scope_);
390
391 return NULL;
392 }
393
394
395 void Scope::ReplaceOuterScope(Scope* outer) {
396 DCHECK_NOT_NULL(outer);
397 DCHECK_NOT_NULL(outer_scope_);
398 DCHECK(!already_resolved());
399 DCHECK(!outer->already_resolved());
400 DCHECK(!outer_scope_->already_resolved());
401 outer_scope_->RemoveInnerScope(this);
402 outer->AddInnerScope(this);
403 outer_scope_ = outer;
404 }
405
406
407 void Scope::PropagateUsageFlagsToScope(Scope* other) {
408 DCHECK_NOT_NULL(other);
409 DCHECK(!already_resolved());
410 DCHECK(!other->already_resolved());
411 if (uses_arguments()) other->RecordArgumentsUsage();
412 if (uses_super_property()) other->RecordSuperPropertyUsage();
413 if (calls_eval()) other->RecordEvalCall();
414 if (scope_contains_with_) other->RecordWithStatement();
415 }
416
417
418 Variable* Scope::LookupLocal(const AstRawString* name) {
419 Variable* result = variables_.Lookup(name);
420 if (result != NULL || scope_info_.is_null()) {
421 return result;
422 }
423 Handle<String> name_handle = name->string();
424 // The Scope is backed up by ScopeInfo. This means it cannot operate in a
425 // heap-independent mode, and all strings must be internalized immediately. So
426 // it's ok to get the Handle<String> here.
427 // If we have a serialized scope info, we might find the variable there.
428 // There should be no local slot with the given name.
429 DCHECK(scope_info_->StackSlotIndex(*name_handle) < 0 || is_block_scope());
430
431 // Check context slot lookup.
432 VariableMode mode;
433 VariableLocation location = VariableLocation::CONTEXT;
434 InitializationFlag init_flag;
435 MaybeAssignedFlag maybe_assigned_flag;
436 int index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode,
437 &init_flag, &maybe_assigned_flag);
438 if (index < 0) {
439 location = VariableLocation::GLOBAL;
440 index = ScopeInfo::ContextGlobalSlotIndex(scope_info_, name_handle, &mode,
441 &init_flag, &maybe_assigned_flag);
442 }
443 if (index < 0) {
444 // Check parameters.
445 index = scope_info_->ParameterIndex(*name_handle);
446 if (index < 0) return NULL;
447
448 mode = DYNAMIC;
449 location = VariableLocation::LOOKUP;
450 init_flag = kCreatedInitialized;
451 // Be conservative and flag parameters as maybe assigned. Better information
452 // would require ScopeInfo to serialize the maybe_assigned bit also for
453 // parameters.
454 maybe_assigned_flag = kMaybeAssigned;
455 } else {
456 DCHECK(location != VariableLocation::GLOBAL ||
457 (is_script_scope() && IsDeclaredVariableMode(mode) &&
458 !IsLexicalVariableMode(mode)));
459 }
460
461 Variable::Kind kind = Variable::NORMAL;
462 if (location == VariableLocation::CONTEXT &&
463 index == scope_info_->ReceiverContextSlotIndex()) {
464 kind = Variable::THIS;
465 }
466 // TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and
467 // ARGUMENTS bindings as their corresponding Variable::Kind.
468
469 Variable* var = variables_.Declare(this, name, mode, kind, init_flag,
470 maybe_assigned_flag);
471 var->AllocateTo(location, index);
472 return var;
473 }
474
475
476 Variable* Scope::LookupFunctionVar(const AstRawString* name,
477 AstNodeFactory* factory) {
478 if (function_ != NULL && function_->proxy()->raw_name() == name) {
479 return function_->proxy()->var();
480 } else if (!scope_info_.is_null()) {
481 // If we are backed by a scope info, try to lookup the variable there.
482 VariableMode mode;
483 int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode);
484 if (index < 0) return NULL;
485 Variable* var = new (zone())
486 Variable(this, name, mode, Variable::NORMAL, kCreatedInitialized);
487 VariableProxy* proxy = factory->NewVariableProxy(var);
488 VariableDeclaration* declaration = factory->NewVariableDeclaration(
489 proxy, mode, this, RelocInfo::kNoPosition);
490 DeclareFunctionVar(declaration);
491 var->AllocateTo(VariableLocation::CONTEXT, index);
492 return var;
493 } else {
494 return NULL;
495 }
496 }
497
498
499 Variable* Scope::Lookup(const AstRawString* name) {
500 for (Scope* scope = this;
501 scope != NULL;
502 scope = scope->outer_scope()) {
503 Variable* var = scope->LookupLocal(name);
504 if (var != NULL) return var;
505 }
506 return NULL;
507 }
508
509
510 Variable* Scope::DeclareParameter(
511 const AstRawString* name, VariableMode mode,
512 bool is_optional, bool is_rest, bool* is_duplicate) {
513 DCHECK(!already_resolved());
514 DCHECK(is_function_scope());
515 DCHECK(!is_optional || !is_rest);
516 Variable* var;
517 if (mode == TEMPORARY) {
518 var = NewTemporary(name);
519 } else {
520 var = variables_.Declare(this, name, mode, Variable::NORMAL,
521 kCreatedInitialized);
522 // TODO(wingo): Avoid O(n^2) check.
523 *is_duplicate = IsDeclaredParameter(name);
524 }
525 if (!is_optional && !is_rest && arity_ == params_.length()) {
526 ++arity_;
527 }
528 if (is_rest) {
529 DCHECK_NULL(rest_parameter_);
530 rest_parameter_ = var;
531 rest_index_ = num_parameters();
532 }
533 params_.Add(var, zone());
534 return var;
535 }
536
537
538 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode,
539 InitializationFlag init_flag, Variable::Kind kind,
540 MaybeAssignedFlag maybe_assigned_flag,
541 int declaration_group_start) {
542 DCHECK(!already_resolved());
543 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are
544 // introduces during variable allocation, and TEMPORARY variables are
545 // allocated via NewTemporary().
546 DCHECK(IsDeclaredVariableMode(mode));
547 ++num_var_or_const_;
548 return variables_.Declare(this, name, mode, kind, init_flag,
549 maybe_assigned_flag, declaration_group_start);
550 }
551
552
553 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) {
554 DCHECK(is_script_scope());
555 return variables_.Declare(this,
556 name,
557 DYNAMIC_GLOBAL,
558 Variable::NORMAL,
559 kCreatedInitialized);
560 }
561
562
563 bool Scope::RemoveUnresolved(VariableProxy* var) {
564 // Most likely (always?) any variable we want to remove
565 // was just added before, so we search backwards.
566 for (int i = unresolved_.length(); i-- > 0;) {
567 if (unresolved_[i] == var) {
568 unresolved_.Remove(i);
569 return true;
570 }
571 }
572 return false;
573 }
574
575
576 Variable* Scope::NewTemporary(const AstRawString* name) {
577 DCHECK(!already_resolved());
578 Scope* scope = this->ClosureScope();
579 Variable* var = new(zone()) Variable(scope,
580 name,
581 TEMPORARY,
582 Variable::NORMAL,
583 kCreatedInitialized);
584 scope->temps_.Add(var, zone());
585 return var;
586 }
587
588
589 void Scope::AddDeclaration(Declaration* declaration) {
590 decls_.Add(declaration, zone());
591 }
592
593
594 void Scope::SetIllegalRedeclaration(Expression* expression) {
595 // Record only the first illegal redeclaration.
596 if (!HasIllegalRedeclaration()) {
597 illegal_redecl_ = expression;
598 }
599 DCHECK(HasIllegalRedeclaration());
600 }
601
602
603 Expression* Scope::GetIllegalRedeclaration() {
604 DCHECK(HasIllegalRedeclaration());
605 return illegal_redecl_;
606 }
607
608
609 Declaration* Scope::CheckConflictingVarDeclarations() {
610 int length = decls_.length();
611 for (int i = 0; i < length; i++) {
612 Declaration* decl = decls_[i];
613 // We don't create a separate scope to hold the function name of a function
614 // expression, so we have to make sure not to consider it when checking for
615 // conflicts (since it's conceptually "outside" the declaration scope).
616 if (is_function_scope() && decl == function()) continue;
617 if (IsLexicalVariableMode(decl->mode()) && !is_block_scope()) continue;
618 const AstRawString* name = decl->proxy()->raw_name();
619
620 // Iterate through all scopes until and including the declaration scope.
621 Scope* previous = NULL;
622 Scope* current = decl->scope();
623 // Lexical vs lexical conflicts within the same scope have already been
624 // captured in Parser::Declare. The only conflicts we still need to check
625 // are lexical vs VAR, or any declarations within a declaration block scope
626 // vs lexical declarations in its surrounding (function) scope.
627 if (IsLexicalVariableMode(decl->mode())) current = current->outer_scope_;
628 do {
629 // There is a conflict if there exists a non-VAR binding.
630 Variable* other_var = current->variables_.Lookup(name);
631 if (other_var != NULL && IsLexicalVariableMode(other_var->mode())) {
632 return decl;
633 }
634 previous = current;
635 current = current->outer_scope_;
636 } while (!previous->is_declaration_scope());
637 }
638 return NULL;
639 }
640
641
642 class VarAndOrder {
643 public:
644 VarAndOrder(Variable* var, int order) : var_(var), order_(order) { }
645 Variable* var() const { return var_; }
646 int order() const { return order_; }
647 static int Compare(const VarAndOrder* a, const VarAndOrder* b) {
648 return a->order_ - b->order_;
649 }
650
651 private:
652 Variable* var_;
653 int order_;
654 };
655
656
657 void Scope::CollectStackAndContextLocals(
658 ZoneList<Variable*>* stack_locals, ZoneList<Variable*>* context_locals,
659 ZoneList<Variable*>* context_globals,
660 ZoneList<Variable*>* strong_mode_free_variables) {
661 DCHECK(stack_locals != NULL);
662 DCHECK(context_locals != NULL);
663 DCHECK(context_globals != NULL);
664
665 // Collect temporaries which are always allocated on the stack, unless the
666 // context as a whole has forced context allocation.
667 for (int i = 0; i < temps_.length(); i++) {
668 Variable* var = temps_[i];
669 if (var->is_used()) {
670 if (var->IsContextSlot()) {
671 DCHECK(has_forced_context_allocation());
672 context_locals->Add(var, zone());
673 } else if (var->IsStackLocal()) {
674 stack_locals->Add(var, zone());
675 } else {
676 DCHECK(var->IsParameter());
677 }
678 }
679 }
680
681 // Collect declared local variables.
682 ZoneList<VarAndOrder> vars(variables_.occupancy(), zone());
683 for (VariableMap::Entry* p = variables_.Start();
684 p != NULL;
685 p = variables_.Next(p)) {
686 Variable* var = reinterpret_cast<Variable*>(p->value);
687 if (strong_mode_free_variables && var->has_strong_mode_reference() &&
688 var->mode() == DYNAMIC_GLOBAL) {
689 strong_mode_free_variables->Add(var, zone());
690 }
691
692 if (var->is_used()) {
693 vars.Add(VarAndOrder(var, p->order), zone());
694 }
695 }
696 vars.Sort(VarAndOrder::Compare);
697 int var_count = vars.length();
698 for (int i = 0; i < var_count; i++) {
699 Variable* var = vars[i].var();
700 if (var->IsStackLocal()) {
701 stack_locals->Add(var, zone());
702 } else if (var->IsContextSlot()) {
703 context_locals->Add(var, zone());
704 } else if (var->IsGlobalSlot()) {
705 context_globals->Add(var, zone());
706 }
707 }
708 }
709
710
711 bool Scope::AllocateVariables(ParseInfo* info, AstNodeFactory* factory) {
712 // 1) Propagate scope information.
713 bool outer_scope_calls_sloppy_eval = false;
714 if (outer_scope_ != NULL) {
715 outer_scope_calls_sloppy_eval =
716 outer_scope_->outer_scope_calls_sloppy_eval() |
717 outer_scope_->calls_sloppy_eval();
718 }
719 PropagateScopeInfo(outer_scope_calls_sloppy_eval);
720
721 // 2) Allocate module instances.
722 if (FLAG_harmony_modules && is_script_scope()) {
723 DCHECK(num_modules_ == 0);
724 AllocateModules();
725 }
726
727 // 3) Resolve variables.
728 if (!ResolveVariablesRecursively(info, factory)) return false;
729
730 // 4) Allocate variables.
731 AllocateVariablesRecursively(info->isolate());
732
733 return true;
734 }
735
736
737 bool Scope::HasTrivialContext() const {
738 // A function scope has a trivial context if it always is the global
739 // context. We iteratively scan out the context chain to see if
740 // there is anything that makes this scope non-trivial; otherwise we
741 // return true.
742 for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) {
743 if (scope->is_eval_scope()) return false;
744 if (scope->scope_inside_with_) return false;
745 if (scope->ContextLocalCount() > 0) return false;
746 if (scope->ContextGlobalCount() > 0) return false;
747 }
748 return true;
749 }
750
751
752 bool Scope::HasTrivialOuterContext() const {
753 Scope* outer = outer_scope_;
754 if (outer == NULL) return true;
755 // Note that the outer context may be trivial in general, but the current
756 // scope may be inside a 'with' statement in which case the outer context
757 // for this scope is not trivial.
758 return !scope_inside_with_ && outer->HasTrivialContext();
759 }
760
761
762 bool Scope::AllowsLazyParsing() const {
763 // If we are inside a block scope, we must parse eagerly to find out how
764 // to allocate variables on the block scope. At this point, declarations may
765 // not have yet been parsed.
766 for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) {
767 if (scope->is_block_scope()) return false;
768 }
769 return AllowsLazyCompilation();
770 }
771
772
773 bool Scope::AllowsLazyCompilation() const { return !force_eager_compilation_; }
774
775
776 bool Scope::AllowsLazyCompilationWithoutContext() const {
777 return !force_eager_compilation_ && HasTrivialOuterContext();
778 }
779
780
781 int Scope::ContextChainLength(Scope* scope) {
782 int n = 0;
783 for (Scope* s = this; s != scope; s = s->outer_scope_) {
784 DCHECK(s != NULL); // scope must be in the scope chain
785 if (s->NeedsContext()) n++;
786 }
787 return n;
788 }
789
790
791 int Scope::MaxNestedContextChainLength() {
792 int max_context_chain_length = 0;
793 for (int i = 0; i < inner_scopes_.length(); i++) {
794 Scope* scope = inner_scopes_[i];
795 max_context_chain_length = std::max(scope->MaxNestedContextChainLength(),
796 max_context_chain_length);
797 }
798 if (NeedsContext()) {
799 max_context_chain_length += 1;
800 }
801 return max_context_chain_length;
802 }
803
804
805 Scope* Scope::DeclarationScope() {
806 Scope* scope = this;
807 while (!scope->is_declaration_scope()) {
808 scope = scope->outer_scope();
809 }
810 return scope;
811 }
812
813
814 Scope* Scope::ClosureScope() {
815 Scope* scope = this;
816 while (!scope->is_declaration_scope() || scope->is_block_scope()) {
817 scope = scope->outer_scope();
818 }
819 return scope;
820 }
821
822
823 Scope* Scope::ReceiverScope() {
824 Scope* scope = this;
825 while (!scope->is_script_scope() &&
826 (!scope->is_function_scope() || scope->is_arrow_scope())) {
827 scope = scope->outer_scope();
828 }
829 return scope;
830 }
831
832
833
834 Handle<ScopeInfo> Scope::GetScopeInfo(Isolate* isolate) {
835 if (scope_info_.is_null()) {
836 scope_info_ = ScopeInfo::Create(isolate, zone(), this);
837 }
838 return scope_info_;
839 }
840
841
842 void Scope::GetNestedScopeChain(Isolate* isolate,
843 List<Handle<ScopeInfo> >* chain, int position) {
844 if (!is_eval_scope()) chain->Add(Handle<ScopeInfo>(GetScopeInfo(isolate)));
845
846 for (int i = 0; i < inner_scopes_.length(); i++) {
847 Scope* scope = inner_scopes_[i];
848 int beg_pos = scope->start_position();
849 int end_pos = scope->end_position();
850 DCHECK(beg_pos >= 0 && end_pos >= 0);
851 if (beg_pos <= position && position < end_pos) {
852 scope->GetNestedScopeChain(isolate, chain, position);
853 return;
854 }
855 }
856 }
857
858
859 void Scope::ReportMessage(int start_position, int end_position,
860 MessageTemplate::Template message,
861 const AstRawString* arg) {
862 // Propagate the error to the topmost scope targeted by this scope analysis
863 // phase.
864 Scope* top = this;
865 while (!top->is_script_scope() && !top->outer_scope()->already_resolved()) {
866 top = top->outer_scope();
867 }
868
869 top->pending_error_handler_.ReportMessageAt(start_position, end_position,
870 message, arg, kReferenceError);
871 }
872
873
874 #ifdef DEBUG
875 static const char* Header(ScopeType scope_type, FunctionKind function_kind,
876 bool is_declaration_scope) {
877 switch (scope_type) {
878 case EVAL_SCOPE: return "eval";
879 // TODO(adamk): Should we print concise method scopes specially?
880 case FUNCTION_SCOPE:
881 return IsArrowFunction(function_kind) ? "arrow" : "function";
882 case MODULE_SCOPE: return "module";
883 case SCRIPT_SCOPE: return "global";
884 case CATCH_SCOPE: return "catch";
885 case BLOCK_SCOPE: return is_declaration_scope ? "varblock" : "block";
886 case WITH_SCOPE: return "with";
887 }
888 UNREACHABLE();
889 return NULL;
890 }
891
892
893 static void Indent(int n, const char* str) {
894 PrintF("%*s%s", n, "", str);
895 }
896
897
898 static void PrintName(const AstRawString* name) {
899 PrintF("%.*s", name->length(), name->raw_data());
900 }
901
902
903 static void PrintLocation(Variable* var) {
904 switch (var->location()) {
905 case VariableLocation::UNALLOCATED:
906 break;
907 case VariableLocation::PARAMETER:
908 PrintF("parameter[%d]", var->index());
909 break;
910 case VariableLocation::LOCAL:
911 PrintF("local[%d]", var->index());
912 break;
913 case VariableLocation::CONTEXT:
914 PrintF("context[%d]", var->index());
915 break;
916 case VariableLocation::GLOBAL:
917 PrintF("global[%d]", var->index());
918 break;
919 case VariableLocation::LOOKUP:
920 PrintF("lookup");
921 break;
922 }
923 }
924
925
926 static void PrintVar(int indent, Variable* var) {
927 if (var->is_used() || !var->IsUnallocated()) {
928 Indent(indent, Variable::Mode2String(var->mode()));
929 PrintF(" ");
930 if (var->raw_name()->IsEmpty())
931 PrintF(".%p", reinterpret_cast<void*>(var));
932 else
933 PrintName(var->raw_name());
934 PrintF("; // ");
935 PrintLocation(var);
936 bool comma = !var->IsUnallocated();
937 if (var->has_forced_context_allocation()) {
938 if (comma) PrintF(", ");
939 PrintF("forced context allocation");
940 comma = true;
941 }
942 if (var->maybe_assigned() == kMaybeAssigned) {
943 if (comma) PrintF(", ");
944 PrintF("maybe assigned");
945 }
946 PrintF("\n");
947 }
948 }
949
950
951 static void PrintMap(int indent, VariableMap* map) {
952 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) {
953 Variable* var = reinterpret_cast<Variable*>(p->value);
954 if (var == NULL) {
955 Indent(indent, "<?>\n");
956 } else {
957 PrintVar(indent, var);
958 }
959 }
960 }
961
962
963 void Scope::Print(int n) {
964 int n0 = (n > 0 ? n : 0);
965 int n1 = n0 + 2; // indentation
966
967 // Print header.
968 Indent(n0, Header(scope_type_, function_kind_, is_declaration_scope()));
969 if (scope_name_ != nullptr && !scope_name_->IsEmpty()) {
970 PrintF(" ");
971 PrintName(scope_name_);
972 }
973
974 // Print parameters, if any.
975 if (is_function_scope()) {
976 PrintF(" (");
977 for (int i = 0; i < params_.length(); i++) {
978 if (i > 0) PrintF(", ");
979 const AstRawString* name = params_[i]->raw_name();
980 if (name->IsEmpty())
981 PrintF(".%p", reinterpret_cast<void*>(params_[i]));
982 else
983 PrintName(name);
984 }
985 PrintF(")");
986 }
987
988 PrintF(" { // (%d, %d)\n", start_position(), end_position());
989
990 // Function name, if any (named function literals, only).
991 if (function_ != NULL) {
992 Indent(n1, "// (local) function name: ");
993 PrintName(function_->proxy()->raw_name());
994 PrintF("\n");
995 }
996
997 // Scope info.
998 if (HasTrivialOuterContext()) {
999 Indent(n1, "// scope has trivial outer context\n");
1000 }
1001 if (is_strong(language_mode())) {
1002 Indent(n1, "// strong mode scope\n");
1003 } else if (is_strict(language_mode())) {
1004 Indent(n1, "// strict mode scope\n");
1005 }
1006 if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
1007 if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");
1008 if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
1009 if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n");
1010 if (scope_uses_super_property_)
1011 Indent(n1, "// scope uses 'super' property\n");
1012 if (outer_scope_calls_sloppy_eval_) {
1013 Indent(n1, "// outer scope calls 'eval' in sloppy context\n");
1014 }
1015 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
1016 if (num_stack_slots_ > 0) {
1017 Indent(n1, "// ");
1018 PrintF("%d stack slots\n", num_stack_slots_);
1019 }
1020 if (num_heap_slots_ > 0) {
1021 Indent(n1, "// ");
1022 PrintF("%d heap slots (including %d global slots)\n", num_heap_slots_,
1023 num_global_slots_);
1024 }
1025
1026 // Print locals.
1027 if (function_ != NULL) {
1028 Indent(n1, "// function var:\n");
1029 PrintVar(n1, function_->proxy()->var());
1030 }
1031
1032 if (temps_.length() > 0) {
1033 Indent(n1, "// temporary vars:\n");
1034 for (int i = 0; i < temps_.length(); i++) {
1035 PrintVar(n1, temps_[i]);
1036 }
1037 }
1038
1039 if (variables_.Start() != NULL) {
1040 Indent(n1, "// local vars:\n");
1041 PrintMap(n1, &variables_);
1042 }
1043
1044 if (dynamics_ != NULL) {
1045 Indent(n1, "// dynamic vars:\n");
1046 PrintMap(n1, dynamics_->GetMap(DYNAMIC));
1047 PrintMap(n1, dynamics_->GetMap(DYNAMIC_LOCAL));
1048 PrintMap(n1, dynamics_->GetMap(DYNAMIC_GLOBAL));
1049 }
1050
1051 // Print inner scopes (disable by providing negative n).
1052 if (n >= 0) {
1053 for (int i = 0; i < inner_scopes_.length(); i++) {
1054 PrintF("\n");
1055 inner_scopes_[i]->Print(n1);
1056 }
1057 }
1058
1059 Indent(n0, "}\n");
1060 }
1061 #endif // DEBUG
1062
1063
1064 Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
1065 if (dynamics_ == NULL) dynamics_ = new (zone()) DynamicScopePart(zone());
1066 VariableMap* map = dynamics_->GetMap(mode);
1067 Variable* var = map->Lookup(name);
1068 if (var == NULL) {
1069 // Declare a new non-local.
1070 InitializationFlag init_flag = (mode == VAR)
1071 ? kCreatedInitialized : kNeedsInitialization;
1072 var = map->Declare(NULL,
1073 name,
1074 mode,
1075 Variable::NORMAL,
1076 init_flag);
1077 // Allocate it by giving it a dynamic lookup.
1078 var->AllocateTo(VariableLocation::LOOKUP, -1);
1079 }
1080 return var;
1081 }
1082
1083
1084 Variable* Scope::LookupRecursive(VariableProxy* proxy,
1085 BindingKind* binding_kind,
1086 AstNodeFactory* factory) {
1087 DCHECK(binding_kind != NULL);
1088 if (already_resolved() && is_with_scope()) {
1089 // Short-cut: if the scope is deserialized from a scope info, variable
1090 // allocation is already fixed. We can simply return with dynamic lookup.
1091 *binding_kind = DYNAMIC_LOOKUP;
1092 return NULL;
1093 }
1094
1095 // Try to find the variable in this scope.
1096 Variable* var = LookupLocal(proxy->raw_name());
1097
1098 // We found a variable and we are done. (Even if there is an 'eval' in
1099 // this scope which introduces the same variable again, the resulting
1100 // variable remains the same.)
1101 if (var != NULL) {
1102 *binding_kind = BOUND;
1103 return var;
1104 }
1105
1106 // We did not find a variable locally. Check against the function variable,
1107 // if any. We can do this for all scopes, since the function variable is
1108 // only present - if at all - for function scopes.
1109 *binding_kind = UNBOUND;
1110 var = LookupFunctionVar(proxy->raw_name(), factory);
1111 if (var != NULL) {
1112 *binding_kind = BOUND;
1113 } else if (outer_scope_ != NULL) {
1114 var = outer_scope_->LookupRecursive(proxy, binding_kind, factory);
1115 if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) {
1116 var->ForceContextAllocation();
1117 }
1118 } else {
1119 DCHECK(is_script_scope());
1120 }
1121
1122 // "this" can't be shadowed by "eval"-introduced bindings or by "with" scopes.
1123 // TODO(wingo): There are other variables in this category; add them.
1124 bool name_can_be_shadowed = var == nullptr || !var->is_this();
1125
1126 if (is_with_scope() && name_can_be_shadowed) {
1127 DCHECK(!already_resolved());
1128 // The current scope is a with scope, so the variable binding can not be
1129 // statically resolved. However, note that it was necessary to do a lookup
1130 // in the outer scope anyway, because if a binding exists in an outer scope,
1131 // the associated variable has to be marked as potentially being accessed
1132 // from inside of an inner with scope (the property may not be in the 'with'
1133 // object).
1134 if (var != NULL && proxy->is_assigned()) var->set_maybe_assigned();
1135 *binding_kind = DYNAMIC_LOOKUP;
1136 return NULL;
1137 } else if (calls_sloppy_eval() && !is_script_scope() &&
1138 name_can_be_shadowed) {
1139 // A variable binding may have been found in an outer scope, but the current
1140 // scope makes a sloppy 'eval' call, so the found variable may not be
1141 // the correct one (the 'eval' may introduce a binding with the same name).
1142 // In that case, change the lookup result to reflect this situation.
1143 if (*binding_kind == BOUND) {
1144 *binding_kind = BOUND_EVAL_SHADOWED;
1145 } else if (*binding_kind == UNBOUND) {
1146 *binding_kind = UNBOUND_EVAL_SHADOWED;
1147 }
1148 }
1149 return var;
1150 }
1151
1152
1153 bool Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy,
1154 AstNodeFactory* factory) {
1155 DCHECK(info->script_scope()->is_script_scope());
1156
1157 // If the proxy is already resolved there's nothing to do
1158 // (functions and consts may be resolved by the parser).
1159 if (proxy->is_resolved()) return true;
1160
1161 // Otherwise, try to resolve the variable.
1162 BindingKind binding_kind;
1163 Variable* var = LookupRecursive(proxy, &binding_kind, factory);
1164 switch (binding_kind) {
1165 case BOUND:
1166 // We found a variable binding.
1167 if (is_strong(language_mode())) {
1168 if (!CheckStrongModeDeclaration(proxy, var)) return false;
1169 }
1170 break;
1171
1172 case BOUND_EVAL_SHADOWED:
1173 // We either found a variable binding that might be shadowed by eval or
1174 // gave up on it (e.g. by encountering a local with the same in the outer
1175 // scope which was not promoted to a context, this can happen if we use
1176 // debugger to evaluate arbitrary expressions at a break point).
1177 if (var->IsGlobalObjectProperty()) {
1178 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL);
1179 } else if (var->is_dynamic()) {
1180 var = NonLocal(proxy->raw_name(), DYNAMIC);
1181 } else {
1182 Variable* invalidated = var;
1183 var = NonLocal(proxy->raw_name(), DYNAMIC_LOCAL);
1184 var->set_local_if_not_shadowed(invalidated);
1185 }
1186 break;
1187
1188 case UNBOUND:
1189 // No binding has been found. Declare a variable on the global object.
1190 var = info->script_scope()->DeclareDynamicGlobal(proxy->raw_name());
1191 break;
1192
1193 case UNBOUND_EVAL_SHADOWED:
1194 // No binding has been found. But some scope makes a sloppy 'eval' call.
1195 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL);
1196 break;
1197
1198 case DYNAMIC_LOOKUP:
1199 // The variable could not be resolved statically.
1200 var = NonLocal(proxy->raw_name(), DYNAMIC);
1201 break;
1202 }
1203
1204 DCHECK(var != NULL);
1205 if (proxy->is_assigned()) var->set_maybe_assigned();
1206
1207 if (is_strong(language_mode())) {
1208 // Record that the variable is referred to from strong mode. Also, record
1209 // the position.
1210 var->RecordStrongModeReference(proxy->position(), proxy->end_position());
1211 }
1212
1213 proxy->BindTo(var);
1214
1215 return true;
1216 }
1217
1218
1219 bool Scope::CheckStrongModeDeclaration(VariableProxy* proxy, Variable* var) {
1220 // Check for declaration-after use (for variables) in strong mode. Note that
1221 // we can only do this in the case where we have seen the declaration. And we
1222 // always allow referencing functions (for now).
1223
1224 // This might happen during lazy compilation; we don't keep track of
1225 // initializer positions for variables stored in ScopeInfo, so we cannot check
1226 // bindings against them. TODO(marja, rossberg): remove this hack.
1227 if (var->initializer_position() == RelocInfo::kNoPosition) return true;
1228
1229 // Allow referencing the class name from methods of that class, even though
1230 // the initializer position for class names is only after the body.
1231 Scope* scope = this;
1232 while (scope) {
1233 if (scope->ClassVariableForMethod() == var) return true;
1234 scope = scope->outer_scope();
1235 }
1236
1237 // Allow references from methods to classes declared later, if we detect no
1238 // problematic dependency cycles. Note that we can be inside multiple methods
1239 // at the same time, and it's enough if we find one where the reference is
1240 // allowed.
1241 if (var->is_class() &&
1242 var->AsClassVariable()->declaration_group_start() >= 0) {
1243 for (scope = this; scope && scope != var->scope();
1244 scope = scope->outer_scope()) {
1245 ClassVariable* class_var = scope->ClassVariableForMethod();
1246 // A method is referring to some other class, possibly declared
1247 // later. Referring to a class declared earlier is always OK and covered
1248 // by the code outside this if. Here we only need to allow special cases
1249 // for referring to a class which is declared later.
1250
1251 // Referring to a class C declared later is OK under the following
1252 // circumstances:
1253
1254 // 1. The class declarations are in a consecutive group with no other
1255 // declarations or statements in between, and
1256
1257 // 2. There is no dependency cycle where the first edge is an
1258 // initialization time dependency (computed property name or extends
1259 // clause) from C to something that depends on this class directly or
1260 // transitively.
1261 if (class_var &&
1262 class_var->declaration_group_start() ==
1263 var->AsClassVariable()->declaration_group_start()) {
1264 return true;
1265 }
1266
1267 // TODO(marja,rossberg): implement the dependency cycle detection. Here we
1268 // undershoot the target and allow referring to any class in the same
1269 // consectuive declaration group.
1270
1271 // The cycle detection can work roughly like this: 1) detect init-time
1272 // references here (they are free variables which are inside the class
1273 // scope but not inside a method scope - no parser changes needed to
1274 // detect them) 2) if we encounter an init-time reference here, allow it,
1275 // but record it for a later dependency cycle check 3) also record
1276 // non-init-time references here 4) after scope analysis is done, analyse
1277 // the dependency cycles: an illegal cycle is one starting with an
1278 // init-time reference and leading back to the starting point with either
1279 // non-init-time and init-time references.
1280 }
1281 }
1282
1283 // If both the use and the declaration are inside an eval scope (possibly
1284 // indirectly), or one of them is, we need to check whether they are inside
1285 // the same eval scope or different ones.
1286
1287 // TODO(marja,rossberg): Detect errors across different evals (depends on the
1288 // future of eval in strong mode).
1289 const Scope* eval_for_use = NearestOuterEvalScope();
1290 const Scope* eval_for_declaration = var->scope()->NearestOuterEvalScope();
1291
1292 if (proxy->position() != RelocInfo::kNoPosition &&
1293 proxy->position() < var->initializer_position() && !var->is_function() &&
1294 eval_for_use == eval_for_declaration) {
1295 DCHECK(proxy->end_position() != RelocInfo::kNoPosition);
1296 ReportMessage(proxy->position(), proxy->end_position(),
1297 MessageTemplate::kStrongUseBeforeDeclaration,
1298 proxy->raw_name());
1299 return false;
1300 }
1301 return true;
1302 }
1303
1304
1305 ClassVariable* Scope::ClassVariableForMethod() const {
1306 // TODO(marja, rossberg): This fails to find a class variable in the following
1307 // cases:
1308 // let A = class { ... }
1309 // It needs to be investigated whether this causes any practical problems.
1310 if (!is_function_scope()) return nullptr;
1311 if (IsInObjectLiteral(function_kind_)) return nullptr;
1312 if (!IsConciseMethod(function_kind_) && !IsClassConstructor(function_kind_) &&
1313 !IsAccessorFunction(function_kind_)) {
1314 return nullptr;
1315 }
1316 DCHECK_NOT_NULL(outer_scope_);
1317 // The class scope contains at most one variable, the class name.
1318 DCHECK(outer_scope_->variables_.occupancy() <= 1);
1319 if (outer_scope_->variables_.occupancy() == 0) return nullptr;
1320 VariableMap::Entry* p = outer_scope_->variables_.Start();
1321 Variable* var = reinterpret_cast<Variable*>(p->value);
1322 if (!var->is_class()) return nullptr;
1323 return var->AsClassVariable();
1324 }
1325
1326
1327 bool Scope::ResolveVariablesRecursively(ParseInfo* info,
1328 AstNodeFactory* factory) {
1329 DCHECK(info->script_scope()->is_script_scope());
1330
1331 // Resolve unresolved variables for this scope.
1332 for (int i = 0; i < unresolved_.length(); i++) {
1333 if (!ResolveVariable(info, unresolved_[i], factory)) return false;
1334 }
1335
1336 // Resolve unresolved variables for inner scopes.
1337 for (int i = 0; i < inner_scopes_.length(); i++) {
1338 if (!inner_scopes_[i]->ResolveVariablesRecursively(info, factory))
1339 return false;
1340 }
1341
1342 return true;
1343 }
1344
1345
1346 void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) {
1347 if (outer_scope_calls_sloppy_eval) {
1348 outer_scope_calls_sloppy_eval_ = true;
1349 }
1350
1351 bool calls_sloppy_eval =
1352 this->calls_sloppy_eval() || outer_scope_calls_sloppy_eval_;
1353 for (int i = 0; i < inner_scopes_.length(); i++) {
1354 Scope* inner = inner_scopes_[i];
1355 inner->PropagateScopeInfo(calls_sloppy_eval);
1356 if (inner->scope_calls_eval_ || inner->inner_scope_calls_eval_) {
1357 inner_scope_calls_eval_ = true;
1358 }
1359 if (inner->force_eager_compilation_) {
1360 force_eager_compilation_ = true;
1361 }
1362 if (asm_module_ && inner->scope_type() == FUNCTION_SCOPE) {
1363 inner->asm_function_ = true;
1364 }
1365 }
1366 }
1367
1368
1369 bool Scope::MustAllocate(Variable* var) {
1370 // Give var a read/write use if there is a chance it might be accessed
1371 // via an eval() call. This is only possible if the variable has a
1372 // visible name.
1373 if ((var->is_this() || !var->raw_name()->IsEmpty()) &&
1374 (var->has_forced_context_allocation() || scope_calls_eval_ ||
1375 inner_scope_calls_eval_ || scope_contains_with_ || is_catch_scope() ||
1376 is_block_scope() || is_module_scope() || is_script_scope())) {
1377 var->set_is_used();
1378 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned();
1379 }
1380 // Global variables do not need to be allocated.
1381 return !var->IsGlobalObjectProperty() && var->is_used();
1382 }
1383
1384
1385 bool Scope::MustAllocateInContext(Variable* var) {
1386 // If var is accessed from an inner scope, or if there is a possibility
1387 // that it might be accessed from the current or an inner scope (through
1388 // an eval() call or a runtime with lookup), it must be allocated in the
1389 // context.
1390 //
1391 // Exceptions: If the scope as a whole has forced context allocation, all
1392 // variables will have context allocation, even temporaries. Otherwise
1393 // temporary variables are always stack-allocated. Catch-bound variables are
1394 // always context-allocated.
1395 if (has_forced_context_allocation()) return true;
1396 if (var->mode() == TEMPORARY) return false;
1397 if (is_catch_scope() || is_module_scope()) return true;
1398 if (is_script_scope() && IsLexicalVariableMode(var->mode())) return true;
1399 return var->has_forced_context_allocation() ||
1400 scope_calls_eval_ ||
1401 inner_scope_calls_eval_ ||
1402 scope_contains_with_;
1403 }
1404
1405
1406 bool Scope::HasArgumentsParameter(Isolate* isolate) {
1407 for (int i = 0; i < params_.length(); i++) {
1408 if (params_[i]->name().is_identical_to(
1409 isolate->factory()->arguments_string())) {
1410 return true;
1411 }
1412 }
1413 return false;
1414 }
1415
1416
1417 void Scope::AllocateStackSlot(Variable* var) {
1418 if (is_block_scope()) {
1419 outer_scope()->DeclarationScope()->AllocateStackSlot(var);
1420 } else {
1421 var->AllocateTo(VariableLocation::LOCAL, num_stack_slots_++);
1422 }
1423 }
1424
1425
1426 void Scope::AllocateHeapSlot(Variable* var) {
1427 var->AllocateTo(VariableLocation::CONTEXT, num_heap_slots_++);
1428 }
1429
1430
1431 void Scope::AllocateParameterLocals(Isolate* isolate) {
1432 DCHECK(is_function_scope());
1433 Variable* arguments = LookupLocal(ast_value_factory_->arguments_string());
1434 // Functions have 'arguments' declared implicitly in all non arrow functions.
1435 DCHECK(arguments != nullptr || is_arrow_scope());
1436
1437 bool uses_sloppy_arguments = false;
1438
1439 if (arguments != nullptr && MustAllocate(arguments) &&
1440 !HasArgumentsParameter(isolate)) {
1441 // 'arguments' is used. Unless there is also a parameter called
1442 // 'arguments', we must be conservative and allocate all parameters to
1443 // the context assuming they will be captured by the arguments object.
1444 // If we have a parameter named 'arguments', a (new) value is always
1445 // assigned to it via the function invocation. Then 'arguments' denotes
1446 // that specific parameter value and cannot be used to access the
1447 // parameters, which is why we don't need to allocate an arguments
1448 // object in that case.
1449
1450 // We are using 'arguments'. Tell the code generator that is needs to
1451 // allocate the arguments object by setting 'arguments_'.
1452 arguments_ = arguments;
1453
1454 // In strict mode 'arguments' does not alias formal parameters.
1455 // Therefore in strict mode we allocate parameters as if 'arguments'
1456 // were not used.
1457 // If the parameter list is not simple, arguments isn't sloppy either.
1458 uses_sloppy_arguments =
1459 is_sloppy(language_mode()) && has_simple_parameters();
1460 }
1461
1462 if (rest_parameter_ && !MustAllocate(rest_parameter_)) {
1463 rest_parameter_ = NULL;
1464 }
1465
1466 // The same parameter may occur multiple times in the parameters_ list.
1467 // If it does, and if it is not copied into the context object, it must
1468 // receive the highest parameter index for that parameter; thus iteration
1469 // order is relevant!
1470 for (int i = params_.length() - 1; i >= 0; --i) {
1471 Variable* var = params_[i];
1472 if (var == rest_parameter_) continue;
1473
1474 DCHECK(var->scope() == this);
1475 if (uses_sloppy_arguments || has_forced_context_allocation()) {
1476 // Force context allocation of the parameter.
1477 var->ForceContextAllocation();
1478 }
1479 AllocateParameter(var, i);
1480 }
1481 }
1482
1483
1484 void Scope::AllocateParameter(Variable* var, int index) {
1485 if (MustAllocate(var)) {
1486 if (MustAllocateInContext(var)) {
1487 DCHECK(var->IsUnallocated() || var->IsContextSlot());
1488 if (var->IsUnallocated()) {
1489 AllocateHeapSlot(var);
1490 }
1491 } else {
1492 DCHECK(var->IsUnallocated() || var->IsParameter());
1493 if (var->IsUnallocated()) {
1494 var->AllocateTo(VariableLocation::PARAMETER, index);
1495 }
1496 }
1497 } else {
1498 DCHECK(!var->IsGlobalSlot());
1499 }
1500 }
1501
1502
1503 void Scope::AllocateReceiver() {
1504 DCHECK_NOT_NULL(receiver());
1505 DCHECK_EQ(receiver()->scope(), this);
1506
1507 if (has_forced_context_allocation()) {
1508 // Force context allocation of the receiver.
1509 receiver()->ForceContextAllocation();
1510 }
1511 AllocateParameter(receiver(), -1);
1512 }
1513
1514
1515 void Scope::AllocateNonParameterLocal(Isolate* isolate, Variable* var) {
1516 DCHECK(var->scope() == this);
1517 DCHECK(!var->IsVariable(isolate->factory()->dot_result_string()) ||
1518 !var->IsStackLocal());
1519 if (var->IsUnallocated() && MustAllocate(var)) {
1520 if (MustAllocateInContext(var)) {
1521 AllocateHeapSlot(var);
1522 } else {
1523 AllocateStackSlot(var);
1524 }
1525 }
1526 }
1527
1528
1529 void Scope::AllocateDeclaredGlobal(Isolate* isolate, Variable* var) {
1530 DCHECK(var->scope() == this);
1531 DCHECK(!var->IsVariable(isolate->factory()->dot_result_string()) ||
1532 !var->IsStackLocal());
1533 if (var->IsUnallocated()) {
1534 if (var->IsStaticGlobalObjectProperty()) {
1535 DCHECK_EQ(-1, var->index());
1536 DCHECK(var->name()->IsString());
1537 var->AllocateTo(VariableLocation::GLOBAL, num_heap_slots_++);
1538 num_global_slots_++;
1539 } else {
1540 // There must be only DYNAMIC_GLOBAL in the script scope.
1541 DCHECK(!is_script_scope() || DYNAMIC_GLOBAL == var->mode());
1542 }
1543 }
1544 }
1545
1546
1547 void Scope::AllocateNonParameterLocalsAndDeclaredGlobals(Isolate* isolate) {
1548 // All variables that have no rewrite yet are non-parameter locals.
1549 for (int i = 0; i < temps_.length(); i++) {
1550 AllocateNonParameterLocal(isolate, temps_[i]);
1551 }
1552
1553 ZoneList<VarAndOrder> vars(variables_.occupancy(), zone());
1554 for (VariableMap::Entry* p = variables_.Start();
1555 p != NULL;
1556 p = variables_.Next(p)) {
1557 Variable* var = reinterpret_cast<Variable*>(p->value);
1558 vars.Add(VarAndOrder(var, p->order), zone());
1559 }
1560 vars.Sort(VarAndOrder::Compare);
1561 int var_count = vars.length();
1562 for (int i = 0; i < var_count; i++) {
1563 AllocateNonParameterLocal(isolate, vars[i].var());
1564 }
1565
1566 if (FLAG_global_var_shortcuts) {
1567 for (int i = 0; i < var_count; i++) {
1568 AllocateDeclaredGlobal(isolate, vars[i].var());
1569 }
1570 }
1571
1572 // For now, function_ must be allocated at the very end. If it gets
1573 // allocated in the context, it must be the last slot in the context,
1574 // because of the current ScopeInfo implementation (see
1575 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
1576 if (function_ != nullptr) {
1577 AllocateNonParameterLocal(isolate, function_->proxy()->var());
1578 }
1579
1580 if (rest_parameter_ != nullptr) {
1581 AllocateNonParameterLocal(isolate, rest_parameter_);
1582 }
1583
1584 Variable* new_target_var =
1585 LookupLocal(ast_value_factory_->new_target_string());
1586 if (new_target_var != nullptr && MustAllocate(new_target_var)) {
1587 new_target_ = new_target_var;
1588 }
1589
1590 Variable* this_function_var =
1591 LookupLocal(ast_value_factory_->this_function_string());
1592 if (this_function_var != nullptr && MustAllocate(this_function_var)) {
1593 this_function_ = this_function_var;
1594 }
1595 }
1596
1597
1598 void Scope::AllocateVariablesRecursively(Isolate* isolate) {
1599 if (!already_resolved()) {
1600 num_stack_slots_ = 0;
1601 }
1602 // Allocate variables for inner scopes.
1603 for (int i = 0; i < inner_scopes_.length(); i++) {
1604 inner_scopes_[i]->AllocateVariablesRecursively(isolate);
1605 }
1606
1607 // If scope is already resolved, we still need to allocate
1608 // variables in inner scopes which might not had been resolved yet.
1609 if (already_resolved()) return;
1610 // The number of slots required for variables.
1611 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
1612
1613 // Allocate variables for this scope.
1614 // Parameters must be allocated first, if any.
1615 if (is_function_scope()) AllocateParameterLocals(isolate);
1616 if (has_this_declaration()) AllocateReceiver();
1617 AllocateNonParameterLocalsAndDeclaredGlobals(isolate);
1618
1619 // Force allocation of a context for this scope if necessary. For a 'with'
1620 // scope and for a function scope that makes an 'eval' call we need a context,
1621 // even if no local variables were statically allocated in the scope.
1622 // Likewise for modules.
1623 bool must_have_context =
1624 is_with_scope() || is_module_scope() ||
1625 (is_function_scope() && calls_sloppy_eval()) ||
1626 (is_block_scope() && is_declaration_scope() && calls_sloppy_eval());
1627
1628 // If we didn't allocate any locals in the local context, then we only
1629 // need the minimal number of slots if we must have a context.
1630 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) {
1631 num_heap_slots_ = 0;
1632 }
1633
1634 // Allocation done.
1635 DCHECK(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
1636 }
1637
1638
1639 void Scope::AllocateModules() {
1640 DCHECK(is_script_scope());
1641 DCHECK(!already_resolved());
1642 for (int i = 0; i < inner_scopes_.length(); i++) {
1643 Scope* scope = inner_scopes_.at(i);
1644 if (scope->is_module_scope()) {
1645 DCHECK(!scope->already_resolved());
1646 DCHECK(scope->module_descriptor_->IsFrozen());
1647 DCHECK_NULL(scope->module_var_);
1648 scope->module_var_ =
1649 NewTemporary(ast_value_factory_->dot_module_string());
1650 ++num_modules_;
1651 }
1652 }
1653 }
1654
1655
1656 int Scope::StackLocalCount() const {
1657 return num_stack_slots() -
1658 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0);
1659 }
1660
1661
1662 int Scope::ContextLocalCount() const {
1663 if (num_heap_slots() == 0) return 0;
1664 bool is_function_var_in_context =
1665 function_ != NULL && function_->proxy()->var()->IsContextSlot();
1666 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() -
1667 (is_function_var_in_context ? 1 : 0);
1668 }
1669
1670
1671 int Scope::ContextGlobalCount() const { return num_global_slots(); }
1672
1673 } // namespace internal
1674 } // namespace v8
OLDNEW
« no previous file with comments | « src/scopes.h ('k') | src/snapshot/serialize.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698