| 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 |