OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdlib.h> | 5 #include <stdlib.h> |
6 | 6 |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 | 8 |
9 #include "src/scopeinfo.h" | 9 #include "src/scopeinfo.h" |
10 #include "src/scopes.h" | 10 #include "src/scopes.h" |
11 | 11 |
12 namespace v8 { | 12 namespace v8 { |
13 namespace internal { | 13 namespace internal { |
14 | 14 |
15 | 15 |
16 Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, | 16 Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, |
17 Scope* scope) { | 17 Scope* scope) { |
18 // Collect stack and context locals. | 18 // Collect stack and context locals. |
19 ZoneList<Variable*> stack_locals(scope->StackLocalCount(), zone); | 19 ZoneList<Variable*> stack_locals(scope->StackLocalCount(), zone); |
20 ZoneList<Variable*> context_locals(scope->ContextLocalCount(), zone); | 20 ZoneList<Variable*> context_locals(scope->ContextLocalCount(), zone); |
21 ZoneList<Variable*> strong_mode_free_variables(0, zone); | 21 ZoneList<Variable*> strong_mode_free_variables(0, zone); |
22 | 22 |
23 scope->CollectStackAndContextLocals(&stack_locals, &context_locals, | 23 scope->CollectStackAndContextLocals(&stack_locals, &context_locals, |
24 &strong_mode_free_variables); | 24 &strong_mode_free_variables); |
25 const int stack_local_count = stack_locals.length(); | 25 const int stack_local_count = stack_locals.length(); |
26 const int context_local_count = context_locals.length(); | 26 const int context_local_count = context_locals.length(); |
27 const int strong_mode_free_variable_count = | 27 const int strong_mode_free_variable_count = |
28 strong_mode_free_variables.length(); | 28 strong_mode_free_variables.length(); |
29 // Make sure we allocate the correct amount. | 29 // Make sure we allocate the correct amount. |
30 DCHECK(scope->StackLocalCount() == stack_local_count); | |
31 DCHECK(scope->ContextLocalCount() == context_local_count); | 30 DCHECK(scope->ContextLocalCount() == context_local_count); |
32 | 31 |
33 bool simple_parameter_list = | 32 bool simple_parameter_list = |
34 scope->is_function_scope() ? scope->is_simple_parameter_list() : true; | 33 scope->is_function_scope() ? scope->is_simple_parameter_list() : true; |
35 | 34 |
36 // Determine use and location of the function variable if it is present. | 35 // Determine use and location of the function variable if it is present. |
37 FunctionVariableInfo function_name_info; | 36 FunctionVariableInfo function_name_info; |
38 VariableMode function_variable_mode; | 37 VariableMode function_variable_mode; |
39 if (scope->is_function_scope() && scope->function() != NULL) { | 38 if (scope->is_function_scope() && scope->function() != NULL) { |
40 Variable* var = scope->function()->proxy()->var(); | 39 Variable* var = scope->function()->proxy()->var(); |
41 if (!var->is_used()) { | 40 if (!var->is_used()) { |
42 function_name_info = UNUSED; | 41 function_name_info = UNUSED; |
43 } else if (var->IsContextSlot()) { | 42 } else if (var->IsContextSlot()) { |
44 function_name_info = CONTEXT; | 43 function_name_info = CONTEXT; |
45 } else { | 44 } else { |
46 DCHECK(var->IsStackLocal()); | 45 DCHECK(var->IsStackLocal()); |
47 function_name_info = STACK; | 46 function_name_info = STACK; |
48 } | 47 } |
49 function_variable_mode = var->mode(); | 48 function_variable_mode = var->mode(); |
50 } else { | 49 } else { |
51 function_name_info = NONE; | 50 function_name_info = NONE; |
52 function_variable_mode = VAR; | 51 function_variable_mode = VAR; |
53 } | 52 } |
54 | 53 |
55 const bool has_function_name = function_name_info != NONE; | 54 const bool has_function_name = function_name_info != NONE; |
56 const int parameter_count = scope->num_parameters(); | 55 const int parameter_count = scope->num_parameters(); |
57 const int length = kVariablePartIndex + parameter_count + stack_local_count + | 56 const int length = kVariablePartIndex + parameter_count + |
58 2 * context_local_count + | 57 (1 + stack_local_count) + 2 * context_local_count + |
59 3 * strong_mode_free_variable_count + | 58 3 * strong_mode_free_variable_count + |
60 (has_function_name ? 2 : 0); | 59 (has_function_name ? 2 : 0); |
61 | 60 |
62 Factory* factory = isolate->factory(); | 61 Factory* factory = isolate->factory(); |
63 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); | 62 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); |
64 | 63 |
65 // Encode the flags. | 64 // Encode the flags. |
66 int flags = ScopeTypeField::encode(scope->scope_type()) | | 65 int flags = ScopeTypeField::encode(scope->scope_type()) | |
67 CallsEvalField::encode(scope->calls_eval()) | | 66 CallsEvalField::encode(scope->calls_eval()) | |
68 LanguageModeField::encode(scope->language_mode()) | | 67 LanguageModeField::encode(scope->language_mode()) | |
(...skipping 13 matching lines...) Expand all Loading... |
82 int index = kVariablePartIndex; | 81 int index = kVariablePartIndex; |
83 // Add parameters. | 82 // Add parameters. |
84 DCHECK(index == scope_info->ParameterEntriesIndex()); | 83 DCHECK(index == scope_info->ParameterEntriesIndex()); |
85 for (int i = 0; i < parameter_count; ++i) { | 84 for (int i = 0; i < parameter_count; ++i) { |
86 scope_info->set(index++, *scope->parameter(i)->name()); | 85 scope_info->set(index++, *scope->parameter(i)->name()); |
87 } | 86 } |
88 | 87 |
89 // Add stack locals' names. We are assuming that the stack locals' | 88 // Add stack locals' names. We are assuming that the stack locals' |
90 // slots are allocated in increasing order, so we can simply add | 89 // slots are allocated in increasing order, so we can simply add |
91 // them to the ScopeInfo object. | 90 // them to the ScopeInfo object. |
| 91 int first_slot_index; |
| 92 if (stack_local_count > 0) { |
| 93 first_slot_index = stack_locals[0]->index(); |
| 94 } else { |
| 95 first_slot_index = 0; |
| 96 } |
| 97 DCHECK(index == scope_info->StackLocalFirstSlotIndex()); |
| 98 scope_info->set(index++, Smi::FromInt(first_slot_index)); |
92 DCHECK(index == scope_info->StackLocalEntriesIndex()); | 99 DCHECK(index == scope_info->StackLocalEntriesIndex()); |
93 for (int i = 0; i < stack_local_count; ++i) { | 100 for (int i = 0; i < stack_local_count; ++i) { |
94 DCHECK(stack_locals[i]->index() == i); | 101 DCHECK(stack_locals[i]->index() == first_slot_index + i); |
95 scope_info->set(index++, *stack_locals[i]->name()); | 102 scope_info->set(index++, *stack_locals[i]->name()); |
96 } | 103 } |
97 | 104 |
98 // Due to usage analysis, context-allocated locals are not necessarily in | 105 // Due to usage analysis, context-allocated locals are not necessarily in |
99 // increasing order: Some of them may be parameters which are allocated before | 106 // increasing order: Some of them may be parameters which are allocated before |
100 // the non-parameter locals. When the non-parameter locals are sorted | 107 // the non-parameter locals. When the non-parameter locals are sorted |
101 // according to usage, the allocated slot indices may not be in increasing | 108 // according to usage, the allocated slot indices may not be in increasing |
102 // order with the variable list anymore. Thus, we first need to sort them by | 109 // order with the variable list anymore. Thus, we first need to sort them by |
103 // context slot index before adding them to the ScopeInfo object. | 110 // context slot index before adding them to the ScopeInfo object. |
104 context_locals.Sort(&Variable::CompareIndex); | 111 context_locals.Sort(&Variable::CompareIndex); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 ->strong_mode_reference_end_position())); | 145 ->strong_mode_reference_end_position())); |
139 scope_info->set(index++, *end_position); | 146 scope_info->set(index++, *end_position); |
140 } | 147 } |
141 | 148 |
142 // If present, add the function variable name and its index. | 149 // If present, add the function variable name and its index. |
143 DCHECK(index == scope_info->FunctionNameEntryIndex()); | 150 DCHECK(index == scope_info->FunctionNameEntryIndex()); |
144 if (has_function_name) { | 151 if (has_function_name) { |
145 int var_index = scope->function()->proxy()->var()->index(); | 152 int var_index = scope->function()->proxy()->var()->index(); |
146 scope_info->set(index++, *scope->function()->proxy()->name()); | 153 scope_info->set(index++, *scope->function()->proxy()->name()); |
147 scope_info->set(index++, Smi::FromInt(var_index)); | 154 scope_info->set(index++, Smi::FromInt(var_index)); |
148 DCHECK(function_name_info != STACK || | |
149 (var_index == scope_info->StackLocalCount() && | |
150 var_index == scope_info->StackSlotCount() - 1)); | |
151 DCHECK(function_name_info != CONTEXT || | 155 DCHECK(function_name_info != CONTEXT || |
152 var_index == scope_info->ContextLength() - 1); | 156 var_index == scope_info->ContextLength() - 1); |
153 } | 157 } |
154 | 158 |
155 DCHECK(index == scope_info->length()); | 159 DCHECK(index == scope_info->length()); |
156 DCHECK(scope->num_parameters() == scope_info->ParameterCount()); | 160 DCHECK(scope->num_parameters() == scope_info->ParameterCount()); |
157 DCHECK(scope->num_stack_slots() == scope_info->StackSlotCount()); | |
158 DCHECK(scope->num_heap_slots() == scope_info->ContextLength() || | 161 DCHECK(scope->num_heap_slots() == scope_info->ContextLength() || |
159 (scope->num_heap_slots() == kVariablePartIndex && | 162 (scope->num_heap_slots() == kVariablePartIndex && |
160 scope_info->ContextLength() == 0)); | 163 scope_info->ContextLength() == 0)); |
161 return scope_info; | 164 return scope_info; |
162 } | 165 } |
163 | 166 |
164 | 167 |
165 ScopeInfo* ScopeInfo::Empty(Isolate* isolate) { | 168 ScopeInfo* ScopeInfo::Empty(Isolate* isolate) { |
166 return reinterpret_cast<ScopeInfo*>(isolate->heap()->empty_fixed_array()); | 169 return reinterpret_cast<ScopeInfo*>(isolate->heap()->empty_fixed_array()); |
167 } | 170 } |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 } | 265 } |
263 | 266 |
264 | 267 |
265 String* ScopeInfo::StackLocalName(int var) { | 268 String* ScopeInfo::StackLocalName(int var) { |
266 DCHECK(0 <= var && var < StackLocalCount()); | 269 DCHECK(0 <= var && var < StackLocalCount()); |
267 int info_index = StackLocalEntriesIndex() + var; | 270 int info_index = StackLocalEntriesIndex() + var; |
268 return String::cast(get(info_index)); | 271 return String::cast(get(info_index)); |
269 } | 272 } |
270 | 273 |
271 | 274 |
| 275 int ScopeInfo::StackLocalIndex(int var) { |
| 276 DCHECK(0 <= var && var < StackLocalCount()); |
| 277 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value(); |
| 278 return first_slot_index + var; |
| 279 } |
| 280 |
| 281 |
272 String* ScopeInfo::ContextLocalName(int var) { | 282 String* ScopeInfo::ContextLocalName(int var) { |
273 DCHECK(0 <= var && var < ContextLocalCount()); | 283 DCHECK(0 <= var && var < ContextLocalCount()); |
274 int info_index = ContextLocalNameEntriesIndex() + var; | 284 int info_index = ContextLocalNameEntriesIndex() + var; |
275 return String::cast(get(info_index)); | 285 return String::cast(get(info_index)); |
276 } | 286 } |
277 | 287 |
278 | 288 |
279 VariableMode ScopeInfo::ContextLocalMode(int var) { | 289 VariableMode ScopeInfo::ContextLocalMode(int var) { |
280 DCHECK(0 <= var && var < ContextLocalCount()); | 290 DCHECK(0 <= var && var < ContextLocalCount()); |
281 int info_index = ContextLocalInfoEntriesIndex() + var; | 291 int info_index = ContextLocalInfoEntriesIndex() + var; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 bool ok = get(info_index)->ToInt32(&value); | 346 bool ok = get(info_index)->ToInt32(&value); |
337 USE(ok); | 347 USE(ok); |
338 DCHECK(ok); | 348 DCHECK(ok); |
339 return value; | 349 return value; |
340 } | 350 } |
341 | 351 |
342 | 352 |
343 int ScopeInfo::StackSlotIndex(String* name) { | 353 int ScopeInfo::StackSlotIndex(String* name) { |
344 DCHECK(name->IsInternalizedString()); | 354 DCHECK(name->IsInternalizedString()); |
345 if (length() > 0) { | 355 if (length() > 0) { |
| 356 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value(); |
346 int start = StackLocalEntriesIndex(); | 357 int start = StackLocalEntriesIndex(); |
347 int end = StackLocalEntriesIndex() + StackLocalCount(); | 358 int end = StackLocalEntriesIndex() + StackLocalCount(); |
348 for (int i = start; i < end; ++i) { | 359 for (int i = start; i < end; ++i) { |
349 if (name == get(i)) { | 360 if (name == get(i)) { |
350 return i - start; | 361 return i - start + first_slot_index; |
351 } | 362 } |
352 } | 363 } |
353 } | 364 } |
354 return -1; | 365 return -1; |
355 } | 366 } |
356 | 367 |
357 | 368 |
358 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info, | 369 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info, |
359 Handle<String> name, VariableMode* mode, | 370 Handle<String> name, VariableMode* mode, |
360 InitializationFlag* init_flag, | 371 InitializationFlag* init_flag, |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
446 Isolate* isolate = scope_info->GetIsolate(); | 457 Isolate* isolate = scope_info->GetIsolate(); |
447 int local_count = scope_info->ContextLocalCount(); | 458 int local_count = scope_info->ContextLocalCount(); |
448 if (local_count == 0) return true; | 459 if (local_count == 0) return true; |
449 // Fill all context locals to the context extension. | 460 // Fill all context locals to the context extension. |
450 int first_context_var = scope_info->StackLocalCount(); | 461 int first_context_var = scope_info->StackLocalCount(); |
451 int start = scope_info->ContextLocalNameEntriesIndex(); | 462 int start = scope_info->ContextLocalNameEntriesIndex(); |
452 for (int i = 0; i < local_count; ++i) { | 463 for (int i = 0; i < local_count; ++i) { |
453 if (scope_info->LocalIsSynthetic(first_context_var + i)) continue; | 464 if (scope_info->LocalIsSynthetic(first_context_var + i)) continue; |
454 int context_index = Context::MIN_CONTEXT_SLOTS + i; | 465 int context_index = Context::MIN_CONTEXT_SLOTS + i; |
455 Handle<Object> value = Handle<Object>(context->get(context_index), isolate); | 466 Handle<Object> value = Handle<Object>(context->get(context_index), isolate); |
456 // Do not reflect variables under TDZ in scope object. | 467 // Reflect variables under TDZ as undefined in scope object. |
457 if (value->IsTheHole()) continue; | 468 if (value->IsTheHole()) continue; |
458 RETURN_ON_EXCEPTION_VALUE( | 469 RETURN_ON_EXCEPTION_VALUE( |
459 isolate, Runtime::DefineObjectProperty( | 470 isolate, Runtime::DefineObjectProperty( |
460 scope_object, | 471 scope_object, |
461 Handle<String>(String::cast(scope_info->get(i + start))), | 472 Handle<String>(String::cast(scope_info->get(i + start))), |
462 value, ::NONE), | 473 value, ::NONE), |
463 false); | 474 false); |
464 } | 475 } |
465 return true; | 476 return true; |
466 } | 477 } |
467 | 478 |
468 | 479 |
469 int ScopeInfo::ParameterEntriesIndex() { | 480 int ScopeInfo::ParameterEntriesIndex() { |
470 DCHECK(length() > 0); | 481 DCHECK(length() > 0); |
471 return kVariablePartIndex; | 482 return kVariablePartIndex; |
472 } | 483 } |
473 | 484 |
474 | 485 |
| 486 int ScopeInfo::StackLocalFirstSlotIndex() { |
| 487 return ParameterEntriesIndex() + ParameterCount(); |
| 488 } |
| 489 |
| 490 |
475 int ScopeInfo::StackLocalEntriesIndex() { | 491 int ScopeInfo::StackLocalEntriesIndex() { |
476 return ParameterEntriesIndex() + ParameterCount(); | 492 return StackLocalFirstSlotIndex() + 1; |
477 } | 493 } |
478 | 494 |
479 | 495 |
480 int ScopeInfo::ContextLocalNameEntriesIndex() { | 496 int ScopeInfo::ContextLocalNameEntriesIndex() { |
481 return StackLocalEntriesIndex() + StackLocalCount(); | 497 return StackLocalEntriesIndex() + StackLocalCount(); |
482 } | 498 } |
483 | 499 |
484 | 500 |
485 int ScopeInfo::ContextLocalInfoEntriesIndex() { | 501 int ScopeInfo::ContextLocalInfoEntriesIndex() { |
486 return ContextLocalNameEntriesIndex() + ContextLocalCount(); | 502 return ContextLocalNameEntriesIndex() + ContextLocalCount(); |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
643 info->set_name(i, *(it.export_name()->string())); | 659 info->set_name(i, *(it.export_name()->string())); |
644 info->set_mode(i, var->mode()); | 660 info->set_mode(i, var->mode()); |
645 DCHECK(var->index() >= 0); | 661 DCHECK(var->index() >= 0); |
646 info->set_index(i, var->index()); | 662 info->set_index(i, var->index()); |
647 } | 663 } |
648 DCHECK(i == info->length()); | 664 DCHECK(i == info->length()); |
649 return info; | 665 return info; |
650 } | 666 } |
651 | 667 |
652 } } // namespace v8::internal | 668 } } // namespace v8::internal |
OLD | NEW |