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

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: Removed tracking of 'with' from parser and variable proxies. 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
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.
412 Variable* LookupRecursive(Handle<String> name, 416 // Possible results of a recursive variable lookup.
413 bool from_inner_function, 417 enum LookupResult {
Kevin Millikin (Chromium) 2011/09/16 12:58:19 This sounds like a silly request, but: we already
Steven 2011/09/16 18:29:52 Used BindingKind for lack of a better name. On 201
414 Variable** invalidated_local); 418 // The variable reference could be statically resolved to a variable
419 // binding which is return in the output parameter *var. There is no
420 // 'with' statement between the reference and the binding and no scope
421 // between the reference scope (inclusive) and binding scope (exclusive)
422 // makes a non-strict 'eval' call.
423 BOUND,
424
425 // The variable reference could be statically resolved to a variable
426 // binding which is return in the output parameter *var. There is no
427 // 'with' statement between the reference and the binding, but some scope
428 // between the reference scope (inclusive) and binding scope (exclusive)
429 // makes a non-strict 'eval' call, that might possibly introduce variable
430 // bindings shadowing the found one. Thus the found variable binding is
431 // 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. No variable
436 // binding is returned in the output parameter *var. The variable reference
437 // is not inside any 'with' statement and no scope between the reference
438 // scope (inclusive) and global scope (exclusive) makes a non-strict 'eval'
439 // call.
440 UNBOUND,
441
442 // The variable reference could not be statically resolved to any binding.
443 // No variable binding is returned in the output parameter *var. The
444 // variable reference is not inside any 'with' statement, but some scope
445 // between the reference scope (inclusive) and global scope (exclusive)
446 // makes a non-strict 'eval' call, that might possibly introduce a variable
447 // binding. Thus the reference should be considered referencing a global
448 // variable unless it is shadowed by an 'eval' introduced binding.
449 UNBOUND_EVAL_SHADOWED,
450
451 // The variable could not be statically resolved and needs to be looked up
452 // dynamically. There are two possible reasons:
453 // * A 'with' statement has been encountered and there is no variable
454 // binding for the name between the variable reference and the 'with'.
455 // The variable potentially references a property of the 'with' object.
456 // * The code is being executed as part of a call to 'eval' and the calling
457 // context chain contains either a variable binding for the name or it
458 // contains a 'with' context.
459 DYNAMIC_LOOKUP
460 };
461
462 // Lookup a variable reference given by name recursively starting with this
463 // scope. If the code is executed because of a call to 'eval', the context
464 // parameter should be set to the calling context of 'eval'.
465 LookupResult LookupRecursive(Handle<String> name,
466 Handle<Context> context,
467 Variable** var);
415 void ResolveVariable(Scope* global_scope, 468 void ResolveVariable(Scope* global_scope,
416 Handle<Context> context, 469 Handle<Context> context,
417 VariableProxy* proxy); 470 VariableProxy* proxy);
418 void ResolveVariablesRecursively(Scope* global_scope, 471 void ResolveVariablesRecursively(Scope* global_scope,
419 Handle<Context> context); 472 Handle<Context> context);
420 473
421 // Scope analysis. 474 // Scope analysis.
422 bool PropagateScopeInfo(bool outer_scope_calls_eval, 475 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; 476 bool HasTrivialContext() const;
426 477
427 // Predicates. 478 // Predicates.
428 bool MustAllocate(Variable* var); 479 bool MustAllocate(Variable* var);
429 bool MustAllocateInContext(Variable* var); 480 bool MustAllocateInContext(Variable* var);
430 bool HasArgumentsParameter(); 481 bool HasArgumentsParameter();
431 482
432 // Variable allocation. 483 // Variable allocation.
433 void AllocateStackSlot(Variable* var); 484 void AllocateStackSlot(Variable* var);
434 void AllocateHeapSlot(Variable* var); 485 void AllocateHeapSlot(Variable* var);
435 void AllocateParameterLocals(); 486 void AllocateParameterLocals();
436 void AllocateNonParameterLocal(Variable* var); 487 void AllocateNonParameterLocal(Variable* var);
437 void AllocateNonParameterLocals(); 488 void AllocateNonParameterLocals();
438 void AllocateVariablesRecursively(); 489 void AllocateVariablesRecursively();
439 490
440 private: 491 private:
441 // Construct a function or block scope based on the scope info. 492 // Construct a scope based on the scope info.
442 Scope(Scope* inner_scope, Type type, Handle<SerializedScopeInfo> scope_info); 493 Scope(Scope* inner_scope, Type type, Handle<SerializedScopeInfo> scope_info);
443 494
444 // Construct a catch scope with a binding for the name. 495 // Construct a catch scope with a binding for the name.
445 Scope(Scope* inner_scope, Handle<String> catch_variable_name); 496 Scope(Scope* inner_scope, Handle<String> catch_variable_name);
446 497
447 void AddInnerScope(Scope* inner_scope) { 498 void AddInnerScope(Scope* inner_scope) {
448 if (inner_scope != NULL) { 499 if (inner_scope != NULL) {
449 inner_scopes_.Add(inner_scope); 500 inner_scopes_.Add(inner_scope);
450 inner_scope->outer_scope_ = this; 501 inner_scope->outer_scope_ = this;
451 } 502 }
452 } 503 }
453 504
454 void SetDefaults(Type type, 505 void SetDefaults(Type type,
455 Scope* outer_scope, 506 Scope* outer_scope,
456 Handle<SerializedScopeInfo> scope_info); 507 Handle<SerializedScopeInfo> scope_info);
457 }; 508 };
458 509
459 } } // namespace v8::internal 510 } } // namespace v8::internal
460 511
461 #endif // V8_SCOPES_H_ 512 #endif // V8_SCOPES_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698