Chromium Code Reviews| 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 + |
| 54 + (has_function_name ? 2 : 0); | 59 3 * strong_mode_free_variable_count + |
| 60 (has_function_name ? 2 : 0); | |
| 55 | 61 |
| 56 Factory* factory = isolate->factory(); | 62 Factory* factory = isolate->factory(); |
| 57 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); | 63 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); |
| 58 | 64 |
| 59 // Encode the flags. | 65 // Encode the flags. |
| 60 int flags = ScopeTypeField::encode(scope->scope_type()) | | 66 int flags = ScopeTypeField::encode(scope->scope_type()) | |
| 61 CallsEvalField::encode(scope->calls_eval()) | | 67 CallsEvalField::encode(scope->calls_eval()) | |
| 62 LanguageModeField::encode(scope->language_mode()) | | 68 LanguageModeField::encode(scope->language_mode()) | |
| 63 FunctionVariableField::encode(function_name_info) | | 69 FunctionVariableField::encode(function_name_info) | |
| 64 FunctionVariableMode::encode(function_variable_mode) | | 70 FunctionVariableMode::encode(function_variable_mode) | |
| 65 AsmModuleField::encode(scope->asm_module()) | | 71 AsmModuleField::encode(scope->asm_module()) | |
| 66 AsmFunctionField::encode(scope->asm_function()) | | 72 AsmFunctionField::encode(scope->asm_function()) | |
| 67 IsSimpleParameterListField::encode(simple_parameter_list) | | 73 IsSimpleParameterListField::encode(simple_parameter_list) | |
| 68 BlockScopeIsClassScopeField::encode(scope->is_class_scope()) | | 74 BlockScopeIsClassScopeField::encode(scope->is_class_scope()) | |
| 69 FunctionKindField::encode(scope->function_kind()); | 75 FunctionKindField::encode(scope->function_kind()); |
| 70 scope_info->SetFlags(flags); | 76 scope_info->SetFlags(flags); |
| 71 scope_info->SetParameterCount(parameter_count); | 77 scope_info->SetParameterCount(parameter_count); |
| 72 scope_info->SetStackLocalCount(stack_local_count); | 78 scope_info->SetStackLocalCount(stack_local_count); |
| 73 scope_info->SetContextLocalCount(context_local_count); | 79 scope_info->SetContextLocalCount(context_local_count); |
| 80 scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count); | |
| 74 | 81 |
| 75 int index = kVariablePartIndex; | 82 int index = kVariablePartIndex; |
| 76 // Add parameters. | 83 // Add parameters. |
| 77 DCHECK(index == scope_info->ParameterEntriesIndex()); | 84 DCHECK(index == scope_info->ParameterEntriesIndex()); |
| 78 for (int i = 0; i < parameter_count; ++i) { | 85 for (int i = 0; i < parameter_count; ++i) { |
| 79 scope_info->set(index++, *scope->parameter(i)->name()); | 86 scope_info->set(index++, *scope->parameter(i)->name()); |
| 80 } | 87 } |
| 81 | 88 |
| 82 // Add stack locals' names. We are assuming that the stack locals' | 89 // Add stack locals' names. We are assuming that the stack locals' |
| 83 // slots are allocated in increasing order, so we can simply add | 90 // slots are allocated in increasing order, so we can simply add |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 106 DCHECK(index == scope_info->ContextLocalInfoEntriesIndex()); | 113 DCHECK(index == scope_info->ContextLocalInfoEntriesIndex()); |
| 107 for (int i = 0; i < context_local_count; ++i) { | 114 for (int i = 0; i < context_local_count; ++i) { |
| 108 Variable* var = context_locals[i]; | 115 Variable* var = context_locals[i]; |
| 109 uint32_t value = | 116 uint32_t value = |
| 110 ContextLocalMode::encode(var->mode()) | | 117 ContextLocalMode::encode(var->mode()) | |
| 111 ContextLocalInitFlag::encode(var->initialization_flag()) | | 118 ContextLocalInitFlag::encode(var->initialization_flag()) | |
| 112 ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned()); | 119 ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned()); |
| 113 scope_info->set(index++, Smi::FromInt(value)); | 120 scope_info->set(index++, Smi::FromInt(value)); |
| 114 } | 121 } |
| 115 | 122 |
| 123 DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex()); | |
| 124 for (int i = 0; i < strong_mode_free_variable_count; ++i) { | |
| 125 scope_info->set(index++, *strong_mode_free_variables[i]->name()); | |
| 126 } | |
| 127 | |
| 128 DCHECK(index == scope_info->StrongModeFreeVariablePositionEntriesIndex()); | |
| 129 for (int i = 0; i < strong_mode_free_variable_count; ++i) { | |
| 130 int start_position = | |
| 131 strong_mode_free_variables[i]->strong_mode_reference_start_position(); | |
| 132 if (Smi::IsValid(start_position)) { | |
|
Dmitry Lomov (no reviews)
2015/03/24 14:51:46
Factory::NewNumberFromInt does this.
marja
2015/03/24 16:46:14
Done.
| |
| 133 scope_info->set(index++, Smi::FromInt(start_position)); | |
| 134 } else { | |
| 135 Handle<HeapNumber> number = factory->NewHeapNumber(start_position); | |
| 136 scope_info->set(index++, *number); | |
| 137 } | |
| 138 int end_position = | |
| 139 strong_mode_free_variables[i]->strong_mode_reference_end_position(); | |
| 140 if (Smi::IsValid(end_position)) { | |
| 141 scope_info->set(index++, Smi::FromInt(end_position)); | |
| 142 } else { | |
| 143 Handle<HeapNumber> number = factory->NewHeapNumber(end_position); | |
| 144 scope_info->set(index++, *number); | |
| 145 } | |
| 146 } | |
| 147 | |
| 116 // If present, add the function variable name and its index. | 148 // If present, add the function variable name and its index. |
| 117 DCHECK(index == scope_info->FunctionNameEntryIndex()); | 149 DCHECK(index == scope_info->FunctionNameEntryIndex()); |
| 118 if (has_function_name) { | 150 if (has_function_name) { |
| 119 int var_index = scope->function()->proxy()->var()->index(); | 151 int var_index = scope->function()->proxy()->var()->index(); |
| 120 scope_info->set(index++, *scope->function()->proxy()->name()); | 152 scope_info->set(index++, *scope->function()->proxy()->name()); |
| 121 scope_info->set(index++, Smi::FromInt(var_index)); | 153 scope_info->set(index++, Smi::FromInt(var_index)); |
| 122 DCHECK(function_name_info != STACK || | 154 DCHECK(function_name_info != STACK || |
| 123 (var_index == scope_info->StackLocalCount() && | 155 (var_index == scope_info->StackLocalCount() && |
| 124 var_index == scope_info->StackSlotCount() - 1)); | 156 var_index == scope_info->StackSlotCount() - 1)); |
| 125 DCHECK(function_name_info != CONTEXT || | 157 DCHECK(function_name_info != CONTEXT || |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 278 DCHECK(0 <= var && var < LocalCount()); | 310 DCHECK(0 <= var && var < LocalCount()); |
| 279 // There's currently no flag stored on the ScopeInfo to indicate that a | 311 // There's currently no flag stored on the ScopeInfo to indicate that a |
| 280 // variable is a compiler-introduced temporary. However, to avoid conflict | 312 // variable is a compiler-introduced temporary. However, to avoid conflict |
| 281 // with user declarations, the current temporaries like .generator_object and | 313 // 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! | 314 // .result start with a dot, so we can use that as a flag. It's a hack! |
| 283 Handle<String> name(LocalName(var)); | 315 Handle<String> name(LocalName(var)); |
| 284 return name->length() > 0 && name->Get(0) == '.'; | 316 return name->length() > 0 && name->Get(0) == '.'; |
| 285 } | 317 } |
| 286 | 318 |
| 287 | 319 |
| 320 String* ScopeInfo::StrongModeFreeVariableName(int var) { | |
| 321 DCHECK(0 <= var && var < StrongModeFreeVariableCount()); | |
| 322 int info_index = StrongModeFreeVariableNameEntriesIndex() + var; | |
| 323 return String::cast(get(info_index)); | |
| 324 } | |
| 325 | |
| 326 | |
| 327 namespace { | |
| 328 | |
| 329 int IntFromSmiOrHeapNumber(Object* value) { | |
| 330 if (value->IsSmi()) return Smi::cast(value)->value(); | |
| 331 DCHECK(value->IsHeapNumber()); | |
| 332 return static_cast<int>(HeapNumber::cast(value)->value()); | |
| 333 } | |
| 334 | |
| 335 } // namespace | |
| 336 | |
| 337 | |
| 338 int ScopeInfo::StrongModeFreeVariableStartPosition(int var) { | |
| 339 DCHECK(0 <= var && var < StrongModeFreeVariableCount()); | |
| 340 int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2; | |
| 341 return IntFromSmiOrHeapNumber(get(info_index)); | |
| 342 } | |
| 343 | |
| 344 | |
| 345 int ScopeInfo::StrongModeFreeVariableEndPosition(int var) { | |
| 346 DCHECK(0 <= var && var < StrongModeFreeVariableCount()); | |
| 347 int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2 + 1; | |
| 348 return IntFromSmiOrHeapNumber(get(info_index)); | |
| 349 } | |
| 350 | |
| 351 | |
| 288 int ScopeInfo::StackSlotIndex(String* name) { | 352 int ScopeInfo::StackSlotIndex(String* name) { |
| 289 DCHECK(name->IsInternalizedString()); | 353 DCHECK(name->IsInternalizedString()); |
| 290 if (length() > 0) { | 354 if (length() > 0) { |
| 291 int start = StackLocalEntriesIndex(); | 355 int start = StackLocalEntriesIndex(); |
| 292 int end = StackLocalEntriesIndex() + StackLocalCount(); | 356 int end = StackLocalEntriesIndex() + StackLocalCount(); |
| 293 for (int i = start; i < end; ++i) { | 357 for (int i = start; i < end; ++i) { |
| 294 if (name == get(i)) { | 358 if (name == get(i)) { |
| 295 return i - start; | 359 return i - start; |
| 296 } | 360 } |
| 297 } | 361 } |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 425 int ScopeInfo::ContextLocalNameEntriesIndex() { | 489 int ScopeInfo::ContextLocalNameEntriesIndex() { |
| 426 return StackLocalEntriesIndex() + StackLocalCount(); | 490 return StackLocalEntriesIndex() + StackLocalCount(); |
| 427 } | 491 } |
| 428 | 492 |
| 429 | 493 |
| 430 int ScopeInfo::ContextLocalInfoEntriesIndex() { | 494 int ScopeInfo::ContextLocalInfoEntriesIndex() { |
| 431 return ContextLocalNameEntriesIndex() + ContextLocalCount(); | 495 return ContextLocalNameEntriesIndex() + ContextLocalCount(); |
| 432 } | 496 } |
| 433 | 497 |
| 434 | 498 |
| 499 int ScopeInfo::StrongModeFreeVariableNameEntriesIndex() { | |
| 500 return ContextLocalInfoEntriesIndex() + ContextLocalCount(); | |
| 501 } | |
| 502 | |
| 503 | |
| 504 int ScopeInfo::StrongModeFreeVariablePositionEntriesIndex() { | |
| 505 return StrongModeFreeVariableNameEntriesIndex() + | |
| 506 StrongModeFreeVariableCount(); | |
| 507 } | |
| 508 | |
| 509 | |
| 435 int ScopeInfo::FunctionNameEntryIndex() { | 510 int ScopeInfo::FunctionNameEntryIndex() { |
| 436 return ContextLocalInfoEntriesIndex() + ContextLocalCount(); | 511 return StrongModeFreeVariablePositionEntriesIndex() + |
| 512 2 * StrongModeFreeVariableCount(); | |
| 437 } | 513 } |
| 438 | 514 |
| 439 | 515 |
| 440 int ContextSlotCache::Hash(Object* data, String* name) { | 516 int ContextSlotCache::Hash(Object* data, String* name) { |
| 441 // Uses only lower 32 bits if pointers are larger. | 517 // Uses only lower 32 bits if pointers are larger. |
| 442 uintptr_t addr_hash = | 518 uintptr_t addr_hash = |
| 443 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2; | 519 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2; |
| 444 return static_cast<int>((addr_hash ^ name->Hash()) % kLength); | 520 return static_cast<int>((addr_hash ^ name->Hash()) % kLength); |
| 445 } | 521 } |
| 446 | 522 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 576 info->set_name(i, *(it.export_name()->string())); | 652 info->set_name(i, *(it.export_name()->string())); |
| 577 info->set_mode(i, var->mode()); | 653 info->set_mode(i, var->mode()); |
| 578 DCHECK(var->index() >= 0); | 654 DCHECK(var->index() >= 0); |
| 579 info->set_index(i, var->index()); | 655 info->set_index(i, var->index()); |
| 580 } | 656 } |
| 581 DCHECK(i == info->length()); | 657 DCHECK(i == info->length()); |
| 582 return info; | 658 return info; |
| 583 } | 659 } |
| 584 | 660 |
| 585 } } // namespace v8::internal | 661 } } // namespace v8::internal |
| OLD | NEW |