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

Side by Side Diff: src/scopes.cc

Issue 8404030: Version 3.7.1 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 9 years, 1 month 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/scopes.h ('k') | src/serialize.h » ('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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 } 107 }
108 return NULL; 108 return NULL;
109 } 109 }
110 110
111 111
112 // ---------------------------------------------------------------------------- 112 // ----------------------------------------------------------------------------
113 // Implementation of Scope 113 // Implementation of Scope
114 114
115 115
116 // Dummy constructor 116 // Dummy constructor
117 Scope::Scope(Type type) 117 Scope::Scope(ScopeType type)
118 : isolate_(Isolate::Current()), 118 : isolate_(Isolate::Current()),
119 inner_scopes_(0), 119 inner_scopes_(0),
120 variables_(false), 120 variables_(false),
121 temps_(0), 121 temps_(0),
122 params_(0), 122 params_(0),
123 unresolved_(0), 123 unresolved_(0),
124 decls_(0), 124 decls_(0),
125 already_resolved_(false) { 125 already_resolved_(false) {
126 SetDefaults(type, NULL, Handle<SerializedScopeInfo>::null()); 126 SetDefaults(type, NULL, Handle<SerializedScopeInfo>::null());
127 } 127 }
128 128
129 129
130 Scope::Scope(Scope* outer_scope, Type type) 130 Scope::Scope(Scope* outer_scope, ScopeType type)
131 : isolate_(Isolate::Current()), 131 : isolate_(Isolate::Current()),
132 inner_scopes_(4), 132 inner_scopes_(4),
133 variables_(), 133 variables_(),
134 temps_(4), 134 temps_(4),
135 params_(4), 135 params_(4),
136 unresolved_(16), 136 unresolved_(16),
137 decls_(4), 137 decls_(4),
138 already_resolved_(false) { 138 already_resolved_(false) {
139 SetDefaults(type, outer_scope, Handle<SerializedScopeInfo>::null()); 139 SetDefaults(type, outer_scope, Handle<SerializedScopeInfo>::null());
140 // At some point we might want to provide outer scopes to 140 // At some point we might want to provide outer scopes to
141 // eval scopes (by walking the stack and reading the scope info). 141 // eval scopes (by walking the stack and reading the scope info).
142 // In that case, the ASSERT below needs to be adjusted. 142 // In that case, the ASSERT below needs to be adjusted.
143 ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL)); 143 ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL));
144 ASSERT(!HasIllegalRedeclaration()); 144 ASSERT(!HasIllegalRedeclaration());
145 } 145 }
146 146
147 147
148 Scope::Scope(Scope* inner_scope, 148 Scope::Scope(Scope* inner_scope,
149 Type type, 149 ScopeType type,
150 Handle<SerializedScopeInfo> scope_info) 150 Handle<SerializedScopeInfo> scope_info)
151 : isolate_(Isolate::Current()), 151 : isolate_(Isolate::Current()),
152 inner_scopes_(4), 152 inner_scopes_(4),
153 variables_(), 153 variables_(),
154 temps_(4), 154 temps_(4),
155 params_(4), 155 params_(4),
156 unresolved_(16), 156 unresolved_(16),
157 decls_(4), 157 decls_(4),
158 already_resolved_(true) { 158 already_resolved_(true) {
159 ASSERT(!scope_info.is_null());
160 SetDefaults(type, NULL, scope_info); 159 SetDefaults(type, NULL, scope_info);
161 if (scope_info->HasHeapAllocatedLocals()) { 160 if (!scope_info.is_null() && scope_info->HasHeapAllocatedLocals()) {
162 num_heap_slots_ = scope_info_->NumberOfContextSlots(); 161 num_heap_slots_ = scope_info_->NumberOfContextSlots();
163 } 162 }
164 AddInnerScope(inner_scope); 163 AddInnerScope(inner_scope);
165 } 164 }
166 165
167 166
168 Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name) 167 Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name)
169 : isolate_(Isolate::Current()), 168 : isolate_(Isolate::Current()),
170 inner_scopes_(1), 169 inner_scopes_(1),
171 variables_(), 170 variables_(),
172 temps_(0), 171 temps_(0),
173 params_(0), 172 params_(0),
174 unresolved_(0), 173 unresolved_(0),
175 decls_(0), 174 decls_(0),
176 already_resolved_(true) { 175 already_resolved_(true) {
177 SetDefaults(CATCH_SCOPE, NULL, Handle<SerializedScopeInfo>::null()); 176 SetDefaults(CATCH_SCOPE, NULL, Handle<SerializedScopeInfo>::null());
178 AddInnerScope(inner_scope); 177 AddInnerScope(inner_scope);
179 ++num_var_or_const_; 178 ++num_var_or_const_;
180 Variable* variable = variables_.Declare(this, 179 Variable* variable = variables_.Declare(this,
181 catch_variable_name, 180 catch_variable_name,
182 VAR, 181 VAR,
183 true, // Valid left-hand side. 182 true, // Valid left-hand side.
184 Variable::NORMAL); 183 Variable::NORMAL);
185 AllocateHeapSlot(variable); 184 AllocateHeapSlot(variable);
186 } 185 }
187 186
188 187
189 void Scope::SetDefaults(Type type, 188 void Scope::SetDefaults(ScopeType type,
190 Scope* outer_scope, 189 Scope* outer_scope,
191 Handle<SerializedScopeInfo> scope_info) { 190 Handle<SerializedScopeInfo> scope_info) {
192 outer_scope_ = outer_scope; 191 outer_scope_ = outer_scope;
193 type_ = type; 192 type_ = type;
194 scope_name_ = isolate_->factory()->empty_symbol(); 193 scope_name_ = isolate_->factory()->empty_symbol();
195 dynamics_ = NULL; 194 dynamics_ = NULL;
196 receiver_ = NULL; 195 receiver_ = NULL;
197 function_ = NULL; 196 function_ = NULL;
198 arguments_ = NULL; 197 arguments_ = NULL;
199 illegal_redecl_ = NULL; 198 illegal_redecl_ = NULL;
200 scope_inside_with_ = false; 199 scope_inside_with_ = false;
201 scope_contains_with_ = false; 200 scope_contains_with_ = false;
202 scope_calls_eval_ = false; 201 scope_calls_eval_ = false;
203 // Inherit the strict mode from the parent scope. 202 // Inherit the strict mode from the parent scope.
204 strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_; 203 strict_mode_flag_ = (outer_scope != NULL)
205 outer_scope_calls_eval_ = false; 204 ? outer_scope->strict_mode_flag_ : kNonStrictMode;
206 outer_scope_calls_non_strict_eval_ = false; 205 outer_scope_calls_non_strict_eval_ = false;
207 inner_scope_calls_eval_ = false; 206 inner_scope_calls_eval_ = false;
208 outer_scope_is_eval_scope_ = false;
209 force_eager_compilation_ = false; 207 force_eager_compilation_ = false;
210 num_var_or_const_ = 0; 208 num_var_or_const_ = 0;
211 num_stack_slots_ = 0; 209 num_stack_slots_ = 0;
212 num_heap_slots_ = 0; 210 num_heap_slots_ = 0;
213 scope_info_ = scope_info; 211 scope_info_ = scope_info;
212 start_position_ = RelocInfo::kNoPosition;
213 end_position_ = RelocInfo::kNoPosition;
214 } 214 }
215 215
216 216
217 Scope* Scope::DeserializeScopeChain(CompilationInfo* info, 217 Scope* Scope::DeserializeScopeChain(CompilationInfo* info,
218 Scope* global_scope) { 218 Scope* global_scope) {
219 // Reconstruct the outer scope chain from a closure's context chain. 219 // Reconstruct the outer scope chain from a closure's context chain.
220 ASSERT(!info->closure().is_null()); 220 ASSERT(!info->closure().is_null());
221 Context* context = info->closure()->context(); 221 Context* context = info->closure()->context();
222 Scope* current_scope = NULL; 222 Scope* current_scope = NULL;
223 Scope* innermost_scope = NULL; 223 Scope* innermost_scope = NULL;
224 bool contains_with = false; 224 bool contains_with = false;
225 while (!context->IsGlobalContext()) { 225 while (!context->IsGlobalContext()) {
226 if (context->IsWithContext()) { 226 if (context->IsWithContext()) {
227 Scope* with_scope = new Scope(current_scope, WITH_SCOPE,
228 Handle<SerializedScopeInfo>::null());
229 current_scope = with_scope;
227 // All the inner scopes are inside a with. 230 // All the inner scopes are inside a with.
228 contains_with = true; 231 contains_with = true;
229 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) { 232 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) {
230 s->scope_inside_with_ = true; 233 s->scope_inside_with_ = true;
231 } 234 }
235 } else if (context->IsFunctionContext()) {
236 SerializedScopeInfo* scope_info =
237 context->closure()->shared()->scope_info();
238 current_scope = new Scope(current_scope, FUNCTION_SCOPE,
239 Handle<SerializedScopeInfo>(scope_info));
240 } else if (context->IsBlockContext()) {
241 SerializedScopeInfo* scope_info =
242 SerializedScopeInfo::cast(context->extension());
243 current_scope = new Scope(current_scope, BLOCK_SCOPE,
244 Handle<SerializedScopeInfo>(scope_info));
232 } else { 245 } else {
233 if (context->IsFunctionContext()) { 246 ASSERT(context->IsCatchContext());
234 SerializedScopeInfo* scope_info = 247 String* name = String::cast(context->extension());
235 context->closure()->shared()->scope_info(); 248 current_scope = new Scope(current_scope, Handle<String>(name));
236 current_scope = new Scope(current_scope, FUNCTION_SCOPE,
237 Handle<SerializedScopeInfo>(scope_info));
238 } else if (context->IsBlockContext()) {
239 SerializedScopeInfo* scope_info =
240 SerializedScopeInfo::cast(context->extension());
241 current_scope = new Scope(current_scope, BLOCK_SCOPE,
242 Handle<SerializedScopeInfo>(scope_info));
243 } else {
244 ASSERT(context->IsCatchContext());
245 String* name = String::cast(context->extension());
246 current_scope = new Scope(current_scope, Handle<String>(name));
247 }
248 if (contains_with) current_scope->RecordWithStatement();
249 if (innermost_scope == NULL) innermost_scope = current_scope;
250 } 249 }
250 if (contains_with) current_scope->RecordWithStatement();
251 if (innermost_scope == NULL) innermost_scope = current_scope;
251 252
252 // Forget about a with when we move to a context for a different function. 253 // Forget about a with when we move to a context for a different function.
253 if (context->previous()->closure() != context->closure()) { 254 if (context->previous()->closure() != context->closure()) {
254 contains_with = false; 255 contains_with = false;
255 } 256 }
256 context = context->previous(); 257 context = context->previous();
257 } 258 }
258 259
259 global_scope->AddInnerScope(current_scope); 260 global_scope->AddInnerScope(current_scope);
260 return (innermost_scope == NULL) ? global_scope : innermost_scope; 261 return (innermost_scope == NULL) ? global_scope : innermost_scope;
(...skipping 13 matching lines...) Expand all
274 : FLAG_print_scopes) { 275 : FLAG_print_scopes) {
275 info->function()->scope()->Print(); 276 info->function()->scope()->Print();
276 } 277 }
277 #endif 278 #endif
278 279
279 info->SetScope(info->function()->scope()); 280 info->SetScope(info->function()->scope());
280 return true; // Can not fail. 281 return true; // Can not fail.
281 } 282 }
282 283
283 284
284 void Scope::Initialize(bool inside_with) { 285 void Scope::Initialize() {
285 ASSERT(!already_resolved()); 286 ASSERT(!already_resolved());
286 287
287 // Add this scope as a new inner scope of the outer scope. 288 // Add this scope as a new inner scope of the outer scope.
288 if (outer_scope_ != NULL) { 289 if (outer_scope_ != NULL) {
289 outer_scope_->inner_scopes_.Add(this); 290 outer_scope_->inner_scopes_.Add(this);
290 scope_inside_with_ = outer_scope_->scope_inside_with_ || inside_with; 291 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope();
291 } else { 292 } else {
292 scope_inside_with_ = inside_with; 293 scope_inside_with_ = is_with_scope();
293 } 294 }
294 295
295 // Declare convenience variables. 296 // Declare convenience variables.
296 // Declare and allocate receiver (even for the global scope, and even 297 // Declare and allocate receiver (even for the global scope, and even
297 // if naccesses_ == 0). 298 // if naccesses_ == 0).
298 // NOTE: When loading parameters in the global scope, we must take 299 // NOTE: When loading parameters in the global scope, we must take
299 // care not to access them as properties of the global object, but 300 // care not to access them as properties of the global object, but
300 // instead load them directly from the stack. Currently, the only 301 // instead load them directly from the stack. Currently, the only
301 // such parameter is 'this' which is passed on the stack when 302 // such parameter is 'this' which is passed on the stack when
302 // invoking scripts 303 // invoking scripts
303 if (is_catch_scope() || is_block_scope()) { 304 if (is_declaration_scope()) {
304 ASSERT(outer_scope() != NULL);
305 receiver_ = outer_scope()->receiver();
306 } else {
307 ASSERT(is_function_scope() ||
308 is_global_scope() ||
309 is_eval_scope());
310 Variable* var = 305 Variable* var =
311 variables_.Declare(this, 306 variables_.Declare(this,
312 isolate_->factory()->this_symbol(), 307 isolate_->factory()->this_symbol(),
313 VAR, 308 VAR,
314 false, 309 false,
315 Variable::THIS); 310 Variable::THIS);
316 var->AllocateTo(Variable::PARAMETER, -1); 311 var->AllocateTo(Variable::PARAMETER, -1);
317 receiver_ = var; 312 receiver_ = var;
313 } else {
314 ASSERT(outer_scope() != NULL);
315 receiver_ = outer_scope()->receiver();
318 } 316 }
319 317
320 if (is_function_scope()) { 318 if (is_function_scope()) {
321 // Declare 'arguments' variable which exists in all functions. 319 // Declare 'arguments' variable which exists in all functions.
322 // Note that it might never be accessed, in which case it won't be 320 // Note that it might never be accessed, in which case it won't be
323 // allocated during variable allocation. 321 // allocated during variable allocation.
324 variables_.Declare(this, 322 variables_.Declare(this,
325 isolate_->factory()->arguments_symbol(), 323 isolate_->factory()->arguments_symbol(),
326 VAR, 324 VAR,
327 true, 325 true,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 372
375 // Check context slot lookup. 373 // Check context slot lookup.
376 VariableMode mode; 374 VariableMode mode;
377 int index = scope_info_->ContextSlotIndex(*name, &mode); 375 int index = scope_info_->ContextSlotIndex(*name, &mode);
378 if (index < 0) { 376 if (index < 0) {
379 // Check parameters. 377 // Check parameters.
380 mode = VAR; 378 mode = VAR;
381 index = scope_info_->ParameterIndex(*name); 379 index = scope_info_->ParameterIndex(*name);
382 if (index < 0) { 380 if (index < 0) {
383 // Check the function name. 381 // Check the function name.
384 index = scope_info_->FunctionContextSlotIndex(*name); 382 index = scope_info_->FunctionContextSlotIndex(*name, NULL);
385 if (index < 0) return NULL; 383 if (index < 0) return NULL;
386 } 384 }
387 } 385 }
388 386
389 Variable* var = 387 Variable* var =
390 variables_.Declare(this, name, mode, true, Variable::NORMAL); 388 variables_.Declare(this, name, mode, true, Variable::NORMAL);
391 var->AllocateTo(Variable::CONTEXT, index); 389 var->AllocateTo(Variable::CONTEXT, index);
392 return var; 390 return var;
393 } 391 }
394 392
395 393
396 Variable* Scope::Lookup(Handle<String> name) { 394 Variable* Scope::Lookup(Handle<String> name) {
397 for (Scope* scope = this; 395 for (Scope* scope = this;
398 scope != NULL; 396 scope != NULL;
399 scope = scope->outer_scope()) { 397 scope = scope->outer_scope()) {
400 Variable* var = scope->LocalLookup(name); 398 Variable* var = scope->LocalLookup(name);
401 if (var != NULL) return var; 399 if (var != NULL) return var;
402 } 400 }
403 return NULL; 401 return NULL;
404 } 402 }
405 403
406 404
407 Variable* Scope::DeclareFunctionVar(Handle<String> name) { 405 Variable* Scope::DeclareFunctionVar(Handle<String> name, VariableMode mode) {
408 ASSERT(is_function_scope() && function_ == NULL); 406 ASSERT(is_function_scope() && function_ == NULL);
409 Variable* function_var = 407 Variable* function_var =
410 new Variable(this, name, CONST, true, Variable::NORMAL); 408 new Variable(this, name, mode, true, Variable::NORMAL);
411 function_ = new(isolate_->zone()) VariableProxy(isolate_, function_var); 409 function_ = new(isolate_->zone()) VariableProxy(isolate_, function_var);
412 return function_var; 410 return function_var;
413 } 411 }
414 412
415 413
416 void Scope::DeclareParameter(Handle<String> name, VariableMode mode) { 414 void Scope::DeclareParameter(Handle<String> name, VariableMode mode) {
417 ASSERT(!already_resolved()); 415 ASSERT(!already_resolved());
418 ASSERT(is_function_scope()); 416 ASSERT(is_function_scope());
419 Variable* var = 417 Variable* var =
420 variables_.Declare(this, name, mode, true, Variable::NORMAL); 418 variables_.Declare(this, name, mode, true, Variable::NORMAL);
421 params_.Add(var); 419 params_.Add(var);
422 } 420 }
423 421
424 422
425 Variable* Scope::DeclareLocal(Handle<String> name, VariableMode mode) { 423 Variable* Scope::DeclareLocal(Handle<String> name, VariableMode mode) {
426 ASSERT(!already_resolved()); 424 ASSERT(!already_resolved());
427 // This function handles VAR and CONST modes. DYNAMIC variables are 425 // This function handles VAR and CONST modes. DYNAMIC variables are
428 // introduces during variable allocation, INTERNAL variables are allocated 426 // introduces during variable allocation, INTERNAL variables are allocated
429 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). 427 // explicitly, and TEMPORARY variables are allocated via NewTemporary().
430 ASSERT(mode == VAR || mode == CONST || mode == LET); 428 ASSERT(mode == VAR ||
429 mode == CONST ||
430 mode == CONST_HARMONY ||
431 mode == LET);
431 ++num_var_or_const_; 432 ++num_var_or_const_;
432 return variables_.Declare(this, name, mode, true, Variable::NORMAL); 433 return variables_.Declare(this, name, mode, true, Variable::NORMAL);
433 } 434 }
434 435
435 436
436 Variable* Scope::DeclareGlobal(Handle<String> name) { 437 Variable* Scope::DeclareGlobal(Handle<String> name) {
437 ASSERT(is_global_scope()); 438 ASSERT(is_global_scope());
438 return variables_.Declare(this, name, DYNAMIC_GLOBAL, 439 return variables_.Declare(this, name, DYNAMIC_GLOBAL,
439 true, 440 true,
440 Variable::NORMAL); 441 Variable::NORMAL);
441 } 442 }
442 443
443 444
444 VariableProxy* Scope::NewUnresolved(Handle<String> name, 445 VariableProxy* Scope::NewUnresolved(Handle<String> name, int position) {
445 bool inside_with,
446 int position) {
447 // Note that we must not share the unresolved variables with 446 // Note that we must not share the unresolved variables with
448 // the same name because they may be removed selectively via 447 // the same name because they may be removed selectively via
449 // RemoveUnresolved(). 448 // RemoveUnresolved().
450 ASSERT(!already_resolved()); 449 ASSERT(!already_resolved());
451 VariableProxy* proxy = new(isolate_->zone()) VariableProxy( 450 VariableProxy* proxy = new(isolate_->zone()) VariableProxy(
452 isolate_, name, false, inside_with, position); 451 isolate_, name, false, position);
453 unresolved_.Add(proxy); 452 unresolved_.Add(proxy);
454 return proxy; 453 return proxy;
455 } 454 }
456 455
457 456
458 void Scope::RemoveUnresolved(VariableProxy* var) { 457 void Scope::RemoveUnresolved(VariableProxy* var) {
459 // Most likely (always?) any variable we want to remove 458 // Most likely (always?) any variable we want to remove
460 // was just added before, so we search backwards. 459 // was just added before, so we search backwards.
461 for (int i = unresolved_.length(); i-- > 0;) { 460 for (int i = unresolved_.length(); i-- > 0;) {
462 if (unresolved_[i] == var) { 461 if (unresolved_[i] == var) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 illegal_redecl_->Accept(visitor); 497 illegal_redecl_->Accept(visitor);
499 } 498 }
500 499
501 500
502 Declaration* Scope::CheckConflictingVarDeclarations() { 501 Declaration* Scope::CheckConflictingVarDeclarations() {
503 int length = decls_.length(); 502 int length = decls_.length();
504 for (int i = 0; i < length; i++) { 503 for (int i = 0; i < length; i++) {
505 Declaration* decl = decls_[i]; 504 Declaration* decl = decls_[i];
506 if (decl->mode() != VAR) continue; 505 if (decl->mode() != VAR) continue;
507 Handle<String> name = decl->proxy()->name(); 506 Handle<String> name = decl->proxy()->name();
508 bool cond = true; 507
509 for (Scope* scope = decl->scope(); cond ; scope = scope->outer_scope_) { 508 // Iterate through all scopes until and including the declaration scope.
509 Scope* previous = NULL;
510 Scope* current = decl->scope();
511 do {
510 // There is a conflict if there exists a non-VAR binding. 512 // There is a conflict if there exists a non-VAR binding.
511 Variable* other_var = scope->variables_.Lookup(name); 513 Variable* other_var = current->variables_.Lookup(name);
512 if (other_var != NULL && other_var->mode() != VAR) { 514 if (other_var != NULL && other_var->mode() != VAR) {
513 return decl; 515 return decl;
514 } 516 }
515 517 previous = current;
516 // Include declaration scope in the iteration but stop after. 518 current = current->outer_scope_;
517 if (!scope->is_block_scope() && !scope->is_catch_scope()) cond = false; 519 } while (!previous->is_declaration_scope());
518 }
519 } 520 }
520 return NULL; 521 return NULL;
521 } 522 }
522 523
523 524
524 template<class Allocator> 525 template<class Allocator>
525 void Scope::CollectUsedVariables(List<Variable*, Allocator>* locals) { 526 void Scope::CollectUsedVariables(List<Variable*, Allocator>* locals) {
526 // Collect variables in this scope. 527 // Collect variables in this scope.
527 // Note that the function_ variable - if present - is not 528 // Note that the function_ variable - if present - is not
528 // collected here but handled separately in ScopeInfo 529 // collected here but handled separately in ScopeInfo
(...skipping 27 matching lines...) Expand all
556 void Scope::AllocateVariables(Handle<Context> context) { 557 void Scope::AllocateVariables(Handle<Context> context) {
557 ASSERT(outer_scope_ == NULL); // eval or global scopes only 558 ASSERT(outer_scope_ == NULL); // eval or global scopes only
558 559
559 // 1) Propagate scope information. 560 // 1) Propagate scope information.
560 // If we are in an eval scope, we may have other outer scopes about 561 // If we are in an eval scope, we may have other outer scopes about
561 // which we don't know anything at this point. Thus we must be conservative 562 // which we don't know anything at this point. Thus we must be conservative
562 // and assume they may invoke eval themselves. Eventually we could capture 563 // and assume they may invoke eval themselves. Eventually we could capture
563 // this information in the ScopeInfo and then use it here (by traversing 564 // this information in the ScopeInfo and then use it here (by traversing
564 // the call chain stack, at compile time). 565 // the call chain stack, at compile time).
565 566
566 bool eval_scope = is_eval_scope();
567 bool outer_scope_calls_eval = false;
568 bool outer_scope_calls_non_strict_eval = false; 567 bool outer_scope_calls_non_strict_eval = false;
569 if (!is_global_scope()) { 568 if (!is_global_scope()) {
570 context->ComputeEvalScopeInfo(&outer_scope_calls_eval, 569 context->ComputeEvalScopeInfo(&outer_scope_calls_non_strict_eval);
571 &outer_scope_calls_non_strict_eval);
572 } 570 }
573 PropagateScopeInfo(outer_scope_calls_eval, 571 PropagateScopeInfo(outer_scope_calls_non_strict_eval);
574 outer_scope_calls_non_strict_eval,
575 eval_scope);
576 572
577 // 2) Resolve variables. 573 // 2) Resolve variables.
578 Scope* global_scope = NULL; 574 Scope* global_scope = NULL;
579 if (is_global_scope()) global_scope = this; 575 if (is_global_scope()) global_scope = this;
580 ResolveVariablesRecursively(global_scope, context); 576 ResolveVariablesRecursively(global_scope, context);
581 577
582 // 3) Allocate variables. 578 // 3) Allocate variables.
583 AllocateVariablesRecursively(); 579 AllocateVariablesRecursively();
584 } 580 }
585 581
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 for (Scope* s = this; s != scope; s = s->outer_scope_) { 614 for (Scope* s = this; s != scope; s = s->outer_scope_) {
619 ASSERT(s != NULL); // scope must be in the scope chain 615 ASSERT(s != NULL); // scope must be in the scope chain
620 if (s->num_heap_slots() > 0) n++; 616 if (s->num_heap_slots() > 0) n++;
621 } 617 }
622 return n; 618 return n;
623 } 619 }
624 620
625 621
626 Scope* Scope::DeclarationScope() { 622 Scope* Scope::DeclarationScope() {
627 Scope* scope = this; 623 Scope* scope = this;
628 while (scope->is_catch_scope() || 624 while (!scope->is_declaration_scope()) {
629 scope->is_block_scope()) {
630 scope = scope->outer_scope(); 625 scope = scope->outer_scope();
631 } 626 }
632 return scope; 627 return scope;
633 } 628 }
634 629
635 630
636 Handle<SerializedScopeInfo> Scope::GetSerializedScopeInfo() { 631 Handle<SerializedScopeInfo> Scope::GetSerializedScopeInfo() {
637 if (scope_info_.is_null()) { 632 if (scope_info_.is_null()) {
638 scope_info_ = SerializedScopeInfo::Create(this); 633 scope_info_ = SerializedScopeInfo::Create(this);
639 } 634 }
640 return scope_info_; 635 return scope_info_;
641 } 636 }
642 637
643 638
639 void Scope::GetNestedScopeChain(
640 List<Handle<SerializedScopeInfo> >* chain,
641 int position) {
642 chain->Add(Handle<SerializedScopeInfo>(GetSerializedScopeInfo()));
643
644 for (int i = 0; i < inner_scopes_.length(); i++) {
645 Scope* scope = inner_scopes_[i];
646 int beg_pos = scope->start_position();
647 int end_pos = scope->end_position();
648 ASSERT(beg_pos >= 0 && end_pos >= 0);
649 if (beg_pos <= position && position <= end_pos) {
650 scope->GetNestedScopeChain(chain, position);
651 return;
652 }
653 }
654 }
655
656
644 #ifdef DEBUG 657 #ifdef DEBUG
645 static const char* Header(Scope::Type type) { 658 static const char* Header(ScopeType type) {
646 switch (type) { 659 switch (type) {
647 case Scope::EVAL_SCOPE: return "eval"; 660 case EVAL_SCOPE: return "eval";
648 case Scope::FUNCTION_SCOPE: return "function"; 661 case FUNCTION_SCOPE: return "function";
649 case Scope::GLOBAL_SCOPE: return "global"; 662 case GLOBAL_SCOPE: return "global";
650 case Scope::CATCH_SCOPE: return "catch"; 663 case CATCH_SCOPE: return "catch";
651 case Scope::BLOCK_SCOPE: return "block"; 664 case BLOCK_SCOPE: return "block";
665 case WITH_SCOPE: return "with";
652 } 666 }
653 UNREACHABLE(); 667 UNREACHABLE();
654 return NULL; 668 return NULL;
655 } 669 }
656 670
657 671
658 static void Indent(int n, const char* str) { 672 static void Indent(int n, const char* str) {
659 PrintF("%*s%s", n, "", str); 673 PrintF("%*s%s", n, "", str);
660 } 674 }
661 675
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 } 755 }
742 756
743 // Scope info. 757 // Scope info.
744 if (HasTrivialOuterContext()) { 758 if (HasTrivialOuterContext()) {
745 Indent(n1, "// scope has trivial outer context\n"); 759 Indent(n1, "// scope has trivial outer context\n");
746 } 760 }
747 if (is_strict_mode()) Indent(n1, "// strict mode scope\n"); 761 if (is_strict_mode()) Indent(n1, "// strict mode scope\n");
748 if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n"); 762 if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
749 if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n"); 763 if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");
750 if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n"); 764 if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
751 if (outer_scope_calls_eval_) Indent(n1, "// outer scope calls 'eval'\n");
752 if (outer_scope_calls_non_strict_eval_) { 765 if (outer_scope_calls_non_strict_eval_) {
753 Indent(n1, "// outer scope calls 'eval' in non-strict context\n"); 766 Indent(n1, "// outer scope calls 'eval' in non-strict context\n");
754 } 767 }
755 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); 768 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
756 if (outer_scope_is_eval_scope_) {
757 Indent(n1, "// outer scope is 'eval' scope\n");
758 }
759 if (num_stack_slots_ > 0) { Indent(n1, "// "); 769 if (num_stack_slots_ > 0) { Indent(n1, "// ");
760 PrintF("%d stack slots\n", num_stack_slots_); } 770 PrintF("%d stack slots\n", num_stack_slots_); }
761 if (num_heap_slots_ > 0) { Indent(n1, "// "); 771 if (num_heap_slots_ > 0) { Indent(n1, "// ");
762 PrintF("%d heap slots\n", num_heap_slots_); } 772 PrintF("%d heap slots\n", num_heap_slots_); }
763 773
764 // Print locals. 774 // Print locals.
765 Indent(n1, "// function var\n"); 775 Indent(n1, "// function var\n");
766 if (function_ != NULL) { 776 if (function_ != NULL) {
767 PrintVar(n1, function_->var()); 777 PrintVar(n1, function_->var());
768 } 778 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 if (var == NULL) { 812 if (var == NULL) {
803 // Declare a new non-local. 813 // Declare a new non-local.
804 var = map->Declare(NULL, name, mode, true, Variable::NORMAL); 814 var = map->Declare(NULL, name, mode, true, Variable::NORMAL);
805 // Allocate it by giving it a dynamic lookup. 815 // Allocate it by giving it a dynamic lookup.
806 var->AllocateTo(Variable::LOOKUP, -1); 816 var->AllocateTo(Variable::LOOKUP, -1);
807 } 817 }
808 return var; 818 return var;
809 } 819 }
810 820
811 821
812 // Lookup a variable starting with this scope. The result is either
813 // the statically resolved variable belonging to an outer scope, or
814 // NULL. It may be NULL because a) we couldn't find a variable, or b)
815 // because the variable is just a guess (and may be shadowed by
816 // another variable that is introduced dynamically via an 'eval' call
817 // or a 'with' statement).
818 Variable* Scope::LookupRecursive(Handle<String> name, 822 Variable* Scope::LookupRecursive(Handle<String> name,
819 bool from_inner_scope, 823 Handle<Context> context,
820 Variable** invalidated_local) { 824 BindingKind* binding_kind) {
821 // If we find a variable, but the current scope calls 'eval', the found 825 ASSERT(binding_kind != NULL);
822 // variable may not be the correct one (the 'eval' may introduce a
823 // property with the same name). In that case, remember that the variable
824 // found is just a guess.
825 bool guess = scope_calls_eval_;
826
827 // Try to find the variable in this scope. 826 // Try to find the variable in this scope.
828 Variable* var = LocalLookup(name); 827 Variable* var = LocalLookup(name);
829 828
829 // We found a variable and we are done. (Even if there is an 'eval' in
830 // this scope which introduces the same variable again, the resulting
831 // variable remains the same.)
830 if (var != NULL) { 832 if (var != NULL) {
831 // We found a variable. If this is not an inner lookup, we are done. 833 *binding_kind = BOUND;
832 // (Even if there is an 'eval' in this scope which introduces the 834 return var;
833 // same variable again, the resulting variable remains the same.
834 // Note that enclosing 'with' statements are handled at the call site.)
835 if (!from_inner_scope)
836 return var;
837
838 } else {
839 // We did not find a variable locally. Check against the function variable,
840 // if any. We can do this for all scopes, since the function variable is
841 // only present - if at all - for function scopes.
842 //
843 // This lookup corresponds to a lookup in the "intermediate" scope sitting
844 // between this scope and the outer scope. (ECMA-262, 3rd., requires that
845 // the name of named function literal is kept in an intermediate scope
846 // in between this scope and the next outer scope.)
847 if (function_ != NULL && function_->name().is_identical_to(name)) {
848 var = function_->var();
849
850 } else if (outer_scope_ != NULL) {
851 var = outer_scope_->LookupRecursive(name, true, invalidated_local);
852 // We may have found a variable in an outer scope. However, if
853 // the current scope is inside a 'with', the actual variable may
854 // be a property introduced via the 'with' statement. Then, the
855 // variable we may have found is just a guess.
856 if (scope_inside_with_)
857 guess = true;
858 }
859
860 // If we did not find a variable, we are done.
861 if (var == NULL)
862 return NULL;
863 } 835 }
864 836
865 ASSERT(var != NULL); 837 // We did not find a variable locally. Check against the function variable,
866 838 // if any. We can do this for all scopes, since the function variable is
867 // If this is a lookup from an inner scope, mark the variable. 839 // only present - if at all - for function scopes.
868 if (from_inner_scope) { 840 //
869 var->MarkAsAccessedFromInnerScope(); 841 // This lookup corresponds to a lookup in the "intermediate" scope sitting
842 // between this scope and the outer scope. (ECMA-262, 3rd., requires that
843 // the name of named function literal is kept in an intermediate scope
844 // in between this scope and the next outer scope.)
845 *binding_kind = UNBOUND;
846 if (function_ != NULL && function_->name().is_identical_to(name)) {
847 var = function_->var();
848 *binding_kind = BOUND;
849 } else if (outer_scope_ != NULL) {
850 var = outer_scope_->LookupRecursive(name, context, binding_kind);
851 if (*binding_kind == BOUND) var->MarkAsAccessedFromInnerScope();
870 } 852 }
871 853
872 // If the variable we have found is just a guess, invalidate the 854 if (is_with_scope()) {
873 // result. If the found variable is local, record that fact so we 855 // The current scope is a with scope, so the variable binding can not be
874 // can generate fast code to get it if it is not shadowed by eval. 856 // statically resolved. However, note that it was necessary to do a lookup
875 if (guess) { 857 // in the outer scope anyway, because if a binding exists in an outer scope,
876 if (!var->is_global()) *invalidated_local = var; 858 // the associated variable has to be marked as potentially being accessed
877 var = NULL; 859 // from inside of an inner with scope (the property may not be in the 'with'
860 // object).
861 *binding_kind = DYNAMIC_LOOKUP;
862 return NULL;
863 } else if (is_eval_scope()) {
864 // No local binding was found, no 'with' statements have been encountered
865 // and the code is executed as part of a call to 'eval'. The calling context
866 // contains scope information that we can use to determine if the variable
867 // is global, i.e. the calling context chain does not contain a binding and
868 // no 'with' contexts.
869 ASSERT(*binding_kind == UNBOUND);
870 *binding_kind = context->GlobalIfNotShadowedByEval(name)
871 ? UNBOUND_EVAL_SHADOWED : DYNAMIC_LOOKUP;
872 return NULL;
873 } else if (calls_non_strict_eval()) {
874 // A variable binding may have been found in an outer scope, but the current
875 // scope makes a non-strict 'eval' call, so the found variable may not be
876 // the correct one (the 'eval' may introduce a binding with the same name).
877 // In that case, change the lookup result to reflect this situation.
878 if (*binding_kind == BOUND) {
879 *binding_kind = BOUND_EVAL_SHADOWED;
880 } else if (*binding_kind == UNBOUND) {
881 *binding_kind = UNBOUND_EVAL_SHADOWED;
882 }
878 } 883 }
879
880 return var; 884 return var;
881 } 885 }
882 886
883 887
884 void Scope::ResolveVariable(Scope* global_scope, 888 void Scope::ResolveVariable(Scope* global_scope,
885 Handle<Context> context, 889 Handle<Context> context,
886 VariableProxy* proxy) { 890 VariableProxy* proxy) {
887 ASSERT(global_scope == NULL || global_scope->is_global_scope()); 891 ASSERT(global_scope == NULL || global_scope->is_global_scope());
888 892
889 // If the proxy is already resolved there's nothing to do 893 // If the proxy is already resolved there's nothing to do
890 // (functions and consts may be resolved by the parser). 894 // (functions and consts may be resolved by the parser).
891 if (proxy->var() != NULL) return; 895 if (proxy->var() != NULL) return;
892 896
893 // Otherwise, try to resolve the variable. 897 // Otherwise, try to resolve the variable.
894 Variable* invalidated_local = NULL; 898 BindingKind binding_kind;
895 Variable* var = LookupRecursive(proxy->name(), false, &invalidated_local); 899 Variable* var = LookupRecursive(proxy->name(), context, &binding_kind);
900 switch (binding_kind) {
901 case BOUND:
902 // We found a variable binding.
903 break;
896 904
897 if (proxy->inside_with()) { 905 case BOUND_EVAL_SHADOWED:
898 // If we are inside a local 'with' statement, all bets are off 906 // We found a variable variable binding that might be shadowed
899 // and we cannot resolve the proxy to a local variable even if 907 // by 'eval' introduced variable bindings.
900 // we found an outer matching variable. 908 if (var->is_global()) {
901 // Note that we must do a lookup anyway, because if we find one, 909 var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
902 // we must mark that variable as potentially accessed from this 910 } else {
903 // inner scope (the property may not be in the 'with' object). 911 Variable* invalidated = var;
904 var = NonLocal(proxy->name(), DYNAMIC); 912 var = NonLocal(proxy->name(), DYNAMIC_LOCAL);
913 var->set_local_if_not_shadowed(invalidated);
914 }
915 break;
905 916
906 } else { 917 case UNBOUND:
907 // We are not inside a local 'with' statement. 918 // No binding has been found. Declare a variable in global scope.
919 ASSERT(global_scope != NULL);
920 var = global_scope->DeclareGlobal(proxy->name());
921 break;
908 922
909 if (var == NULL) { 923 case UNBOUND_EVAL_SHADOWED:
910 // We did not find the variable. We have a global variable 924 // No binding has been found. But some scope makes a
911 // if we are in the global scope (we know already that we 925 // non-strict 'eval' call.
912 // are outside a 'with' statement) or if there is no way 926 var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
913 // that the variable might be introduced dynamically (through 927 break;
914 // a local or outer eval() call, or an outer 'with' statement),
915 // or we don't know about the outer scope (because we are
916 // in an eval scope).
917 if (is_global_scope() ||
918 !(scope_inside_with_ || outer_scope_is_eval_scope_ ||
919 scope_calls_eval_ || outer_scope_calls_eval_)) {
920 // We must have a global variable.
921 ASSERT(global_scope != NULL);
922 var = global_scope->DeclareGlobal(proxy->name());
923 928
924 } else if (scope_inside_with_) { 929 case DYNAMIC_LOOKUP:
925 // If we are inside a with statement we give up and look up 930 // The variable could not be resolved statically.
926 // the variable at runtime. 931 var = NonLocal(proxy->name(), DYNAMIC);
927 var = NonLocal(proxy->name(), DYNAMIC); 932 break;
928
929 } else if (invalidated_local != NULL) {
930 // No with statements are involved and we found a local
931 // variable that might be shadowed by eval introduced
932 // variables.
933 var = NonLocal(proxy->name(), DYNAMIC_LOCAL);
934 var->set_local_if_not_shadowed(invalidated_local);
935
936 } else if (outer_scope_is_eval_scope_) {
937 // No with statements and we did not find a local and the code
938 // is executed with a call to eval. The context contains
939 // scope information that we can use to determine if the
940 // variable is global if it is not shadowed by eval-introduced
941 // variables.
942 if (context->GlobalIfNotShadowedByEval(proxy->name())) {
943 var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
944
945 } else {
946 var = NonLocal(proxy->name(), DYNAMIC);
947 }
948
949 } else {
950 // No with statements and we did not find a local and the code
951 // is not executed with a call to eval. We know that this
952 // variable is global unless it is shadowed by eval-introduced
953 // variables.
954 var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
955 }
956 }
957 } 933 }
958 934
935 ASSERT(var != NULL);
959 proxy->BindTo(var); 936 proxy->BindTo(var);
960 } 937 }
961 938
962 939
963 void Scope::ResolveVariablesRecursively(Scope* global_scope, 940 void Scope::ResolveVariablesRecursively(Scope* global_scope,
964 Handle<Context> context) { 941 Handle<Context> context) {
965 ASSERT(global_scope == NULL || global_scope->is_global_scope()); 942 ASSERT(global_scope == NULL || global_scope->is_global_scope());
966 943
967 // Resolve unresolved variables for this scope. 944 // Resolve unresolved variables for this scope.
968 for (int i = 0; i < unresolved_.length(); i++) { 945 for (int i = 0; i < unresolved_.length(); i++) {
969 ResolveVariable(global_scope, context, unresolved_[i]); 946 ResolveVariable(global_scope, context, unresolved_[i]);
970 } 947 }
971 948
972 // Resolve unresolved variables for inner scopes. 949 // Resolve unresolved variables for inner scopes.
973 for (int i = 0; i < inner_scopes_.length(); i++) { 950 for (int i = 0; i < inner_scopes_.length(); i++) {
974 inner_scopes_[i]->ResolveVariablesRecursively(global_scope, context); 951 inner_scopes_[i]->ResolveVariablesRecursively(global_scope, context);
975 } 952 }
976 } 953 }
977 954
978 955
979 bool Scope::PropagateScopeInfo(bool outer_scope_calls_eval, 956 bool Scope::PropagateScopeInfo(bool outer_scope_calls_non_strict_eval ) {
980 bool outer_scope_calls_non_strict_eval,
981 bool outer_scope_is_eval_scope) {
982 if (outer_scope_calls_eval) {
983 outer_scope_calls_eval_ = true;
984 }
985
986 if (outer_scope_calls_non_strict_eval) { 957 if (outer_scope_calls_non_strict_eval) {
987 outer_scope_calls_non_strict_eval_ = true; 958 outer_scope_calls_non_strict_eval_ = true;
988 } 959 }
989 960
990 if (outer_scope_is_eval_scope) {
991 outer_scope_is_eval_scope_ = true;
992 }
993
994 bool calls_eval = scope_calls_eval_ || outer_scope_calls_eval_;
995 bool is_eval = is_eval_scope() || outer_scope_is_eval_scope_;
996 bool calls_non_strict_eval = 961 bool calls_non_strict_eval =
997 (scope_calls_eval_ && !is_strict_mode()) || 962 (scope_calls_eval_ && !is_strict_mode()) ||
998 outer_scope_calls_non_strict_eval_; 963 outer_scope_calls_non_strict_eval_;
999 for (int i = 0; i < inner_scopes_.length(); i++) { 964 for (int i = 0; i < inner_scopes_.length(); i++) {
1000 Scope* inner_scope = inner_scopes_[i]; 965 Scope* inner_scope = inner_scopes_[i];
1001 if (inner_scope->PropagateScopeInfo(calls_eval, 966 if (inner_scope->PropagateScopeInfo(calls_non_strict_eval)) {
1002 calls_non_strict_eval,
1003 is_eval)) {
1004 inner_scope_calls_eval_ = true; 967 inner_scope_calls_eval_ = true;
1005 } 968 }
1006 if (inner_scope->force_eager_compilation_) { 969 if (inner_scope->force_eager_compilation_) {
1007 force_eager_compilation_ = true; 970 force_eager_compilation_ = true;
1008 } 971 }
1009 } 972 }
1010 973
1011 return scope_calls_eval_ || inner_scope_calls_eval_; 974 return scope_calls_eval_ || inner_scope_calls_eval_;
1012 } 975 }
1013 976
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
1197 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && 1160 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS &&
1198 !must_have_local_context) { 1161 !must_have_local_context) {
1199 num_heap_slots_ = 0; 1162 num_heap_slots_ = 0;
1200 } 1163 }
1201 1164
1202 // Allocation done. 1165 // Allocation done.
1203 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); 1166 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
1204 } 1167 }
1205 1168
1206 } } // namespace v8::internal 1169 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/scopes.h ('k') | src/serialize.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698