OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 class Scope: public ZoneObject { | 87 class Scope: public ZoneObject { |
88 public: | 88 public: |
89 // --------------------------------------------------------------------------- | 89 // --------------------------------------------------------------------------- |
90 // Construction | 90 // Construction |
91 | 91 |
92 enum Type { | 92 enum Type { |
93 EVAL_SCOPE, // The top-level scope for an eval source. | 93 EVAL_SCOPE, // The top-level scope for an eval source. |
94 FUNCTION_SCOPE, // The top-level scope for a function. | 94 FUNCTION_SCOPE, // The top-level scope for a function. |
95 GLOBAL_SCOPE, // The top-level scope for a program or a top-level eval. | 95 GLOBAL_SCOPE, // The top-level scope for a program or a top-level eval. |
96 CATCH_SCOPE, // The scope introduced by catch. | 96 CATCH_SCOPE, // The scope introduced by catch. |
97 BLOCK_SCOPE // The scope introduced by a new block. | 97 BLOCK_SCOPE, // The scope introduced by a new block. |
| 98 WITH_SCOPE // The scope introduced by with. |
98 }; | 99 }; |
99 | 100 |
100 Scope(Scope* outer_scope, Type type); | 101 Scope(Scope* outer_scope, Type type); |
101 | 102 |
102 // Compute top scope and allocate variables. For lazy compilation the top | 103 // Compute top scope and allocate variables. For lazy compilation the top |
103 // scope only contains the single lazily compiled function, so this | 104 // scope only contains the single lazily compiled function, so this |
104 // doesn't re-allocate variables repeatedly. | 105 // doesn't re-allocate variables repeatedly. |
105 static bool Analyze(CompilationInfo* info); | 106 static bool Analyze(CompilationInfo* info); |
106 | 107 |
107 static Scope* DeserializeScopeChain(CompilationInfo* info, | 108 static Scope* DeserializeScopeChain(CompilationInfo* info, |
108 Scope* innermost_scope); | 109 Scope* innermost_scope); |
109 | 110 |
110 // The scope name is only used for printing/debugging. | 111 // The scope name is only used for printing/debugging. |
111 void SetScopeName(Handle<String> scope_name) { scope_name_ = scope_name; } | 112 void SetScopeName(Handle<String> scope_name) { scope_name_ = scope_name; } |
112 | 113 |
113 void Initialize(bool inside_with); | 114 void Initialize(); |
114 | 115 |
115 // Checks if the block scope is redundant, i.e. it does not contain any | 116 // Checks if the block scope is redundant, i.e. it does not contain any |
116 // block scoped declarations. In that case it is removed from the scope | 117 // block scoped declarations. In that case it is removed from the scope |
117 // tree and its children are reparented. | 118 // tree and its children are reparented. |
118 Scope* FinalizeBlockScope(); | 119 Scope* FinalizeBlockScope(); |
119 | 120 |
120 // --------------------------------------------------------------------------- | 121 // --------------------------------------------------------------------------- |
121 // Declarations | 122 // Declarations |
122 | 123 |
123 // Lookup a variable in this scope. Returns the variable or NULL if not found. | 124 // Lookup a variable in this scope. Returns the variable or NULL if not found. |
(...skipping 18 matching lines...) Expand all Loading... |
142 Variable* DeclareLocal(Handle<String> name, Variable::Mode mode); | 143 Variable* DeclareLocal(Handle<String> name, Variable::Mode mode); |
143 | 144 |
144 // Declare an implicit global variable in this scope which must be a | 145 // Declare an implicit global variable in this scope which must be a |
145 // global scope. The variable was introduced (possibly from an inner | 146 // global scope. The variable was introduced (possibly from an inner |
146 // scope) by a reference to an unresolved variable with no intervening | 147 // scope) by a reference to an unresolved variable with no intervening |
147 // with statements or eval calls. | 148 // with statements or eval calls. |
148 Variable* DeclareGlobal(Handle<String> name); | 149 Variable* DeclareGlobal(Handle<String> name); |
149 | 150 |
150 // Create a new unresolved variable. | 151 // Create a new unresolved variable. |
151 VariableProxy* NewUnresolved(Handle<String> name, | 152 VariableProxy* NewUnresolved(Handle<String> name, |
152 bool inside_with, | |
153 int position = RelocInfo::kNoPosition); | 153 int position = RelocInfo::kNoPosition); |
154 | 154 |
155 // Remove a unresolved variable. During parsing, an unresolved variable | 155 // Remove a unresolved variable. During parsing, an unresolved variable |
156 // may have been added optimistically, but then only the variable name | 156 // may have been added optimistically, but then only the variable name |
157 // was used (typically for labels). If the variable was not declared, the | 157 // was used (typically for labels). If the variable was not declared, the |
158 // addition introduced a new unresolved variable which may end up being | 158 // addition introduced a new unresolved variable which may end up being |
159 // allocated globally as a "ghost" variable. RemoveUnresolved removes | 159 // allocated globally as a "ghost" variable. RemoveUnresolved removes |
160 // such a variable again if it was added; otherwise this is a no-op. | 160 // such a variable again if it was added; otherwise this is a no-op. |
161 void RemoveUnresolved(VariableProxy* var); | 161 void RemoveUnresolved(VariableProxy* var); |
162 | 162 |
(...skipping 29 matching lines...) Expand all Loading... |
192 // scope over a let binding of the same name. | 192 // scope over a let binding of the same name. |
193 Declaration* CheckConflictingVarDeclarations(); | 193 Declaration* CheckConflictingVarDeclarations(); |
194 | 194 |
195 // --------------------------------------------------------------------------- | 195 // --------------------------------------------------------------------------- |
196 // Scope-specific info. | 196 // Scope-specific info. |
197 | 197 |
198 // Inform the scope that the corresponding code contains a with statement. | 198 // Inform the scope that the corresponding code contains a with statement. |
199 void RecordWithStatement() { scope_contains_with_ = true; } | 199 void RecordWithStatement() { scope_contains_with_ = true; } |
200 | 200 |
201 // Inform the scope that the corresponding code contains an eval call. | 201 // Inform the scope that the corresponding code contains an eval call. |
202 void RecordEvalCall() { scope_calls_eval_ = true; } | 202 void RecordEvalCall() { if (!is_global_scope()) scope_calls_eval_ = true; } |
203 | 203 |
204 // Enable strict mode for the scope (unless disabled by a global flag). | 204 // Enable strict mode for the scope (unless disabled by a global flag). |
205 void EnableStrictMode() { | 205 void EnableStrictMode() { |
206 strict_mode_ = FLAG_strict_mode; | 206 strict_mode_ = FLAG_strict_mode; |
207 } | 207 } |
208 | 208 |
209 // --------------------------------------------------------------------------- | 209 // --------------------------------------------------------------------------- |
210 // Predicates. | 210 // Predicates. |
211 | 211 |
212 // Specific scope types. | 212 // Specific scope types. |
213 bool is_eval_scope() const { return type_ == EVAL_SCOPE; } | 213 bool is_eval_scope() const { return type_ == EVAL_SCOPE; } |
214 bool is_function_scope() const { return type_ == FUNCTION_SCOPE; } | 214 bool is_function_scope() const { return type_ == FUNCTION_SCOPE; } |
215 bool is_global_scope() const { return type_ == GLOBAL_SCOPE; } | 215 bool is_global_scope() const { return type_ == GLOBAL_SCOPE; } |
216 bool is_catch_scope() const { return type_ == CATCH_SCOPE; } | 216 bool is_catch_scope() const { return type_ == CATCH_SCOPE; } |
217 bool is_block_scope() const { return type_ == BLOCK_SCOPE; } | 217 bool is_block_scope() const { return type_ == BLOCK_SCOPE; } |
| 218 bool is_with_scope() const { return type_ == WITH_SCOPE; } |
| 219 bool is_declaration_scope() const { |
| 220 return is_eval_scope() || is_function_scope() || is_global_scope(); |
| 221 } |
218 bool is_strict_mode() const { return strict_mode_; } | 222 bool is_strict_mode() const { return strict_mode_; } |
219 bool is_strict_mode_eval_scope() const { | 223 bool is_strict_mode_eval_scope() const { |
220 return is_eval_scope() && is_strict_mode(); | 224 return is_eval_scope() && is_strict_mode(); |
221 } | 225 } |
222 | 226 |
223 // Information about which scopes calls eval. | 227 // Information about which scopes calls eval. |
224 bool calls_eval() const { return scope_calls_eval_; } | 228 bool calls_eval() const { return scope_calls_eval_; } |
225 bool outer_scope_calls_eval() const { return outer_scope_calls_eval_; } | 229 bool calls_non_strict_eval() { |
| 230 return scope_calls_eval_ && !is_strict_mode(); |
| 231 } |
226 bool outer_scope_calls_non_strict_eval() const { | 232 bool outer_scope_calls_non_strict_eval() const { |
227 return outer_scope_calls_non_strict_eval_; | 233 return outer_scope_calls_non_strict_eval_; |
228 } | 234 } |
229 | 235 |
230 // Is this scope inside a with statement. | 236 // Is this scope inside a with statement. |
231 bool inside_with() const { return scope_inside_with_; } | 237 bool inside_with() const { return scope_inside_with_; } |
232 // Does this scope contain a with statement. | 238 // Does this scope contain a with statement. |
233 bool contains_with() const { return scope_contains_with_; } | 239 bool contains_with() const { return scope_contains_with_; } |
234 | 240 |
235 // The scope immediately surrounding this scope, or NULL. | 241 // The scope immediately surrounding this scope, or NULL. |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 bool scope_inside_with_; | 382 bool scope_inside_with_; |
377 // This scope contains a 'with' statement. | 383 // This scope contains a 'with' statement. |
378 bool scope_contains_with_; | 384 bool scope_contains_with_; |
379 // This scope or a nested catch scope or with scope contain an 'eval' call. At | 385 // This scope or a nested catch scope or with scope contain an 'eval' call. At |
380 // the 'eval' call site this scope is the declaration scope. | 386 // the 'eval' call site this scope is the declaration scope. |
381 bool scope_calls_eval_; | 387 bool scope_calls_eval_; |
382 // This scope is a strict mode scope. | 388 // This scope is a strict mode scope. |
383 bool strict_mode_; | 389 bool strict_mode_; |
384 | 390 |
385 // Computed via PropagateScopeInfo. | 391 // Computed via PropagateScopeInfo. |
386 bool outer_scope_calls_eval_; | |
387 bool outer_scope_calls_non_strict_eval_; | 392 bool outer_scope_calls_non_strict_eval_; |
388 bool inner_scope_calls_eval_; | 393 bool inner_scope_calls_eval_; |
389 bool outer_scope_is_eval_scope_; | |
390 bool force_eager_compilation_; | 394 bool force_eager_compilation_; |
391 | 395 |
392 // True if it doesn't need scope resolution (e.g., if the scope was | 396 // True if it doesn't need scope resolution (e.g., if the scope was |
393 // constructed based on a serialized scope info or a catch context). | 397 // constructed based on a serialized scope info or a catch context). |
394 bool already_resolved_; | 398 bool already_resolved_; |
395 | 399 |
396 // Computed as variables are declared. | 400 // Computed as variables are declared. |
397 int num_var_or_const_; | 401 int num_var_or_const_; |
398 | 402 |
399 // Computed via AllocateVariables; function scopes only. | 403 // Computed via AllocateVariables; function, block and catch scopes only. |
400 int num_stack_slots_; | 404 int num_stack_slots_; |
401 int num_heap_slots_; | 405 int num_heap_slots_; |
402 | 406 |
403 // Serialized scopes support. | 407 // Serialized scopes support. |
404 Handle<SerializedScopeInfo> scope_info_; | 408 Handle<SerializedScopeInfo> scope_info_; |
405 bool already_resolved() { return already_resolved_; } | 409 bool already_resolved() { return already_resolved_; } |
406 | 410 |
407 // Create a non-local variable with a given name. | 411 // Create a non-local variable with a given name. |
408 // These variables are looked up dynamically at runtime. | 412 // These variables are looked up dynamically at runtime. |
409 Variable* NonLocal(Handle<String> name, Variable::Mode mode); | 413 Variable* NonLocal(Handle<String> name, Variable::Mode mode); |
410 | 414 |
411 // Variable resolution. | 415 // Variable resolution. |
| 416 // Possible results of a recursive variable lookup telling if and how a |
| 417 // variable is bound. These are returned in the output parameter *binding_kind |
| 418 // of the LookupRecursive function. |
| 419 enum BindingKind { |
| 420 // The variable reference could be statically resolved to a variable binding |
| 421 // which is returned. There is no 'with' statement between the reference and |
| 422 // the binding and no scope between the reference scope (inclusive) and |
| 423 // binding scope (exclusive) makes a non-strict 'eval' call. |
| 424 BOUND, |
| 425 |
| 426 // The variable reference could be statically resolved to a variable binding |
| 427 // which is returned. There is no 'with' statement between the reference and |
| 428 // the binding, but some scope between the reference scope (inclusive) and |
| 429 // binding scope (exclusive) makes a non-strict 'eval' call, that might |
| 430 // possibly introduce variable bindings shadowing the found one. Thus the |
| 431 // found variable binding is just a guess. |
| 432 BOUND_EVAL_SHADOWED, |
| 433 |
| 434 // The variable reference could not be statically resolved to any binding |
| 435 // and thus should be considered referencing a global variable. NULL is |
| 436 // returend. The variable reference is not inside any 'with' statement and |
| 437 // no scope between the reference scope (inclusive) and global scope |
| 438 // (exclusive) makes a non-strict 'eval' call. |
| 439 UNBOUND, |
| 440 |
| 441 // The variable reference could not be statically resolved to any binding |
| 442 // NULL is returned. The variable reference is not inside any 'with' |
| 443 // statement, but some scope between the reference scope (inclusive) and |
| 444 // global scope (exclusive) makes a non-strict 'eval' call, that might |
| 445 // possibly introduce a variable binding. Thus the reference should be |
| 446 // considered referencing a global variable unless it is shadowed by an |
| 447 // 'eval' introduced binding. |
| 448 UNBOUND_EVAL_SHADOWED, |
| 449 |
| 450 // The variable could not be statically resolved and needs to be looked up |
| 451 // dynamically. NULL is returned. There are two possible reasons: |
| 452 // * A 'with' statement has been encountered and there is no variable |
| 453 // binding for the name between the variable reference and the 'with'. |
| 454 // The variable potentially references a property of the 'with' object. |
| 455 // * The code is being executed as part of a call to 'eval' and the calling |
| 456 // context chain contains either a variable binding for the name or it |
| 457 // contains a 'with' context. |
| 458 DYNAMIC_LOOKUP |
| 459 }; |
| 460 |
| 461 // Lookup a variable reference given by name recursively starting with this |
| 462 // scope. If the code is executed because of a call to 'eval', the context |
| 463 // parameter should be set to the calling context of 'eval'. |
412 Variable* LookupRecursive(Handle<String> name, | 464 Variable* LookupRecursive(Handle<String> name, |
413 bool from_inner_function, | 465 Handle<Context> context, |
414 Variable** invalidated_local); | 466 BindingKind* binding_kind); |
415 void ResolveVariable(Scope* global_scope, | 467 void ResolveVariable(Scope* global_scope, |
416 Handle<Context> context, | 468 Handle<Context> context, |
417 VariableProxy* proxy); | 469 VariableProxy* proxy); |
418 void ResolveVariablesRecursively(Scope* global_scope, | 470 void ResolveVariablesRecursively(Scope* global_scope, |
419 Handle<Context> context); | 471 Handle<Context> context); |
420 | 472 |
421 // Scope analysis. | 473 // Scope analysis. |
422 bool PropagateScopeInfo(bool outer_scope_calls_eval, | 474 bool PropagateScopeInfo(bool outer_scope_calls_non_strict_eval); |
423 bool outer_scope_calls_non_strict_eval, | |
424 bool outer_scope_is_eval_scope); | |
425 bool HasTrivialContext() const; | 475 bool HasTrivialContext() const; |
426 | 476 |
427 // Predicates. | 477 // Predicates. |
428 bool MustAllocate(Variable* var); | 478 bool MustAllocate(Variable* var); |
429 bool MustAllocateInContext(Variable* var); | 479 bool MustAllocateInContext(Variable* var); |
430 bool HasArgumentsParameter(); | 480 bool HasArgumentsParameter(); |
431 | 481 |
432 // Variable allocation. | 482 // Variable allocation. |
433 void AllocateStackSlot(Variable* var); | 483 void AllocateStackSlot(Variable* var); |
434 void AllocateHeapSlot(Variable* var); | 484 void AllocateHeapSlot(Variable* var); |
435 void AllocateParameterLocals(); | 485 void AllocateParameterLocals(); |
436 void AllocateNonParameterLocal(Variable* var); | 486 void AllocateNonParameterLocal(Variable* var); |
437 void AllocateNonParameterLocals(); | 487 void AllocateNonParameterLocals(); |
438 void AllocateVariablesRecursively(); | 488 void AllocateVariablesRecursively(); |
439 | 489 |
440 private: | 490 private: |
441 // Construct a function or block scope based on the scope info. | 491 // Construct a scope based on the scope info. |
442 Scope(Scope* inner_scope, Type type, Handle<SerializedScopeInfo> scope_info); | 492 Scope(Scope* inner_scope, Type type, Handle<SerializedScopeInfo> scope_info); |
443 | 493 |
444 // Construct a catch scope with a binding for the name. | 494 // Construct a catch scope with a binding for the name. |
445 Scope(Scope* inner_scope, Handle<String> catch_variable_name); | 495 Scope(Scope* inner_scope, Handle<String> catch_variable_name); |
446 | 496 |
447 void AddInnerScope(Scope* inner_scope) { | 497 void AddInnerScope(Scope* inner_scope) { |
448 if (inner_scope != NULL) { | 498 if (inner_scope != NULL) { |
449 inner_scopes_.Add(inner_scope); | 499 inner_scopes_.Add(inner_scope); |
450 inner_scope->outer_scope_ = this; | 500 inner_scope->outer_scope_ = this; |
451 } | 501 } |
452 } | 502 } |
453 | 503 |
454 void SetDefaults(Type type, | 504 void SetDefaults(Type type, |
455 Scope* outer_scope, | 505 Scope* outer_scope, |
456 Handle<SerializedScopeInfo> scope_info); | 506 Handle<SerializedScopeInfo> scope_info); |
457 }; | 507 }; |
458 | 508 |
459 } } // namespace v8::internal | 509 } } // namespace v8::internal |
460 | 510 |
461 #endif // V8_SCOPES_H_ | 511 #endif // V8_SCOPES_H_ |
OLD | NEW |