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

Side by Side Diff: src/scopes.cc

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 5 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/scopes.h ('k') | src/serialize.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 // Implementation of Scope 112 // Implementation of Scope
113 113
114 114
115 // Dummy constructor 115 // Dummy constructor
116 Scope::Scope(Type type) 116 Scope::Scope(Type type)
117 : inner_scopes_(0), 117 : inner_scopes_(0),
118 variables_(false), 118 variables_(false),
119 temps_(0), 119 temps_(0),
120 params_(0), 120 params_(0),
121 unresolved_(0), 121 unresolved_(0),
122 decls_(0) { 122 decls_(0),
123 already_resolved_(false) {
123 SetDefaults(type, NULL, Handle<SerializedScopeInfo>::null()); 124 SetDefaults(type, NULL, Handle<SerializedScopeInfo>::null());
124 ASSERT(!resolved());
125 } 125 }
126 126
127 127
128 Scope::Scope(Scope* outer_scope, Type type) 128 Scope::Scope(Scope* outer_scope, Type type)
129 : inner_scopes_(4), 129 : inner_scopes_(4),
130 variables_(), 130 variables_(),
131 temps_(4), 131 temps_(4),
132 params_(4), 132 params_(4),
133 unresolved_(16), 133 unresolved_(16),
134 decls_(4) { 134 decls_(4),
135 already_resolved_(false) {
135 SetDefaults(type, outer_scope, Handle<SerializedScopeInfo>::null()); 136 SetDefaults(type, outer_scope, Handle<SerializedScopeInfo>::null());
136 // At some point we might want to provide outer scopes to 137 // At some point we might want to provide outer scopes to
137 // eval scopes (by walking the stack and reading the scope info). 138 // eval scopes (by walking the stack and reading the scope info).
138 // In that case, the ASSERT below needs to be adjusted. 139 // In that case, the ASSERT below needs to be adjusted.
139 ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL)); 140 ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL));
140 ASSERT(!HasIllegalRedeclaration()); 141 ASSERT(!HasIllegalRedeclaration());
141 ASSERT(!resolved());
142 } 142 }
143 143
144 144
145 Scope::Scope(Scope* inner_scope, Handle<SerializedScopeInfo> scope_info) 145 Scope::Scope(Scope* inner_scope, Handle<SerializedScopeInfo> scope_info)
146 : inner_scopes_(4), 146 : inner_scopes_(4),
147 variables_(), 147 variables_(),
148 temps_(4), 148 temps_(4),
149 params_(4), 149 params_(4),
150 unresolved_(16), 150 unresolved_(16),
151 decls_(4) { 151 decls_(4),
152 already_resolved_(true) {
152 ASSERT(!scope_info.is_null()); 153 ASSERT(!scope_info.is_null());
153 SetDefaults(FUNCTION_SCOPE, NULL, scope_info); 154 SetDefaults(FUNCTION_SCOPE, NULL, scope_info);
154 ASSERT(resolved());
155 if (scope_info->HasHeapAllocatedLocals()) { 155 if (scope_info->HasHeapAllocatedLocals()) {
156 num_heap_slots_ = scope_info_->NumberOfContextSlots(); 156 num_heap_slots_ = scope_info_->NumberOfContextSlots();
157 } 157 }
158
159 AddInnerScope(inner_scope); 158 AddInnerScope(inner_scope);
160
161 // This scope's arguments shadow (if present) is context-allocated if an inner
162 // scope accesses this one's parameters. Allocate the arguments_shadow_
163 // variable if necessary.
164 Isolate* isolate = Isolate::Current();
165 Variable::Mode mode;
166 int arguments_shadow_index =
167 scope_info_->ContextSlotIndex(
168 isolate->heap()->arguments_shadow_symbol(), &mode);
169 if (arguments_shadow_index >= 0) {
170 ASSERT(mode == Variable::INTERNAL);
171 arguments_shadow_ = new Variable(
172 this,
173 isolate->factory()->arguments_shadow_symbol(),
174 Variable::INTERNAL,
175 true,
176 Variable::ARGUMENTS);
177 arguments_shadow_->set_rewrite(
178 new Slot(arguments_shadow_, Slot::CONTEXT, arguments_shadow_index));
179 arguments_shadow_->set_is_used(true);
180 }
181 } 159 }
182 160
183 161
162 Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name)
163 : inner_scopes_(1),
164 variables_(),
165 temps_(0),
166 params_(0),
167 unresolved_(0),
168 decls_(0),
169 already_resolved_(true) {
170 SetDefaults(CATCH_SCOPE, NULL, Handle<SerializedScopeInfo>::null());
171 AddInnerScope(inner_scope);
172 ++num_var_or_const_;
173 Variable* variable = variables_.Declare(this,
174 catch_variable_name,
175 Variable::VAR,
176 true, // Valid left-hand side.
177 Variable::NORMAL);
178 AllocateHeapSlot(variable);
179 }
180
181
184 void Scope::SetDefaults(Type type, 182 void Scope::SetDefaults(Type type,
185 Scope* outer_scope, 183 Scope* outer_scope,
186 Handle<SerializedScopeInfo> scope_info) { 184 Handle<SerializedScopeInfo> scope_info) {
187 outer_scope_ = outer_scope; 185 outer_scope_ = outer_scope;
188 type_ = type; 186 type_ = type;
189 scope_name_ = FACTORY->empty_symbol(); 187 scope_name_ = FACTORY->empty_symbol();
190 dynamics_ = NULL; 188 dynamics_ = NULL;
191 receiver_ = NULL; 189 receiver_ = NULL;
192 function_ = NULL; 190 function_ = NULL;
193 arguments_ = NULL; 191 arguments_ = NULL;
194 arguments_shadow_ = NULL;
195 illegal_redecl_ = NULL; 192 illegal_redecl_ = NULL;
196 scope_inside_with_ = false; 193 scope_inside_with_ = false;
197 scope_contains_with_ = false; 194 scope_contains_with_ = false;
198 scope_calls_eval_ = false; 195 scope_calls_eval_ = false;
199 // Inherit the strict mode from the parent scope. 196 // Inherit the strict mode from the parent scope.
200 strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_; 197 strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_;
201 outer_scope_calls_eval_ = false; 198 outer_scope_calls_eval_ = false;
202 outer_scope_calls_non_strict_eval_ = false; 199 outer_scope_calls_non_strict_eval_ = false;
203 inner_scope_calls_eval_ = false; 200 inner_scope_calls_eval_ = false;
204 outer_scope_is_eval_scope_ = false; 201 outer_scope_is_eval_scope_ = false;
205 force_eager_compilation_ = false; 202 force_eager_compilation_ = false;
206 num_var_or_const_ = 0; 203 num_var_or_const_ = 0;
207 num_stack_slots_ = 0; 204 num_stack_slots_ = 0;
208 num_heap_slots_ = 0; 205 num_heap_slots_ = 0;
209 scope_info_ = scope_info; 206 scope_info_ = scope_info;
210 } 207 }
211 208
212 209
213 Scope* Scope::DeserializeScopeChain(CompilationInfo* info, 210 Scope* Scope::DeserializeScopeChain(CompilationInfo* info,
214 Scope* global_scope) { 211 Scope* global_scope) {
212 // Reconstruct the outer scope chain from a closure's context chain.
215 ASSERT(!info->closure().is_null()); 213 ASSERT(!info->closure().is_null());
216 // If we have a serialized scope info, reuse it. 214 Context* context = info->closure()->context();
215 Scope* current_scope = NULL;
217 Scope* innermost_scope = NULL; 216 Scope* innermost_scope = NULL;
218 Scope* scope = NULL; 217 bool contains_with = false;
218 while (!context->IsGlobalContext()) {
219 if (context->IsWithContext()) {
220 // All the inner scopes are inside a with.
221 contains_with = true;
222 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) {
223 s->scope_inside_with_ = true;
224 }
225 } else {
226 if (context->IsFunctionContext()) {
227 SerializedScopeInfo* scope_info =
228 context->closure()->shared()->scope_info();
229 current_scope =
230 new Scope(current_scope, Handle<SerializedScopeInfo>(scope_info));
231 } else {
232 ASSERT(context->IsCatchContext());
233 String* name = String::cast(context->extension());
234 current_scope = new Scope(current_scope, Handle<String>(name));
235 }
236 if (contains_with) current_scope->RecordWithStatement();
237 if (innermost_scope == NULL) innermost_scope = current_scope;
238 }
219 239
220 SerializedScopeInfo* scope_info = info->closure()->shared()->scope_info(); 240 // Forget about a with when we move to a context for a different function.
221 if (scope_info != SerializedScopeInfo::Empty()) { 241 if (context->previous()->closure() != context->closure()) {
222 JSFunction* current = *info->closure(); 242 contains_with = false;
223 do { 243 }
224 current = current->context()->closure(); 244 context = context->previous();
225 Handle<SerializedScopeInfo> scope_info(current->shared()->scope_info());
226 if (*scope_info != SerializedScopeInfo::Empty()) {
227 scope = new Scope(scope, scope_info);
228 if (innermost_scope == NULL) innermost_scope = scope;
229 } else {
230 ASSERT(current->context()->IsGlobalContext());
231 }
232 } while (!current->context()->IsGlobalContext());
233 } 245 }
234 246
235 global_scope->AddInnerScope(scope); 247 global_scope->AddInnerScope(current_scope);
236 if (innermost_scope == NULL) innermost_scope = global_scope; 248 return (innermost_scope == NULL) ? global_scope : innermost_scope;
237
238 return innermost_scope;
239 } 249 }
240 250
241 251
242 bool Scope::Analyze(CompilationInfo* info) { 252 bool Scope::Analyze(CompilationInfo* info) {
243 ASSERT(info->function() != NULL); 253 ASSERT(info->function() != NULL);
244 Scope* top = info->function()->scope(); 254 Scope* top = info->function()->scope();
245 255
246 while (top->outer_scope() != NULL) top = top->outer_scope(); 256 while (top->outer_scope() != NULL) top = top->outer_scope();
247 top->AllocateVariables(info->calling_context()); 257 top->AllocateVariables(info->calling_context());
248 258
249 #ifdef DEBUG 259 #ifdef DEBUG
250 if (info->isolate()->bootstrapper()->IsActive() 260 if (info->isolate()->bootstrapper()->IsActive()
251 ? FLAG_print_builtin_scopes 261 ? FLAG_print_builtin_scopes
252 : FLAG_print_scopes) { 262 : FLAG_print_scopes) {
253 info->function()->scope()->Print(); 263 info->function()->scope()->Print();
254 } 264 }
255 #endif 265 #endif
256 266
257 info->SetScope(info->function()->scope()); 267 info->SetScope(info->function()->scope());
258 return true; // Can not fail. 268 return true; // Can not fail.
259 } 269 }
260 270
261 271
262 void Scope::Initialize(bool inside_with) { 272 void Scope::Initialize(bool inside_with) {
263 ASSERT(!resolved()); 273 ASSERT(!already_resolved());
264 274
265 // Add this scope as a new inner scope of the outer scope. 275 // Add this scope as a new inner scope of the outer scope.
266 if (outer_scope_ != NULL) { 276 if (outer_scope_ != NULL) {
267 outer_scope_->inner_scopes_.Add(this); 277 outer_scope_->inner_scopes_.Add(this);
268 scope_inside_with_ = outer_scope_->scope_inside_with_ || inside_with; 278 scope_inside_with_ = outer_scope_->scope_inside_with_ || inside_with;
269 } else { 279 } else {
270 scope_inside_with_ = inside_with; 280 scope_inside_with_ = inside_with;
271 } 281 }
272 282
273 // Declare convenience variables. 283 // Declare convenience variables.
274 // Declare and allocate receiver (even for the global scope, and even 284 // Declare and allocate receiver (even for the global scope, and even
275 // if naccesses_ == 0). 285 // if naccesses_ == 0).
276 // NOTE: When loading parameters in the global scope, we must take 286 // NOTE: When loading parameters in the global scope, we must take
277 // care not to access them as properties of the global object, but 287 // care not to access them as properties of the global object, but
278 // instead load them directly from the stack. Currently, the only 288 // instead load them directly from the stack. Currently, the only
279 // such parameter is 'this' which is passed on the stack when 289 // such parameter is 'this' which is passed on the stack when
280 // invoking scripts 290 // invoking scripts
281 Variable* var = 291 if (is_catch_scope()) {
282 variables_.Declare(this, FACTORY->this_symbol(), Variable::VAR, 292 ASSERT(outer_scope() != NULL);
283 false, Variable::THIS); 293 receiver_ = outer_scope()->receiver();
284 var->set_rewrite(new Slot(var, Slot::PARAMETER, -1)); 294 } else {
285 receiver_ = var; 295 Variable* var =
296 variables_.Declare(this, FACTORY->this_symbol(), Variable::VAR,
297 false, Variable::THIS);
298 var->set_rewrite(new Slot(var, Slot::PARAMETER, -1));
299 receiver_ = var;
300 }
286 301
287 if (is_function_scope()) { 302 if (is_function_scope()) {
288 // Declare 'arguments' variable which exists in all functions. 303 // Declare 'arguments' variable which exists in all functions.
289 // Note that it might never be accessed, in which case it won't be 304 // Note that it might never be accessed, in which case it won't be
290 // allocated during variable allocation. 305 // allocated during variable allocation.
291 variables_.Declare(this, FACTORY->arguments_symbol(), Variable::VAR, 306 variables_.Declare(this, FACTORY->arguments_symbol(), Variable::VAR,
292 true, Variable::ARGUMENTS); 307 true, Variable::ARGUMENTS);
293 } 308 }
294 } 309 }
295 310
296 311
297 Variable* Scope::LocalLookup(Handle<String> name) { 312 Variable* Scope::LocalLookup(Handle<String> name) {
298 Variable* result = variables_.Lookup(name); 313 Variable* result = variables_.Lookup(name);
299 if (result != NULL || !resolved()) { 314 if (result != NULL || scope_info_.is_null()) {
300 return result; 315 return result;
301 } 316 }
302 // If the scope is resolved, we can find a variable in serialized scope info. 317 // If we have a serialized scope info, we might find the variable there.
303 318 //
304 // We should never lookup 'arguments' in this scope 319 // We should never lookup 'arguments' in this scope as it is implicitly
305 // as it is implicitly present in any scope. 320 // present in every scope.
306 ASSERT(*name != *FACTORY->arguments_symbol()); 321 ASSERT(*name != *FACTORY->arguments_symbol());
307 322 // There should be no local slot with the given name.
308 // Assert that there is no local slot with the given name.
309 ASSERT(scope_info_->StackSlotIndex(*name) < 0); 323 ASSERT(scope_info_->StackSlotIndex(*name) < 0);
310 324
311 // Check context slot lookup. 325 // Check context slot lookup.
312 Variable::Mode mode; 326 Variable::Mode mode;
313 int index = scope_info_->ContextSlotIndex(*name, &mode); 327 int index = scope_info_->ContextSlotIndex(*name, &mode);
314 if (index >= 0) { 328 if (index < 0) {
315 Variable* var = 329 // Check parameters.
316 variables_.Declare(this, name, mode, true, Variable::NORMAL); 330 mode = Variable::VAR;
317 var->set_rewrite(new Slot(var, Slot::CONTEXT, index)); 331 index = scope_info_->ParameterIndex(*name);
318 return var; 332 if (index < 0) {
333 // Check the function name.
334 index = scope_info_->FunctionContextSlotIndex(*name);
335 if (index < 0) return NULL;
336 }
319 } 337 }
320 338
321 index = scope_info_->ParameterIndex(*name); 339 Variable* var =
322 if (index >= 0) { 340 variables_.Declare(this, name, mode, true, Variable::NORMAL);
323 // ".arguments" must be present in context slots. 341 var->set_rewrite(new Slot(var, Slot::CONTEXT, index));
324 ASSERT(arguments_shadow_ != NULL); 342 return var;
325 Variable* var =
326 variables_.Declare(this, name, Variable::VAR, true, Variable::NORMAL);
327 Property* rewrite =
328 new Property(new VariableProxy(arguments_shadow_),
329 new Literal(Handle<Object>(Smi::FromInt(index))),
330 RelocInfo::kNoPosition,
331 Property::SYNTHETIC);
332 rewrite->set_is_arguments_access(true);
333 var->set_rewrite(rewrite);
334 return var;
335 }
336
337 index = scope_info_->FunctionContextSlotIndex(*name);
338 if (index >= 0) {
339 // Check that there is no local slot with the given name.
340 ASSERT(scope_info_->StackSlotIndex(*name) < 0);
341 Variable* var =
342 variables_.Declare(this, name, Variable::VAR, true, Variable::NORMAL);
343 var->set_rewrite(new Slot(var, Slot::CONTEXT, index));
344 return var;
345 }
346
347 return NULL;
348 } 343 }
349 344
350 345
351 Variable* Scope::Lookup(Handle<String> name) { 346 Variable* Scope::Lookup(Handle<String> name) {
352 for (Scope* scope = this; 347 for (Scope* scope = this;
353 scope != NULL; 348 scope != NULL;
354 scope = scope->outer_scope()) { 349 scope = scope->outer_scope()) {
355 Variable* var = scope->LocalLookup(name); 350 Variable* var = scope->LocalLookup(name);
356 if (var != NULL) return var; 351 if (var != NULL) return var;
357 } 352 }
358 return NULL; 353 return NULL;
359 } 354 }
360 355
361 356
362 Variable* Scope::DeclareFunctionVar(Handle<String> name) { 357 Variable* Scope::DeclareFunctionVar(Handle<String> name) {
363 ASSERT(is_function_scope() && function_ == NULL); 358 ASSERT(is_function_scope() && function_ == NULL);
364 function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL); 359 function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL);
365 return function_; 360 return function_;
366 } 361 }
367 362
368 363
369 Variable* Scope::DeclareLocal(Handle<String> name, 364 void Scope::DeclareParameter(Handle<String> name) {
370 Variable::Mode mode, 365 ASSERT(!already_resolved());
371 LocalType type) { 366 ASSERT(is_function_scope());
372 // DYNAMIC variables are introduces during variable allocation, 367 Variable* var =
373 // INTERNAL variables are allocated explicitly, and TEMPORARY 368 variables_.Declare(this, name, Variable::VAR, true, Variable::NORMAL);
374 // variables are allocated via NewTemporary(). 369 params_.Add(var);
375 ASSERT(!resolved()); 370 }
371
372
373 Variable* Scope::DeclareLocal(Handle<String> name, Variable::Mode mode) {
374 ASSERT(!already_resolved());
375 // This function handles VAR and CONST modes. DYNAMIC variables are
376 // introduces during variable allocation, INTERNAL variables are allocated
377 // explicitly, and TEMPORARY variables are allocated via NewTemporary().
376 ASSERT(mode == Variable::VAR || mode == Variable::CONST); 378 ASSERT(mode == Variable::VAR || mode == Variable::CONST);
377 if (type == VAR_OR_CONST) { 379 ++num_var_or_const_;
378 num_var_or_const_++;
379 }
380 return variables_.Declare(this, name, mode, true, Variable::NORMAL); 380 return variables_.Declare(this, name, mode, true, Variable::NORMAL);
381 } 381 }
382 382
383 383
384 Variable* Scope::DeclareGlobal(Handle<String> name) { 384 Variable* Scope::DeclareGlobal(Handle<String> name) {
385 ASSERT(is_global_scope()); 385 ASSERT(is_global_scope());
386 return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL, true, 386 return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL, true,
387 Variable::NORMAL); 387 Variable::NORMAL);
388 } 388 }
389 389
390 390
391 void Scope::AddParameter(Variable* var) {
392 ASSERT(is_function_scope());
393 ASSERT(LocalLookup(var->name()) == var);
394 params_.Add(var);
395 }
396
397
398 VariableProxy* Scope::NewUnresolved(Handle<String> name, 391 VariableProxy* Scope::NewUnresolved(Handle<String> name,
399 bool inside_with, 392 bool inside_with,
400 int position) { 393 int position) {
401 // Note that we must not share the unresolved variables with 394 // Note that we must not share the unresolved variables with
402 // the same name because they may be removed selectively via 395 // the same name because they may be removed selectively via
403 // RemoveUnresolved(). 396 // RemoveUnresolved().
404 ASSERT(!resolved()); 397 ASSERT(!already_resolved());
405 VariableProxy* proxy = new VariableProxy(name, false, inside_with, position); 398 VariableProxy* proxy = new VariableProxy(name, false, inside_with, position);
406 unresolved_.Add(proxy); 399 unresolved_.Add(proxy);
407 return proxy; 400 return proxy;
408 } 401 }
409 402
410 403
411 void Scope::RemoveUnresolved(VariableProxy* var) { 404 void Scope::RemoveUnresolved(VariableProxy* var) {
412 // Most likely (always?) any variable we want to remove 405 // Most likely (always?) any variable we want to remove
413 // was just added before, so we search backwards. 406 // was just added before, so we search backwards.
414 for (int i = unresolved_.length(); i-- > 0;) { 407 for (int i = unresolved_.length(); i-- > 0;) {
415 if (unresolved_[i] == var) { 408 if (unresolved_[i] == var) {
416 unresolved_.Remove(i); 409 unresolved_.Remove(i);
417 return; 410 return;
418 } 411 }
419 } 412 }
420 } 413 }
421 414
422 415
423 Variable* Scope::NewTemporary(Handle<String> name) { 416 Variable* Scope::NewTemporary(Handle<String> name) {
424 ASSERT(!resolved()); 417 ASSERT(!already_resolved());
425 Variable* var = 418 Variable* var =
426 new Variable(this, name, Variable::TEMPORARY, true, Variable::NORMAL); 419 new Variable(this, name, Variable::TEMPORARY, true, Variable::NORMAL);
427 temps_.Add(var); 420 temps_.Add(var);
428 return var; 421 return var;
429 } 422 }
430 423
431 424
432 void Scope::AddDeclaration(Declaration* declaration) { 425 void Scope::AddDeclaration(Declaration* declaration) {
433 decls_.Add(declaration); 426 decls_.Add(declaration);
434 } 427 }
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 int Scope::ContextChainLength(Scope* scope) { 537 int Scope::ContextChainLength(Scope* scope) {
545 int n = 0; 538 int n = 0;
546 for (Scope* s = this; s != scope; s = s->outer_scope_) { 539 for (Scope* s = this; s != scope; s = s->outer_scope_) {
547 ASSERT(s != NULL); // scope must be in the scope chain 540 ASSERT(s != NULL); // scope must be in the scope chain
548 if (s->num_heap_slots() > 0) n++; 541 if (s->num_heap_slots() > 0) n++;
549 } 542 }
550 return n; 543 return n;
551 } 544 }
552 545
553 546
547 Scope* Scope::DeclarationScope() {
548 Scope* scope = this;
549 while (scope->is_catch_scope()) {
550 scope = scope->outer_scope();
551 }
552 return scope;
553 }
554
555
554 #ifdef DEBUG 556 #ifdef DEBUG
555 static const char* Header(Scope::Type type) { 557 static const char* Header(Scope::Type type) {
556 switch (type) { 558 switch (type) {
557 case Scope::EVAL_SCOPE: return "eval"; 559 case Scope::EVAL_SCOPE: return "eval";
558 case Scope::FUNCTION_SCOPE: return "function"; 560 case Scope::FUNCTION_SCOPE: return "function";
559 case Scope::GLOBAL_SCOPE: return "global"; 561 case Scope::GLOBAL_SCOPE: return "global";
562 case Scope::CATCH_SCOPE: return "catch";
560 } 563 }
561 UNREACHABLE(); 564 UNREACHABLE();
562 return NULL; 565 return NULL;
563 } 566 }
564 567
565 568
566 static void Indent(int n, const char* str) { 569 static void Indent(int n, const char* str) {
567 PrintF("%*s%s", n, "", str); 570 PrintF("%*s%s", n, "", str);
568 } 571 }
569 572
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
900 return scope_calls_eval_ || inner_scope_calls_eval_; 903 return scope_calls_eval_ || inner_scope_calls_eval_;
901 } 904 }
902 905
903 906
904 bool Scope::MustAllocate(Variable* var) { 907 bool Scope::MustAllocate(Variable* var) {
905 // Give var a read/write use if there is a chance it might be accessed 908 // Give var a read/write use if there is a chance it might be accessed
906 // via an eval() call. This is only possible if the variable has a 909 // via an eval() call. This is only possible if the variable has a
907 // visible name. 910 // visible name.
908 if ((var->is_this() || var->name()->length() > 0) && 911 if ((var->is_this() || var->name()->length() > 0) &&
909 (var->is_accessed_from_inner_scope() || 912 (var->is_accessed_from_inner_scope() ||
910 scope_calls_eval_ || inner_scope_calls_eval_ || 913 scope_calls_eval_ ||
911 scope_contains_with_)) { 914 inner_scope_calls_eval_ ||
915 scope_contains_with_ ||
916 is_catch_scope())) {
912 var->set_is_used(true); 917 var->set_is_used(true);
913 } 918 }
914 // Global variables do not need to be allocated. 919 // Global variables do not need to be allocated.
915 return !var->is_global() && var->is_used(); 920 return !var->is_global() && var->is_used();
916 } 921 }
917 922
918 923
919 bool Scope::MustAllocateInContext(Variable* var) { 924 bool Scope::MustAllocateInContext(Variable* var) {
920 // If var is accessed from an inner scope, or if there is a 925 // If var is accessed from an inner scope, or if there is a possibility
921 // possibility that it might be accessed from the current or an inner 926 // that it might be accessed from the current or an inner scope (through
922 // scope (through an eval() call), it must be allocated in the 927 // an eval() call or a runtime with lookup), it must be allocated in the
923 // context. Exception: temporary variables are not allocated in the
924 // context. 928 // context.
925 return 929 //
926 var->mode() != Variable::TEMPORARY && 930 // Exceptions: temporary variables are never allocated in a context;
927 (var->is_accessed_from_inner_scope() || 931 // catch-bound variables are always allocated in a context.
928 scope_calls_eval_ || inner_scope_calls_eval_ || 932 if (var->mode() == Variable::TEMPORARY) return false;
929 scope_contains_with_ || var->is_global()); 933 if (is_catch_scope()) return true;
934 return var->is_accessed_from_inner_scope() ||
935 scope_calls_eval_ ||
936 inner_scope_calls_eval_ ||
937 scope_contains_with_ ||
938 var->is_global();
930 } 939 }
931 940
932 941
933 bool Scope::HasArgumentsParameter() { 942 bool Scope::HasArgumentsParameter() {
934 for (int i = 0; i < params_.length(); i++) { 943 for (int i = 0; i < params_.length(); i++) {
935 if (params_[i]->name().is_identical_to(FACTORY->arguments_symbol())) 944 if (params_[i]->name().is_identical_to(FACTORY->arguments_symbol()))
936 return true; 945 return true;
937 } 946 }
938 return false; 947 return false;
939 } 948 }
940 949
941 950
942 void Scope::AllocateStackSlot(Variable* var) { 951 void Scope::AllocateStackSlot(Variable* var) {
943 var->set_rewrite(new Slot(var, Slot::LOCAL, num_stack_slots_++)); 952 var->set_rewrite(new Slot(var, Slot::LOCAL, num_stack_slots_++));
944 } 953 }
945 954
946 955
947 void Scope::AllocateHeapSlot(Variable* var) { 956 void Scope::AllocateHeapSlot(Variable* var) {
948 var->set_rewrite(new Slot(var, Slot::CONTEXT, num_heap_slots_++)); 957 var->set_rewrite(new Slot(var, Slot::CONTEXT, num_heap_slots_++));
949 } 958 }
950 959
951 960
952 void Scope::AllocateParameterLocals() { 961 void Scope::AllocateParameterLocals() {
953 ASSERT(is_function_scope()); 962 ASSERT(is_function_scope());
954 Variable* arguments = LocalLookup(FACTORY->arguments_symbol()); 963 Variable* arguments = LocalLookup(FACTORY->arguments_symbol());
955 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly 964 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly
956 965
957 // Parameters are rewritten to arguments[i] if 'arguments' is used in 966 bool uses_nonstrict_arguments = false;
958 // a non-strict mode function. Strict mode code doesn't alias arguments.
959 bool rewrite_parameters = false;
960 967
961 if (MustAllocate(arguments) && !HasArgumentsParameter()) { 968 if (MustAllocate(arguments) && !HasArgumentsParameter()) {
962 // 'arguments' is used. Unless there is also a parameter called 969 // 'arguments' is used. Unless there is also a parameter called
963 // 'arguments', we must be conservative and access all parameters via 970 // 'arguments', we must be conservative and allocate all parameters to
964 // the arguments object: The i'th parameter is rewritten into 971 // the context assuming they will be captured by the arguments object.
965 // '.arguments[i]' (*). If we have a parameter named 'arguments', a 972 // If we have a parameter named 'arguments', a (new) value is always
966 // (new) value is always assigned to it via the function 973 // assigned to it via the function invocation. Then 'arguments' denotes
967 // invocation. Then 'arguments' denotes that specific parameter value 974 // that specific parameter value and cannot be used to access the
968 // and cannot be used to access the parameters, which is why we don't 975 // parameters, which is why we don't need to allocate an arguments
969 // need to rewrite in that case. 976 // object in that case.
970 //
971 // (*) Instead of having a parameter called 'arguments', we may have an
972 // assignment to 'arguments' in the function body, at some arbitrary
973 // point in time (possibly through an 'eval()' call!). After that
974 // assignment any re-write of parameters would be invalid (was bug
975 // 881452). Thus, we introduce a shadow '.arguments'
976 // variable which also points to the arguments object. For rewrites we
977 // use '.arguments' which remains valid even if we assign to
978 // 'arguments'. To summarize: If we need to rewrite, we allocate an
979 // 'arguments' object dynamically upon function invocation. The compiler
980 // introduces 2 local variables 'arguments' and '.arguments', both of
981 // which originally point to the arguments object that was
982 // allocated. All parameters are rewritten into property accesses via
983 // the '.arguments' variable. Thus, any changes to properties of
984 // 'arguments' are reflected in the variables and vice versa. If the
985 // 'arguments' variable is changed, '.arguments' still points to the
986 // correct arguments object and the rewrites still work.
987 977
988 // We are using 'arguments'. Tell the code generator that is needs to 978 // We are using 'arguments'. Tell the code generator that is needs to
989 // allocate the arguments object by setting 'arguments_'. 979 // allocate the arguments object by setting 'arguments_'.
990 arguments_ = arguments; 980 arguments_ = arguments;
991 981
992 // In strict mode 'arguments' does not alias formal parameters. 982 // In strict mode 'arguments' does not alias formal parameters.
993 // Therefore in strict mode we allocate parameters as if 'arguments' 983 // Therefore in strict mode we allocate parameters as if 'arguments'
994 // were not used. 984 // were not used.
995 rewrite_parameters = !is_strict_mode(); 985 uses_nonstrict_arguments = !is_strict_mode();
996 } 986 }
997 987
998 if (rewrite_parameters) { 988 // The same parameter may occur multiple times in the parameters_ list.
999 // We also need the '.arguments' shadow variable. Declare it and create 989 // If it does, and if it is not copied into the context object, it must
1000 // and bind the corresponding proxy. It's ok to declare it only now 990 // receive the highest parameter index for that parameter; thus iteration
1001 // because it's a local variable that is allocated after the parameters 991 // order is relevant!
1002 // have been allocated. 992 for (int i = params_.length() - 1; i >= 0; --i) {
1003 // 993 Variable* var = params_[i];
1004 // Note: This is "almost" at temporary variable but we cannot use 994 ASSERT(var->scope() == this);
1005 // NewTemporary() because the mode needs to be INTERNAL since this 995 if (uses_nonstrict_arguments) {
1006 // variable may be allocated in the heap-allocated context (temporaries 996 // Give the parameter a use from an inner scope, to force allocation
1007 // are never allocated in the context). 997 // to the context.
1008 arguments_shadow_ = new Variable(this, 998 var->MarkAsAccessedFromInnerScope();
1009 FACTORY->arguments_shadow_symbol(),
1010 Variable::INTERNAL,
1011 true,
1012 Variable::ARGUMENTS);
1013 arguments_shadow_->set_is_used(true);
1014 temps_.Add(arguments_shadow_);
1015
1016 // Allocate the parameters by rewriting them into '.arguments[i]' accesses.
1017 for (int i = 0; i < params_.length(); i++) {
1018 Variable* var = params_[i];
1019 ASSERT(var->scope() == this);
1020 if (MustAllocate(var)) {
1021 if (MustAllocateInContext(var)) {
1022 // It is ok to set this only now, because arguments is a local
1023 // variable that is allocated after the parameters have been
1024 // allocated.
1025 arguments_shadow_->MarkAsAccessedFromInnerScope();
1026 }
1027 Property* rewrite =
1028 new Property(new VariableProxy(arguments_shadow_),
1029 new Literal(Handle<Object>(Smi::FromInt(i))),
1030 RelocInfo::kNoPosition,
1031 Property::SYNTHETIC);
1032 rewrite->set_is_arguments_access(true);
1033 var->set_rewrite(rewrite);
1034 }
1035 } 999 }
1036 1000
1037 } else { 1001 if (MustAllocate(var)) {
1038 // The arguments object is not used, so we can access parameters directly. 1002 if (MustAllocateInContext(var)) {
1039 // The same parameter may occur multiple times in the parameters_ list. 1003 ASSERT(var->rewrite() == NULL || var->IsContextSlot());
1040 // If it does, and if it is not copied into the context object, it must 1004 if (var->rewrite() == NULL) {
1041 // receive the highest parameter index for that parameter; thus iteration 1005 AllocateHeapSlot(var);
1042 // order is relevant! 1006 }
1043 for (int i = 0; i < params_.length(); i++) { 1007 } else {
1044 Variable* var = params_[i]; 1008 ASSERT(var->rewrite() == NULL || var->IsParameter());
1045 ASSERT(var->scope() == this); 1009 if (var->rewrite() == NULL) {
1046 if (MustAllocate(var)) {
1047 if (MustAllocateInContext(var)) {
1048 ASSERT(var->rewrite() == NULL ||
1049 (var->AsSlot() != NULL &&
1050 var->AsSlot()->type() == Slot::CONTEXT));
1051 if (var->rewrite() == NULL) {
1052 // Only set the heap allocation if the parameter has not
1053 // been allocated yet.
1054 AllocateHeapSlot(var);
1055 }
1056 } else {
1057 ASSERT(var->rewrite() == NULL ||
1058 (var->AsSlot() != NULL &&
1059 var->AsSlot()->type() == Slot::PARAMETER));
1060 // Set the parameter index always, even if the parameter
1061 // was seen before! (We need to access the actual parameter
1062 // supplied for the last occurrence of a multiply declared
1063 // parameter.)
1064 var->set_rewrite(new Slot(var, Slot::PARAMETER, i)); 1010 var->set_rewrite(new Slot(var, Slot::PARAMETER, i));
1065 } 1011 }
1066 } 1012 }
1067 } 1013 }
1068 } 1014 }
1069 } 1015 }
1070 1016
1071 1017
1072 void Scope::AllocateNonParameterLocal(Variable* var) { 1018 void Scope::AllocateNonParameterLocal(Variable* var) {
1073 ASSERT(var->scope() == this); 1019 ASSERT(var->scope() == this);
1074 ASSERT(var->rewrite() == NULL || 1020 ASSERT(var->rewrite() == NULL ||
1075 (!var->IsVariable(FACTORY->result_symbol())) || 1021 !var->IsVariable(FACTORY->result_symbol()) ||
1076 (var->AsSlot() == NULL || var->AsSlot()->type() != Slot::LOCAL)); 1022 var->AsSlot() == NULL ||
1023 var->AsSlot()->type() != Slot::LOCAL);
1077 if (var->rewrite() == NULL && MustAllocate(var)) { 1024 if (var->rewrite() == NULL && MustAllocate(var)) {
1078 if (MustAllocateInContext(var)) { 1025 if (MustAllocateInContext(var)) {
1079 AllocateHeapSlot(var); 1026 AllocateHeapSlot(var);
1080 } else { 1027 } else {
1081 AllocateStackSlot(var); 1028 AllocateStackSlot(var);
1082 } 1029 }
1083 } 1030 }
1084 } 1031 }
1085 1032
1086 1033
(...skipping 21 matching lines...) Expand all
1108 1055
1109 1056
1110 void Scope::AllocateVariablesRecursively() { 1057 void Scope::AllocateVariablesRecursively() {
1111 // Allocate variables for inner scopes. 1058 // Allocate variables for inner scopes.
1112 for (int i = 0; i < inner_scopes_.length(); i++) { 1059 for (int i = 0; i < inner_scopes_.length(); i++) {
1113 inner_scopes_[i]->AllocateVariablesRecursively(); 1060 inner_scopes_[i]->AllocateVariablesRecursively();
1114 } 1061 }
1115 1062
1116 // If scope is already resolved, we still need to allocate 1063 // If scope is already resolved, we still need to allocate
1117 // variables in inner scopes which might not had been resolved yet. 1064 // variables in inner scopes which might not had been resolved yet.
1118 if (resolved()) return; 1065 if (already_resolved()) return;
1119 // The number of slots required for variables. 1066 // The number of slots required for variables.
1120 num_stack_slots_ = 0; 1067 num_stack_slots_ = 0;
1121 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; 1068 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
1122 1069
1123 // Allocate variables for this scope. 1070 // Allocate variables for this scope.
1124 // Parameters must be allocated first, if any. 1071 // Parameters must be allocated first, if any.
1125 if (is_function_scope()) AllocateParameterLocals(); 1072 if (is_function_scope()) AllocateParameterLocals();
1126 AllocateNonParameterLocals(); 1073 AllocateNonParameterLocals();
1127 1074
1128 // Allocate context if necessary. 1075 // Allocate context if necessary.
(...skipping 12 matching lines...) Expand all
1141 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && 1088 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS &&
1142 !must_have_local_context) { 1089 !must_have_local_context) {
1143 num_heap_slots_ = 0; 1090 num_heap_slots_ = 0;
1144 } 1091 }
1145 1092
1146 // Allocation done. 1093 // Allocation done.
1147 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); 1094 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
1148 } 1095 }
1149 1096
1150 } } // namespace v8::internal 1097 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/scopes.h ('k') | src/serialize.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698