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

Side by Side Diff: src/scopes.cc

Issue 7285032: Fix an issue with optimization of functions inside catch. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
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') | test/mjsunit/regress/regress-1521.js » ('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 } 159 }
161 160
162 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
163 void Scope::SetDefaults(Type type, 182 void Scope::SetDefaults(Type type,
164 Scope* outer_scope, 183 Scope* outer_scope,
165 Handle<SerializedScopeInfo> scope_info) { 184 Handle<SerializedScopeInfo> scope_info) {
166 outer_scope_ = outer_scope; 185 outer_scope_ = outer_scope;
167 type_ = type; 186 type_ = type;
168 scope_name_ = FACTORY->empty_symbol(); 187 scope_name_ = FACTORY->empty_symbol();
169 dynamics_ = NULL; 188 dynamics_ = NULL;
170 receiver_ = NULL; 189 receiver_ = NULL;
171 function_ = NULL; 190 function_ = NULL;
172 arguments_ = NULL; 191 arguments_ = NULL;
(...skipping 10 matching lines...) Expand all
183 force_eager_compilation_ = false; 202 force_eager_compilation_ = false;
184 num_var_or_const_ = 0; 203 num_var_or_const_ = 0;
185 num_stack_slots_ = 0; 204 num_stack_slots_ = 0;
186 num_heap_slots_ = 0; 205 num_heap_slots_ = 0;
187 scope_info_ = scope_info; 206 scope_info_ = scope_info;
188 } 207 }
189 208
190 209
191 Scope* Scope::DeserializeScopeChain(CompilationInfo* info, 210 Scope* Scope::DeserializeScopeChain(CompilationInfo* info,
192 Scope* global_scope) { 211 Scope* global_scope) {
212 // Reconstruct the outer scope chain from a closure's context chain.
193 ASSERT(!info->closure().is_null()); 213 ASSERT(!info->closure().is_null());
194 // If we have a serialized scope info, reuse it. 214 Context* context = info->closure()->context();
215 Scope* current_scope = NULL;
195 Scope* innermost_scope = NULL; 216 Scope* innermost_scope = NULL;
196 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 }
197 239
198 SerializedScopeInfo* scope_info = info->closure()->shared()->scope_info(); 240 // Forget about a with when we move to a context for a different function.
199 if (scope_info != SerializedScopeInfo::Empty()) { 241 if (context->previous()->closure() != context->closure()) {
200 JSFunction* current = *info->closure(); 242 contains_with = false;
201 do { 243 }
202 current = current->context()->closure(); 244 context = context->previous();
203 Handle<SerializedScopeInfo> scope_info(current->shared()->scope_info());
204 if (*scope_info != SerializedScopeInfo::Empty()) {
205 scope = new Scope(scope, scope_info);
206 if (innermost_scope == NULL) innermost_scope = scope;
207 } else {
208 ASSERT(current->context()->IsGlobalContext());
209 }
210 } while (!current->context()->IsGlobalContext());
211 } 245 }
212 246
213 global_scope->AddInnerScope(scope); 247 global_scope->AddInnerScope(current_scope);
214 if (innermost_scope == NULL) innermost_scope = global_scope; 248 return (innermost_scope == NULL) ? global_scope : innermost_scope;
215
216 return innermost_scope;
217 } 249 }
218 250
219 251
220 bool Scope::Analyze(CompilationInfo* info) { 252 bool Scope::Analyze(CompilationInfo* info) {
221 ASSERT(info->function() != NULL); 253 ASSERT(info->function() != NULL);
222 Scope* top = info->function()->scope(); 254 Scope* top = info->function()->scope();
223 255
224 while (top->outer_scope() != NULL) top = top->outer_scope(); 256 while (top->outer_scope() != NULL) top = top->outer_scope();
225 top->AllocateVariables(info->calling_context()); 257 top->AllocateVariables(info->calling_context());
226 258
227 #ifdef DEBUG 259 #ifdef DEBUG
228 if (info->isolate()->bootstrapper()->IsActive() 260 if (info->isolate()->bootstrapper()->IsActive()
229 ? FLAG_print_builtin_scopes 261 ? FLAG_print_builtin_scopes
230 : FLAG_print_scopes) { 262 : FLAG_print_scopes) {
231 info->function()->scope()->Print(); 263 info->function()->scope()->Print();
232 } 264 }
233 #endif 265 #endif
234 266
235 info->SetScope(info->function()->scope()); 267 info->SetScope(info->function()->scope());
236 return true; // Can not fail. 268 return true; // Can not fail.
237 } 269 }
238 270
239 271
240 void Scope::Initialize(bool inside_with) { 272 void Scope::Initialize(bool inside_with) {
241 ASSERT(!resolved()); 273 ASSERT(!already_resolved());
242 274
243 // 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.
244 if (outer_scope_ != NULL) { 276 if (outer_scope_ != NULL) {
245 outer_scope_->inner_scopes_.Add(this); 277 outer_scope_->inner_scopes_.Add(this);
246 scope_inside_with_ = outer_scope_->scope_inside_with_ || inside_with; 278 scope_inside_with_ = outer_scope_->scope_inside_with_ || inside_with;
247 } else { 279 } else {
248 scope_inside_with_ = inside_with; 280 scope_inside_with_ = inside_with;
249 } 281 }
250 282
251 // Declare convenience variables. 283 // Declare convenience variables.
(...skipping 20 matching lines...) Expand all
272 // 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
273 // allocated during variable allocation. 305 // allocated during variable allocation.
274 variables_.Declare(this, FACTORY->arguments_symbol(), Variable::VAR, 306 variables_.Declare(this, FACTORY->arguments_symbol(), Variable::VAR,
275 true, Variable::ARGUMENTS); 307 true, Variable::ARGUMENTS);
276 } 308 }
277 } 309 }
278 310
279 311
280 Variable* Scope::LocalLookup(Handle<String> name) { 312 Variable* Scope::LocalLookup(Handle<String> name) {
281 Variable* result = variables_.Lookup(name); 313 Variable* result = variables_.Lookup(name);
282 if (result != NULL || !resolved()) { 314 if (result != NULL || scope_info_.is_null()) {
283 return result; 315 return result;
284 } 316 }
285 // If the scope is resolved, we can find a variable in serialized scope 317 // If we have a serialized scope info, we might find the variable there.
286 // info.
287 // 318 //
288 // We should never lookup 'arguments' in this scope as it is implicitly 319 // We should never lookup 'arguments' in this scope as it is implicitly
289 // present in every scope. 320 // present in every scope.
290 ASSERT(*name != *FACTORY->arguments_symbol()); 321 ASSERT(*name != *FACTORY->arguments_symbol());
291 // There should be no local slot with the given name. 322 // There should be no local slot with the given name.
292 ASSERT(scope_info_->StackSlotIndex(*name) < 0); 323 ASSERT(scope_info_->StackSlotIndex(*name) < 0);
293 324
294 // Check context slot lookup. 325 // Check context slot lookup.
295 Variable::Mode mode; 326 Variable::Mode mode;
296 int index = scope_info_->ContextSlotIndex(*name, &mode); 327 int index = scope_info_->ContextSlotIndex(*name, &mode);
(...skipping 27 matching lines...) Expand all
324 355
325 356
326 Variable* Scope::DeclareFunctionVar(Handle<String> name) { 357 Variable* Scope::DeclareFunctionVar(Handle<String> name) {
327 ASSERT(is_function_scope() && function_ == NULL); 358 ASSERT(is_function_scope() && function_ == NULL);
328 function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL); 359 function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL);
329 return function_; 360 return function_;
330 } 361 }
331 362
332 363
333 void Scope::DeclareParameter(Handle<String> name) { 364 void Scope::DeclareParameter(Handle<String> name) {
334 ASSERT(!resolved()); 365 ASSERT(!already_resolved());
335 ASSERT(is_function_scope()); 366 ASSERT(is_function_scope());
336 Variable* var = 367 Variable* var =
337 variables_.Declare(this, name, Variable::VAR, true, Variable::NORMAL); 368 variables_.Declare(this, name, Variable::VAR, true, Variable::NORMAL);
338 params_.Add(var); 369 params_.Add(var);
339 } 370 }
340 371
341 372
342 Variable* Scope::DeclareLocal(Handle<String> name, Variable::Mode mode) { 373 Variable* Scope::DeclareLocal(Handle<String> name, Variable::Mode mode) {
343 ASSERT(!resolved()); 374 ASSERT(!already_resolved());
344 // This function handles VAR and CONST modes. DYNAMIC variables are 375 // This function handles VAR and CONST modes. DYNAMIC variables are
345 // introduces during variable allocation, INTERNAL variables are allocated 376 // introduces during variable allocation, INTERNAL variables are allocated
346 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). 377 // explicitly, and TEMPORARY variables are allocated via NewTemporary().
347 ASSERT(mode == Variable::VAR || mode == Variable::CONST); 378 ASSERT(mode == Variable::VAR || mode == Variable::CONST);
348 ++num_var_or_const_; 379 ++num_var_or_const_;
349 return variables_.Declare(this, name, mode, true, Variable::NORMAL); 380 return variables_.Declare(this, name, mode, true, Variable::NORMAL);
350 } 381 }
351 382
352 383
353 Variable* Scope::DeclareGlobal(Handle<String> name) { 384 Variable* Scope::DeclareGlobal(Handle<String> name) {
354 ASSERT(is_global_scope()); 385 ASSERT(is_global_scope());
355 return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL, true, 386 return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL, true,
356 Variable::NORMAL); 387 Variable::NORMAL);
357 } 388 }
358 389
359 390
360 VariableProxy* Scope::NewUnresolved(Handle<String> name, 391 VariableProxy* Scope::NewUnresolved(Handle<String> name,
361 bool inside_with, 392 bool inside_with,
362 int position) { 393 int position) {
363 // Note that we must not share the unresolved variables with 394 // Note that we must not share the unresolved variables with
364 // the same name because they may be removed selectively via 395 // the same name because they may be removed selectively via
365 // RemoveUnresolved(). 396 // RemoveUnresolved().
366 ASSERT(!resolved()); 397 ASSERT(!already_resolved());
367 VariableProxy* proxy = new VariableProxy(name, false, inside_with, position); 398 VariableProxy* proxy = new VariableProxy(name, false, inside_with, position);
368 unresolved_.Add(proxy); 399 unresolved_.Add(proxy);
369 return proxy; 400 return proxy;
370 } 401 }
371 402
372 403
373 void Scope::RemoveUnresolved(VariableProxy* var) { 404 void Scope::RemoveUnresolved(VariableProxy* var) {
374 // Most likely (always?) any variable we want to remove 405 // Most likely (always?) any variable we want to remove
375 // was just added before, so we search backwards. 406 // was just added before, so we search backwards.
376 for (int i = unresolved_.length(); i-- > 0;) { 407 for (int i = unresolved_.length(); i-- > 0;) {
377 if (unresolved_[i] == var) { 408 if (unresolved_[i] == var) {
378 unresolved_.Remove(i); 409 unresolved_.Remove(i);
379 return; 410 return;
380 } 411 }
381 } 412 }
382 } 413 }
383 414
384 415
385 Variable* Scope::NewTemporary(Handle<String> name) { 416 Variable* Scope::NewTemporary(Handle<String> name) {
386 ASSERT(!resolved()); 417 ASSERT(!already_resolved());
387 Variable* var = 418 Variable* var =
388 new Variable(this, name, Variable::TEMPORARY, true, Variable::NORMAL); 419 new Variable(this, name, Variable::TEMPORARY, true, Variable::NORMAL);
389 temps_.Add(var); 420 temps_.Add(var);
390 return var; 421 return var;
391 } 422 }
392 423
393 424
394 void Scope::AddDeclaration(Declaration* declaration) { 425 void Scope::AddDeclaration(Declaration* declaration) {
395 decls_.Add(declaration); 426 decls_.Add(declaration);
396 } 427 }
(...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 1046
1016 1047
1017 void Scope::AllocateVariablesRecursively() { 1048 void Scope::AllocateVariablesRecursively() {
1018 // Allocate variables for inner scopes. 1049 // Allocate variables for inner scopes.
1019 for (int i = 0; i < inner_scopes_.length(); i++) { 1050 for (int i = 0; i < inner_scopes_.length(); i++) {
1020 inner_scopes_[i]->AllocateVariablesRecursively(); 1051 inner_scopes_[i]->AllocateVariablesRecursively();
1021 } 1052 }
1022 1053
1023 // If scope is already resolved, we still need to allocate 1054 // If scope is already resolved, we still need to allocate
1024 // variables in inner scopes which might not had been resolved yet. 1055 // variables in inner scopes which might not had been resolved yet.
1025 if (resolved()) return; 1056 if (already_resolved()) return;
1026 // The number of slots required for variables. 1057 // The number of slots required for variables.
1027 num_stack_slots_ = 0; 1058 num_stack_slots_ = 0;
1028 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; 1059 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
1029 1060
1030 // Allocate variables for this scope. 1061 // Allocate variables for this scope.
1031 // Parameters must be allocated first, if any. 1062 // Parameters must be allocated first, if any.
1032 if (is_function_scope()) AllocateParameterLocals(); 1063 if (is_function_scope()) AllocateParameterLocals();
1033 AllocateNonParameterLocals(); 1064 AllocateNonParameterLocals();
1034 1065
1035 // Allocate context if necessary. 1066 // Allocate context if necessary.
(...skipping 12 matching lines...) Expand all
1048 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && 1079 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS &&
1049 !must_have_local_context) { 1080 !must_have_local_context) {
1050 num_heap_slots_ = 0; 1081 num_heap_slots_ = 0;
1051 } 1082 }
1052 1083
1053 // Allocation done. 1084 // Allocation done.
1054 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); 1085 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
1055 } 1086 }
1056 1087
1057 } } // namespace v8::internal 1088 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/scopes.h ('k') | test/mjsunit/regress/regress-1521.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698