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

Side by Side Diff: src/scopes.h

Issue 7904008: Introduce with scope and rework variable resolution. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Latest version. Created 9 years, 3 months 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 | Annotate | Revision Log
« no previous file with comments | « src/parser.cc ('k') | src/scopes.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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_
OLDNEW
« no previous file with comments | « src/parser.cc ('k') | src/scopes.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698