| 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 scope->CollectStackAndContextLocals(&stack_locals, &context_locals); | 21 ZoneList<Variable*> strong_mode_free_variables(0, zone); |
| 22 |
| 23 scope->CollectStackAndContextLocals(&stack_locals, &context_locals, |
| 24 &strong_mode_free_variables); |
| 22 const int stack_local_count = stack_locals.length(); | 25 const int stack_local_count = stack_locals.length(); |
| 23 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 = |
| 28 strong_mode_free_variables.length(); |
| 24 // Make sure we allocate the correct amount. | 29 // Make sure we allocate the correct amount. |
| 25 DCHECK(scope->StackLocalCount() == stack_local_count); | 30 DCHECK(scope->StackLocalCount() == stack_local_count); |
| 26 DCHECK(scope->ContextLocalCount() == context_local_count); | 31 DCHECK(scope->ContextLocalCount() == context_local_count); |
| 27 | 32 |
| 28 bool simple_parameter_list = | 33 bool simple_parameter_list = |
| 29 scope->is_function_scope() ? scope->is_simple_parameter_list() : true; | 34 scope->is_function_scope() ? scope->is_simple_parameter_list() : true; |
| 30 | 35 |
| 31 // 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. |
| 32 FunctionVariableInfo function_name_info; | 37 FunctionVariableInfo function_name_info; |
| 33 VariableMode function_variable_mode; | 38 VariableMode function_variable_mode; |
| 34 if (scope->is_function_scope() && scope->function() != NULL) { | 39 if (scope->is_function_scope() && scope->function() != NULL) { |
| 35 Variable* var = scope->function()->proxy()->var(); | 40 Variable* var = scope->function()->proxy()->var(); |
| 36 if (!var->is_used()) { | 41 if (!var->is_used()) { |
| 37 function_name_info = UNUSED; | 42 function_name_info = UNUSED; |
| 38 } else if (var->IsContextSlot()) { | 43 } else if (var->IsContextSlot()) { |
| 39 function_name_info = CONTEXT; | 44 function_name_info = CONTEXT; |
| 40 } else { | 45 } else { |
| 41 DCHECK(var->IsStackLocal()); | 46 DCHECK(var->IsStackLocal()); |
| 42 function_name_info = STACK; | 47 function_name_info = STACK; |
| 43 } | 48 } |
| 44 function_variable_mode = var->mode(); | 49 function_variable_mode = var->mode(); |
| 45 } else { | 50 } else { |
| 46 function_name_info = NONE; | 51 function_name_info = NONE; |
| 47 function_variable_mode = VAR; | 52 function_variable_mode = VAR; |
| 48 } | 53 } |
| 49 | 54 |
| 50 const bool has_function_name = function_name_info != NONE; | 55 const bool has_function_name = function_name_info != NONE; |
| 51 const int parameter_count = scope->num_parameters(); | 56 const int parameter_count = scope->num_parameters(); |
| 52 const int length = kVariablePartIndex | 57 const int length = kVariablePartIndex + parameter_count + stack_local_count + |
| 53 + parameter_count + stack_local_count + 2 * context_local_count | 58 2 * context_local_count + (has_function_name ? 2 : 0) + |
| 54 + (has_function_name ? 2 : 0); | 59 strong_mode_free_variable_count; |
| 55 | 60 |
| 56 Factory* factory = isolate->factory(); | 61 Factory* factory = isolate->factory(); |
| 57 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); | 62 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); |
| 58 | 63 |
| 59 // Encode the flags. | 64 // Encode the flags. |
| 60 int flags = ScopeTypeField::encode(scope->scope_type()) | | 65 int flags = ScopeTypeField::encode(scope->scope_type()) | |
| 61 CallsEvalField::encode(scope->calls_eval()) | | 66 CallsEvalField::encode(scope->calls_eval()) | |
| 62 LanguageModeField::encode(scope->language_mode()) | | 67 LanguageModeField::encode(scope->language_mode()) | |
| 63 FunctionVariableField::encode(function_name_info) | | 68 FunctionVariableField::encode(function_name_info) | |
| 64 FunctionVariableMode::encode(function_variable_mode) | | 69 FunctionVariableMode::encode(function_variable_mode) | |
| 65 AsmModuleField::encode(scope->asm_module()) | | 70 AsmModuleField::encode(scope->asm_module()) | |
| 66 AsmFunctionField::encode(scope->asm_function()) | | 71 AsmFunctionField::encode(scope->asm_function()) | |
| 67 IsSimpleParameterListField::encode(simple_parameter_list) | | 72 IsSimpleParameterListField::encode(simple_parameter_list) | |
| 68 BlockScopeIsClassScopeField::encode(scope->is_class_scope()) | | 73 BlockScopeIsClassScopeField::encode(scope->is_class_scope()) | |
| 69 FunctionKindField::encode(scope->function_kind()); | 74 FunctionKindField::encode(scope->function_kind()); |
| 70 scope_info->SetFlags(flags); | 75 scope_info->SetFlags(flags); |
| 71 scope_info->SetParameterCount(parameter_count); | 76 scope_info->SetParameterCount(parameter_count); |
| 72 scope_info->SetStackLocalCount(stack_local_count); | 77 scope_info->SetStackLocalCount(stack_local_count); |
| 73 scope_info->SetContextLocalCount(context_local_count); | 78 scope_info->SetContextLocalCount(context_local_count); |
| 79 scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count); |
| 74 | 80 |
| 75 int index = kVariablePartIndex; | 81 int index = kVariablePartIndex; |
| 76 // Add parameters. | 82 // Add parameters. |
| 77 DCHECK(index == scope_info->ParameterEntriesIndex()); | 83 DCHECK(index == scope_info->ParameterEntriesIndex()); |
| 78 for (int i = 0; i < parameter_count; ++i) { | 84 for (int i = 0; i < parameter_count; ++i) { |
| 79 scope_info->set(index++, *scope->parameter(i)->name()); | 85 scope_info->set(index++, *scope->parameter(i)->name()); |
| 80 } | 86 } |
| 81 | 87 |
| 82 // Add stack locals' names. We are assuming that the stack locals' | 88 // Add stack locals' names. We are assuming that the stack locals' |
| 83 // slots are allocated in increasing order, so we can simply add | 89 // slots are allocated in increasing order, so we can simply add |
| (...skipping 22 matching lines...) Expand all Loading... |
| 106 DCHECK(index == scope_info->ContextLocalInfoEntriesIndex()); | 112 DCHECK(index == scope_info->ContextLocalInfoEntriesIndex()); |
| 107 for (int i = 0; i < context_local_count; ++i) { | 113 for (int i = 0; i < context_local_count; ++i) { |
| 108 Variable* var = context_locals[i]; | 114 Variable* var = context_locals[i]; |
| 109 uint32_t value = | 115 uint32_t value = |
| 110 ContextLocalMode::encode(var->mode()) | | 116 ContextLocalMode::encode(var->mode()) | |
| 111 ContextLocalInitFlag::encode(var->initialization_flag()) | | 117 ContextLocalInitFlag::encode(var->initialization_flag()) | |
| 112 ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned()); | 118 ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned()); |
| 113 scope_info->set(index++, Smi::FromInt(value)); | 119 scope_info->set(index++, Smi::FromInt(value)); |
| 114 } | 120 } |
| 115 | 121 |
| 122 DCHECK(index == scope_info->StrongModeFreeVariableEntriesIndex()); |
| 123 for (int i = 0; i < strong_mode_free_variable_count; ++i) { |
| 124 scope_info->set(index++, *strong_mode_free_variables[i]->name()); |
| 125 } |
| 126 |
| 116 // If present, add the function variable name and its index. | 127 // If present, add the function variable name and its index. |
| 117 DCHECK(index == scope_info->FunctionNameEntryIndex()); | 128 DCHECK(index == scope_info->FunctionNameEntryIndex()); |
| 118 if (has_function_name) { | 129 if (has_function_name) { |
| 119 int var_index = scope->function()->proxy()->var()->index(); | 130 int var_index = scope->function()->proxy()->var()->index(); |
| 120 scope_info->set(index++, *scope->function()->proxy()->name()); | 131 scope_info->set(index++, *scope->function()->proxy()->name()); |
| 121 scope_info->set(index++, Smi::FromInt(var_index)); | 132 scope_info->set(index++, Smi::FromInt(var_index)); |
| 122 DCHECK(function_name_info != STACK || | 133 DCHECK(function_name_info != STACK || |
| 123 (var_index == scope_info->StackLocalCount() && | 134 (var_index == scope_info->StackLocalCount() && |
| 124 var_index == scope_info->StackSlotCount() - 1)); | 135 var_index == scope_info->StackSlotCount() - 1)); |
| 125 DCHECK(function_name_info != CONTEXT || | 136 DCHECK(function_name_info != CONTEXT || |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 DCHECK(0 <= var && var < LocalCount()); | 289 DCHECK(0 <= var && var < LocalCount()); |
| 279 // There's currently no flag stored on the ScopeInfo to indicate that a | 290 // There's currently no flag stored on the ScopeInfo to indicate that a |
| 280 // variable is a compiler-introduced temporary. However, to avoid conflict | 291 // variable is a compiler-introduced temporary. However, to avoid conflict |
| 281 // with user declarations, the current temporaries like .generator_object and | 292 // with user declarations, the current temporaries like .generator_object and |
| 282 // .result start with a dot, so we can use that as a flag. It's a hack! | 293 // .result start with a dot, so we can use that as a flag. It's a hack! |
| 283 Handle<String> name(LocalName(var)); | 294 Handle<String> name(LocalName(var)); |
| 284 return name->length() > 0 && name->Get(0) == '.'; | 295 return name->length() > 0 && name->Get(0) == '.'; |
| 285 } | 296 } |
| 286 | 297 |
| 287 | 298 |
| 299 String* ScopeInfo::StrongModeFreeVariableName(int var) { |
| 300 DCHECK(0 <= var && var < StrongModeFreeVariableCount()); |
| 301 int info_index = StrongModeFreeVariableEntriesIndex() + var; |
| 302 return String::cast(get(info_index)); |
| 303 } |
| 304 |
| 305 |
| 288 int ScopeInfo::StackSlotIndex(String* name) { | 306 int ScopeInfo::StackSlotIndex(String* name) { |
| 289 DCHECK(name->IsInternalizedString()); | 307 DCHECK(name->IsInternalizedString()); |
| 290 if (length() > 0) { | 308 if (length() > 0) { |
| 291 int start = StackLocalEntriesIndex(); | 309 int start = StackLocalEntriesIndex(); |
| 292 int end = StackLocalEntriesIndex() + StackLocalCount(); | 310 int end = StackLocalEntriesIndex() + StackLocalCount(); |
| 293 for (int i = start; i < end; ++i) { | 311 for (int i = start; i < end; ++i) { |
| 294 if (name == get(i)) { | 312 if (name == get(i)) { |
| 295 return i - start; | 313 return i - start; |
| 296 } | 314 } |
| 297 } | 315 } |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 int ScopeInfo::ContextLocalNameEntriesIndex() { | 443 int ScopeInfo::ContextLocalNameEntriesIndex() { |
| 426 return StackLocalEntriesIndex() + StackLocalCount(); | 444 return StackLocalEntriesIndex() + StackLocalCount(); |
| 427 } | 445 } |
| 428 | 446 |
| 429 | 447 |
| 430 int ScopeInfo::ContextLocalInfoEntriesIndex() { | 448 int ScopeInfo::ContextLocalInfoEntriesIndex() { |
| 431 return ContextLocalNameEntriesIndex() + ContextLocalCount(); | 449 return ContextLocalNameEntriesIndex() + ContextLocalCount(); |
| 432 } | 450 } |
| 433 | 451 |
| 434 | 452 |
| 453 int ScopeInfo::StrongModeFreeVariableEntriesIndex() { |
| 454 return ContextLocalInfoEntriesIndex() + ContextLocalCount(); |
| 455 } |
| 456 |
| 457 |
| 435 int ScopeInfo::FunctionNameEntryIndex() { | 458 int ScopeInfo::FunctionNameEntryIndex() { |
| 436 return ContextLocalInfoEntriesIndex() + ContextLocalCount(); | 459 return StrongModeFreeVariableEntriesIndex() + StrongModeFreeVariableCount(); |
| 437 } | 460 } |
| 438 | 461 |
| 439 | 462 |
| 440 int ContextSlotCache::Hash(Object* data, String* name) { | 463 int ContextSlotCache::Hash(Object* data, String* name) { |
| 441 // Uses only lower 32 bits if pointers are larger. | 464 // Uses only lower 32 bits if pointers are larger. |
| 442 uintptr_t addr_hash = | 465 uintptr_t addr_hash = |
| 443 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2; | 466 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2; |
| 444 return static_cast<int>((addr_hash ^ name->Hash()) % kLength); | 467 return static_cast<int>((addr_hash ^ name->Hash()) % kLength); |
| 445 } | 468 } |
| 446 | 469 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 576 info->set_name(i, *(it.export_name()->string())); | 599 info->set_name(i, *(it.export_name()->string())); |
| 577 info->set_mode(i, var->mode()); | 600 info->set_mode(i, var->mode()); |
| 578 DCHECK(var->index() >= 0); | 601 DCHECK(var->index() >= 0); |
| 579 info->set_index(i, var->index()); | 602 info->set_index(i, var->index()); |
| 580 } | 603 } |
| 581 DCHECK(i == info->length()); | 604 DCHECK(i == info->length()); |
| 582 return info; | 605 return info; |
| 583 } | 606 } |
| 584 | 607 |
| 585 } } // namespace v8::internal | 608 } } // namespace v8::internal |
| OLD | NEW |