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); | 30 // DCHECK(scope->StackLocalCount() >= stack_local_count); |
rossberg
2015/04/17 15:16:27
What about this?
Dmitry Lomov (no reviews)
2015/04/20 11:53:21
These are incorrect
| |
31 DCHECK(scope->ContextLocalCount() == context_local_count); | 31 DCHECK(scope->ContextLocalCount() == context_local_count); |
32 | 32 |
33 bool simple_parameter_list = | 33 bool simple_parameter_list = |
34 scope->is_function_scope() ? scope->is_simple_parameter_list() : true; | 34 scope->is_function_scope() ? scope->is_simple_parameter_list() : true; |
35 | 35 |
36 // Determine use and location of the function variable if it is present. | 36 // Determine use and location of the function variable if it is present. |
37 FunctionVariableInfo function_name_info; | 37 FunctionVariableInfo function_name_info; |
38 VariableMode function_variable_mode; | 38 VariableMode function_variable_mode; |
39 if (scope->is_function_scope() && scope->function() != NULL) { | 39 if (scope->is_function_scope() && scope->function() != NULL) { |
40 Variable* var = scope->function()->proxy()->var(); | 40 Variable* var = scope->function()->proxy()->var(); |
41 if (!var->is_used()) { | 41 if (!var->is_used()) { |
42 function_name_info = UNUSED; | 42 function_name_info = UNUSED; |
43 } else if (var->IsContextSlot()) { | 43 } else if (var->IsContextSlot()) { |
44 function_name_info = CONTEXT; | 44 function_name_info = CONTEXT; |
45 } else { | 45 } else { |
46 DCHECK(var->IsStackLocal()); | 46 DCHECK(var->IsStackLocal()); |
47 function_name_info = STACK; | 47 function_name_info = STACK; |
48 } | 48 } |
49 function_variable_mode = var->mode(); | 49 function_variable_mode = var->mode(); |
50 } else { | 50 } else { |
51 function_name_info = NONE; | 51 function_name_info = NONE; |
52 function_variable_mode = VAR; | 52 function_variable_mode = VAR; |
53 } | 53 } |
54 | 54 |
55 const bool has_function_name = function_name_info != NONE; | 55 const bool has_function_name = function_name_info != NONE; |
56 const int parameter_count = scope->num_parameters(); | 56 const int parameter_count = scope->num_parameters(); |
57 const int length = kVariablePartIndex + parameter_count + stack_local_count + | 57 const int length = kVariablePartIndex + parameter_count + |
58 2 * context_local_count + | 58 (1 + stack_local_count) + 2 * context_local_count + |
59 3 * strong_mode_free_variable_count + | 59 3 * strong_mode_free_variable_count + |
60 (has_function_name ? 2 : 0); | 60 (has_function_name ? 2 : 0); |
61 | 61 |
62 Factory* factory = isolate->factory(); | 62 Factory* factory = isolate->factory(); |
63 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); | 63 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); |
64 | 64 |
65 // Encode the flags. | 65 // Encode the flags. |
66 int flags = ScopeTypeField::encode(scope->scope_type()) | | 66 int flags = ScopeTypeField::encode(scope->scope_type()) | |
67 CallsEvalField::encode(scope->calls_eval()) | | 67 CallsEvalField::encode(scope->calls_eval()) | |
68 LanguageModeField::encode(scope->language_mode()) | | 68 LanguageModeField::encode(scope->language_mode()) | |
(...skipping 13 matching lines...) Expand all Loading... | |
82 int index = kVariablePartIndex; | 82 int index = kVariablePartIndex; |
83 // Add parameters. | 83 // Add parameters. |
84 DCHECK(index == scope_info->ParameterEntriesIndex()); | 84 DCHECK(index == scope_info->ParameterEntriesIndex()); |
85 for (int i = 0; i < parameter_count; ++i) { | 85 for (int i = 0; i < parameter_count; ++i) { |
86 scope_info->set(index++, *scope->parameter(i)->name()); | 86 scope_info->set(index++, *scope->parameter(i)->name()); |
87 } | 87 } |
88 | 88 |
89 // Add stack locals' names. We are assuming that the stack locals' | 89 // Add stack locals' names. We are assuming that the stack locals' |
90 // slots are allocated in increasing order, so we can simply add | 90 // slots are allocated in increasing order, so we can simply add |
91 // them to the ScopeInfo object. | 91 // them to the ScopeInfo object. |
92 int first_slot_index; | |
93 if (stack_local_count > 0) { | |
94 first_slot_index = stack_locals[0]->index(); | |
95 } else { | |
96 first_slot_index = 0; | |
97 } | |
98 DCHECK(index == scope_info->StackLocalFirstSlotIndex()); | |
99 scope_info->set(index++, Smi::FromInt(first_slot_index)); | |
92 DCHECK(index == scope_info->StackLocalEntriesIndex()); | 100 DCHECK(index == scope_info->StackLocalEntriesIndex()); |
93 for (int i = 0; i < stack_local_count; ++i) { | 101 for (int i = 0; i < stack_local_count; ++i) { |
94 DCHECK(stack_locals[i]->index() == i); | 102 DCHECK(stack_locals[i]->index() == first_slot_index + i); |
95 scope_info->set(index++, *stack_locals[i]->name()); | 103 scope_info->set(index++, *stack_locals[i]->name()); |
96 } | 104 } |
97 | 105 |
98 // Due to usage analysis, context-allocated locals are not necessarily in | 106 // Due to usage analysis, context-allocated locals are not necessarily in |
99 // increasing order: Some of them may be parameters which are allocated before | 107 // increasing order: Some of them may be parameters which are allocated before |
100 // the non-parameter locals. When the non-parameter locals are sorted | 108 // the non-parameter locals. When the non-parameter locals are sorted |
101 // according to usage, the allocated slot indices may not be in increasing | 109 // 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 | 110 // 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. | 111 // context slot index before adding them to the ScopeInfo object. |
104 context_locals.Sort(&Variable::CompareIndex); | 112 context_locals.Sort(&Variable::CompareIndex); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
138 ->strong_mode_reference_end_position())); | 146 ->strong_mode_reference_end_position())); |
139 scope_info->set(index++, *end_position); | 147 scope_info->set(index++, *end_position); |
140 } | 148 } |
141 | 149 |
142 // If present, add the function variable name and its index. | 150 // If present, add the function variable name and its index. |
143 DCHECK(index == scope_info->FunctionNameEntryIndex()); | 151 DCHECK(index == scope_info->FunctionNameEntryIndex()); |
144 if (has_function_name) { | 152 if (has_function_name) { |
145 int var_index = scope->function()->proxy()->var()->index(); | 153 int var_index = scope->function()->proxy()->var()->index(); |
146 scope_info->set(index++, *scope->function()->proxy()->name()); | 154 scope_info->set(index++, *scope->function()->proxy()->name()); |
147 scope_info->set(index++, Smi::FromInt(var_index)); | 155 scope_info->set(index++, Smi::FromInt(var_index)); |
156 /* | |
rossberg
2015/04/17 15:16:27
TODO?
Dmitry Lomov (no reviews)
2015/04/20 11:53:20
Done.
| |
148 DCHECK(function_name_info != STACK || | 157 DCHECK(function_name_info != STACK || |
149 (var_index == scope_info->StackLocalCount() && | 158 (var_index == scope_info->StackLocalCount() && |
150 var_index == scope_info->StackSlotCount() - 1)); | 159 var_index == scope_info->StackSlotCount() - 1)); |
160 */ | |
151 DCHECK(function_name_info != CONTEXT || | 161 DCHECK(function_name_info != CONTEXT || |
152 var_index == scope_info->ContextLength() - 1); | 162 var_index == scope_info->ContextLength() - 1); |
153 } | 163 } |
154 | 164 |
155 DCHECK(index == scope_info->length()); | 165 DCHECK(index == scope_info->length()); |
156 DCHECK(scope->num_parameters() == scope_info->ParameterCount()); | 166 DCHECK(scope->num_parameters() == scope_info->ParameterCount()); |
157 DCHECK(scope->num_stack_slots() == scope_info->StackSlotCount()); | 167 // DCHECK(scope->is_block_scope() || scope->num_stack_slots() == |
rossberg
2015/04/17 15:16:27
TODO?
Dmitry Lomov (no reviews)
2015/04/20 11:53:21
Done.
| |
168 // scope_info->StackSlotCount()); | |
158 DCHECK(scope->num_heap_slots() == scope_info->ContextLength() || | 169 DCHECK(scope->num_heap_slots() == scope_info->ContextLength() || |
159 (scope->num_heap_slots() == kVariablePartIndex && | 170 (scope->num_heap_slots() == kVariablePartIndex && |
160 scope_info->ContextLength() == 0)); | 171 scope_info->ContextLength() == 0)); |
161 return scope_info; | 172 return scope_info; |
162 } | 173 } |
163 | 174 |
164 | 175 |
165 ScopeInfo* ScopeInfo::Empty(Isolate* isolate) { | 176 ScopeInfo* ScopeInfo::Empty(Isolate* isolate) { |
166 return reinterpret_cast<ScopeInfo*>(isolate->heap()->empty_fixed_array()); | 177 return reinterpret_cast<ScopeInfo*>(isolate->heap()->empty_fixed_array()); |
167 } | 178 } |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
262 } | 273 } |
263 | 274 |
264 | 275 |
265 String* ScopeInfo::StackLocalName(int var) { | 276 String* ScopeInfo::StackLocalName(int var) { |
266 DCHECK(0 <= var && var < StackLocalCount()); | 277 DCHECK(0 <= var && var < StackLocalCount()); |
267 int info_index = StackLocalEntriesIndex() + var; | 278 int info_index = StackLocalEntriesIndex() + var; |
268 return String::cast(get(info_index)); | 279 return String::cast(get(info_index)); |
269 } | 280 } |
270 | 281 |
271 | 282 |
283 int ScopeInfo::StackLocalIndex(int var) { | |
284 DCHECK(0 <= var && var < StackLocalCount()); | |
285 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value(); | |
286 return first_slot_index + var; | |
287 } | |
288 | |
289 | |
272 String* ScopeInfo::ContextLocalName(int var) { | 290 String* ScopeInfo::ContextLocalName(int var) { |
273 DCHECK(0 <= var && var < ContextLocalCount()); | 291 DCHECK(0 <= var && var < ContextLocalCount()); |
274 int info_index = ContextLocalNameEntriesIndex() + var; | 292 int info_index = ContextLocalNameEntriesIndex() + var; |
275 return String::cast(get(info_index)); | 293 return String::cast(get(info_index)); |
276 } | 294 } |
277 | 295 |
278 | 296 |
279 VariableMode ScopeInfo::ContextLocalMode(int var) { | 297 VariableMode ScopeInfo::ContextLocalMode(int var) { |
280 DCHECK(0 <= var && var < ContextLocalCount()); | 298 DCHECK(0 <= var && var < ContextLocalCount()); |
281 int info_index = ContextLocalInfoEntriesIndex() + var; | 299 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); | 354 bool ok = get(info_index)->ToInt32(&value); |
337 USE(ok); | 355 USE(ok); |
338 DCHECK(ok); | 356 DCHECK(ok); |
339 return value; | 357 return value; |
340 } | 358 } |
341 | 359 |
342 | 360 |
343 int ScopeInfo::StackSlotIndex(String* name) { | 361 int ScopeInfo::StackSlotIndex(String* name) { |
344 DCHECK(name->IsInternalizedString()); | 362 DCHECK(name->IsInternalizedString()); |
345 if (length() > 0) { | 363 if (length() > 0) { |
364 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value(); | |
346 int start = StackLocalEntriesIndex(); | 365 int start = StackLocalEntriesIndex(); |
347 int end = StackLocalEntriesIndex() + StackLocalCount(); | 366 int end = StackLocalEntriesIndex() + StackLocalCount(); |
348 for (int i = start; i < end; ++i) { | 367 for (int i = start; i < end; ++i) { |
349 if (name == get(i)) { | 368 if (name == get(i)) { |
350 return i - start; | 369 return i - start + first_slot_index; |
351 } | 370 } |
352 } | 371 } |
353 } | 372 } |
354 return -1; | 373 return -1; |
355 } | 374 } |
356 | 375 |
357 | 376 |
358 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info, | 377 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info, |
359 Handle<String> name, VariableMode* mode, | 378 Handle<String> name, VariableMode* mode, |
360 InitializationFlag* init_flag, | 379 InitializationFlag* init_flag, |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
447 int local_count = scope_info->ContextLocalCount(); | 466 int local_count = scope_info->ContextLocalCount(); |
448 if (local_count == 0) return true; | 467 if (local_count == 0) return true; |
449 // Fill all context locals to the context extension. | 468 // Fill all context locals to the context extension. |
450 int first_context_var = scope_info->StackLocalCount(); | 469 int first_context_var = scope_info->StackLocalCount(); |
451 int start = scope_info->ContextLocalNameEntriesIndex(); | 470 int start = scope_info->ContextLocalNameEntriesIndex(); |
452 for (int i = 0; i < local_count; ++i) { | 471 for (int i = 0; i < local_count; ++i) { |
453 if (scope_info->LocalIsSynthetic(first_context_var + i)) continue; | 472 if (scope_info->LocalIsSynthetic(first_context_var + i)) continue; |
454 int context_index = Context::MIN_CONTEXT_SLOTS + i; | 473 int context_index = Context::MIN_CONTEXT_SLOTS + i; |
455 Handle<Object> value = Handle<Object>(context->get(context_index), isolate); | 474 Handle<Object> value = Handle<Object>(context->get(context_index), isolate); |
456 // Do not reflect variables under TDZ in scope object. | 475 // Do not reflect variables under TDZ in scope object. |
457 if (value->IsTheHole()) continue; | 476 if (value->IsTheHole()) { |
477 value = isolate->factory()->undefined_value(); | |
rossberg
2015/04/17 15:16:27
Same as earlier (also, the comment now is out of s
Dmitry Lomov (no reviews)
2015/04/20 11:53:21
Removed. This is not needed.
| |
478 } | |
458 RETURN_ON_EXCEPTION_VALUE( | 479 RETURN_ON_EXCEPTION_VALUE( |
459 isolate, Runtime::DefineObjectProperty( | 480 isolate, Runtime::DefineObjectProperty( |
460 scope_object, | 481 scope_object, |
461 Handle<String>(String::cast(scope_info->get(i + start))), | 482 Handle<String>(String::cast(scope_info->get(i + start))), |
462 value, ::NONE), | 483 value, ::NONE), |
463 false); | 484 false); |
464 } | 485 } |
465 return true; | 486 return true; |
466 } | 487 } |
467 | 488 |
468 | 489 |
469 int ScopeInfo::ParameterEntriesIndex() { | 490 int ScopeInfo::ParameterEntriesIndex() { |
470 DCHECK(length() > 0); | 491 DCHECK(length() > 0); |
471 return kVariablePartIndex; | 492 return kVariablePartIndex; |
472 } | 493 } |
473 | 494 |
474 | 495 |
496 int ScopeInfo::StackLocalFirstSlotIndex() { | |
497 return ParameterEntriesIndex() + ParameterCount(); | |
498 } | |
499 | |
500 | |
475 int ScopeInfo::StackLocalEntriesIndex() { | 501 int ScopeInfo::StackLocalEntriesIndex() { |
476 return ParameterEntriesIndex() + ParameterCount(); | 502 return StackLocalFirstSlotIndex() + 1; |
477 } | 503 } |
478 | 504 |
479 | 505 |
480 int ScopeInfo::ContextLocalNameEntriesIndex() { | 506 int ScopeInfo::ContextLocalNameEntriesIndex() { |
481 return StackLocalEntriesIndex() + StackLocalCount(); | 507 return StackLocalEntriesIndex() + StackLocalCount(); |
482 } | 508 } |
483 | 509 |
484 | 510 |
485 int ScopeInfo::ContextLocalInfoEntriesIndex() { | 511 int ScopeInfo::ContextLocalInfoEntriesIndex() { |
486 return ContextLocalNameEntriesIndex() + ContextLocalCount(); | 512 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())); | 669 info->set_name(i, *(it.export_name()->string())); |
644 info->set_mode(i, var->mode()); | 670 info->set_mode(i, var->mode()); |
645 DCHECK(var->index() >= 0); | 671 DCHECK(var->index() >= 0); |
646 info->set_index(i, var->index()); | 672 info->set_index(i, var->index()); |
647 } | 673 } |
648 DCHECK(i == info->length()); | 674 DCHECK(i == info->length()); |
649 return info; | 675 return info; |
650 } | 676 } |
651 | 677 |
652 } } // namespace v8::internal | 678 } } // namespace v8::internal |
OLD | NEW |