| 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" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 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->ContextLocalCount() == context_local_count); | 30 DCHECK(scope->ContextLocalCount() == context_local_count); |
| 31 | 31 |
| 32 bool simple_parameter_list = | 32 bool simple_parameter_list = |
| 33 scope->is_function_scope() ? scope->is_simple_parameter_list() : true; | 33 scope->is_function_scope() ? scope->is_simple_parameter_list() : true; |
| 34 | 34 |
| 35 // Determine use and location of the "this" binding if it is present. |
| 36 VariableAllocationInfo receiver_info; |
| 37 if (scope->has_this_declaration()) { |
| 38 Variable* var = scope->receiver(); |
| 39 if (!var->is_used()) { |
| 40 receiver_info = UNUSED; |
| 41 } else if (var->IsContextSlot()) { |
| 42 receiver_info = CONTEXT; |
| 43 } else { |
| 44 DCHECK(var->IsParameter()); |
| 45 receiver_info = STACK; |
| 46 } |
| 47 } else { |
| 48 receiver_info = NONE; |
| 49 } |
| 50 |
| 35 // Determine use and location of the function variable if it is present. | 51 // Determine use and location of the function variable if it is present. |
| 36 FunctionVariableInfo function_name_info; | 52 VariableAllocationInfo function_name_info; |
| 37 VariableMode function_variable_mode; | 53 VariableMode function_variable_mode; |
| 38 if (scope->is_function_scope() && scope->function() != NULL) { | 54 if (scope->is_function_scope() && scope->function() != NULL) { |
| 39 Variable* var = scope->function()->proxy()->var(); | 55 Variable* var = scope->function()->proxy()->var(); |
| 40 if (!var->is_used()) { | 56 if (!var->is_used()) { |
| 41 function_name_info = UNUSED; | 57 function_name_info = UNUSED; |
| 42 } else if (var->IsContextSlot()) { | 58 } else if (var->IsContextSlot()) { |
| 43 function_name_info = CONTEXT; | 59 function_name_info = CONTEXT; |
| 44 } else { | 60 } else { |
| 45 DCHECK(var->IsStackLocal()); | 61 DCHECK(var->IsStackLocal()); |
| 46 function_name_info = STACK; | 62 function_name_info = STACK; |
| 47 } | 63 } |
| 48 function_variable_mode = var->mode(); | 64 function_variable_mode = var->mode(); |
| 49 } else { | 65 } else { |
| 50 function_name_info = NONE; | 66 function_name_info = NONE; |
| 51 function_variable_mode = VAR; | 67 function_variable_mode = VAR; |
| 52 } | 68 } |
| 53 | 69 |
| 54 const bool has_function_name = function_name_info != NONE; | 70 const bool has_function_name = function_name_info != NONE; |
| 71 const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT; |
| 55 const int parameter_count = scope->num_parameters(); | 72 const int parameter_count = scope->num_parameters(); |
| 56 const int length = kVariablePartIndex + parameter_count + | 73 const int length = kVariablePartIndex + parameter_count + |
| 57 (1 + stack_local_count) + 2 * context_local_count + | 74 (1 + stack_local_count) + 2 * context_local_count + |
| 58 3 * strong_mode_free_variable_count + | 75 3 * strong_mode_free_variable_count + |
| 59 (has_function_name ? 2 : 0); | 76 (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0); |
| 60 | 77 |
| 61 Factory* factory = isolate->factory(); | 78 Factory* factory = isolate->factory(); |
| 62 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); | 79 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); |
| 63 | 80 |
| 64 // Encode the flags. | 81 // Encode the flags. |
| 65 int flags = ScopeTypeField::encode(scope->scope_type()) | | 82 int flags = ScopeTypeField::encode(scope->scope_type()) | |
| 66 CallsEvalField::encode(scope->calls_eval()) | | 83 CallsEvalField::encode(scope->calls_eval()) | |
| 67 LanguageModeField::encode(scope->language_mode()) | | 84 LanguageModeField::encode(scope->language_mode()) | |
| 85 ReceiverVariableField::encode(receiver_info) | |
| 68 FunctionVariableField::encode(function_name_info) | | 86 FunctionVariableField::encode(function_name_info) | |
| 69 FunctionVariableMode::encode(function_variable_mode) | | 87 FunctionVariableMode::encode(function_variable_mode) | |
| 70 AsmModuleField::encode(scope->asm_module()) | | 88 AsmModuleField::encode(scope->asm_module()) | |
| 71 AsmFunctionField::encode(scope->asm_function()) | | 89 AsmFunctionField::encode(scope->asm_function()) | |
| 72 IsSimpleParameterListField::encode(simple_parameter_list) | | 90 IsSimpleParameterListField::encode(simple_parameter_list) | |
| 73 BlockScopeIsClassScopeField::encode(scope->is_class_scope()) | | 91 BlockScopeIsClassScopeField::encode(scope->is_class_scope()) | |
| 74 FunctionKindField::encode(scope->function_kind()); | 92 FunctionKindField::encode(scope->function_kind()); |
| 75 scope_info->SetFlags(flags); | 93 scope_info->SetFlags(flags); |
| 76 scope_info->SetParameterCount(parameter_count); | 94 scope_info->SetParameterCount(parameter_count); |
| 77 scope_info->SetStackLocalCount(stack_local_count); | 95 scope_info->SetStackLocalCount(stack_local_count); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 Handle<Object> start_position = factory->NewNumberFromInt( | 157 Handle<Object> start_position = factory->NewNumberFromInt( |
| 140 static_cast<int32_t>(strong_mode_free_variables[i] | 158 static_cast<int32_t>(strong_mode_free_variables[i] |
| 141 ->strong_mode_reference_start_position())); | 159 ->strong_mode_reference_start_position())); |
| 142 scope_info->set(index++, *start_position); | 160 scope_info->set(index++, *start_position); |
| 143 Handle<Object> end_position = factory->NewNumberFromInt( | 161 Handle<Object> end_position = factory->NewNumberFromInt( |
| 144 static_cast<int32_t>(strong_mode_free_variables[i] | 162 static_cast<int32_t>(strong_mode_free_variables[i] |
| 145 ->strong_mode_reference_end_position())); | 163 ->strong_mode_reference_end_position())); |
| 146 scope_info->set(index++, *end_position); | 164 scope_info->set(index++, *end_position); |
| 147 } | 165 } |
| 148 | 166 |
| 167 // If the receiver is allocated, add its index. |
| 168 DCHECK(index == scope_info->ReceiverEntryIndex()); |
| 169 if (has_receiver) { |
| 170 int var_index = scope->receiver()->index(); |
| 171 scope_info->set(index++, Smi::FromInt(var_index)); |
| 172 // ?? DCHECK(receiver_info != CONTEXT || var_index == |
| 173 // scope_info->ContextLength() - 1); |
| 174 } |
| 175 |
| 149 // If present, add the function variable name and its index. | 176 // If present, add the function variable name and its index. |
| 150 DCHECK(index == scope_info->FunctionNameEntryIndex()); | 177 DCHECK(index == scope_info->FunctionNameEntryIndex()); |
| 151 if (has_function_name) { | 178 if (has_function_name) { |
| 152 int var_index = scope->function()->proxy()->var()->index(); | 179 int var_index = scope->function()->proxy()->var()->index(); |
| 153 scope_info->set(index++, *scope->function()->proxy()->name()); | 180 scope_info->set(index++, *scope->function()->proxy()->name()); |
| 154 scope_info->set(index++, Smi::FromInt(var_index)); | 181 scope_info->set(index++, Smi::FromInt(var_index)); |
| 155 DCHECK(function_name_info != CONTEXT || | 182 DCHECK(function_name_info != CONTEXT || |
| 156 var_index == scope_info->ContextLength() - 1); | 183 var_index == scope_info->ContextLength() - 1); |
| 157 } | 184 } |
| 158 | 185 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 scope_type() == MODULE_SCOPE; | 240 scope_type() == MODULE_SCOPE; |
| 214 if (has_context) { | 241 if (has_context) { |
| 215 return Context::MIN_CONTEXT_SLOTS + context_locals + | 242 return Context::MIN_CONTEXT_SLOTS + context_locals + |
| 216 (function_name_context_slot ? 1 : 0); | 243 (function_name_context_slot ? 1 : 0); |
| 217 } | 244 } |
| 218 } | 245 } |
| 219 return 0; | 246 return 0; |
| 220 } | 247 } |
| 221 | 248 |
| 222 | 249 |
| 250 bool ScopeInfo::HasReceiver() { |
| 251 if (length() > 0) { |
| 252 return NONE != ReceiverVariableField::decode(Flags()); |
| 253 } else { |
| 254 return false; |
| 255 } |
| 256 } |
| 257 |
| 258 |
| 259 bool ScopeInfo::HasAllocatedReceiver() { |
| 260 if (length() > 0) { |
| 261 VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags()); |
| 262 return allocation == STACK || allocation == CONTEXT; |
| 263 } else { |
| 264 return false; |
| 265 } |
| 266 } |
| 267 |
| 268 |
| 223 bool ScopeInfo::HasFunctionName() { | 269 bool ScopeInfo::HasFunctionName() { |
| 224 if (length() > 0) { | 270 if (length() > 0) { |
| 225 return NONE != FunctionVariableField::decode(Flags()); | 271 return NONE != FunctionVariableField::decode(Flags()); |
| 226 } else { | 272 } else { |
| 227 return false; | 273 return false; |
| 228 } | 274 } |
| 229 } | 275 } |
| 230 | 276 |
| 231 | 277 |
| 232 bool ScopeInfo::HasHeapAllocatedLocals() { | 278 bool ScopeInfo::HasHeapAllocatedLocals() { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 } | 356 } |
| 311 | 357 |
| 312 | 358 |
| 313 bool ScopeInfo::LocalIsSynthetic(int var) { | 359 bool ScopeInfo::LocalIsSynthetic(int var) { |
| 314 DCHECK(0 <= var && var < LocalCount()); | 360 DCHECK(0 <= var && var < LocalCount()); |
| 315 // There's currently no flag stored on the ScopeInfo to indicate that a | 361 // There's currently no flag stored on the ScopeInfo to indicate that a |
| 316 // variable is a compiler-introduced temporary. However, to avoid conflict | 362 // variable is a compiler-introduced temporary. However, to avoid conflict |
| 317 // with user declarations, the current temporaries like .generator_object and | 363 // with user declarations, the current temporaries like .generator_object and |
| 318 // .result start with a dot, so we can use that as a flag. It's a hack! | 364 // .result start with a dot, so we can use that as a flag. It's a hack! |
| 319 Handle<String> name(LocalName(var)); | 365 Handle<String> name(LocalName(var)); |
| 320 return name->length() > 0 && name->Get(0) == '.'; | 366 return (name->length() > 0 && name->Get(0) == '.') || |
| 367 name->Equals(*GetIsolate()->factory()->this_string()); |
| 321 } | 368 } |
| 322 | 369 |
| 323 | 370 |
| 324 String* ScopeInfo::StrongModeFreeVariableName(int var) { | 371 String* ScopeInfo::StrongModeFreeVariableName(int var) { |
| 325 DCHECK(0 <= var && var < StrongModeFreeVariableCount()); | 372 DCHECK(0 <= var && var < StrongModeFreeVariableCount()); |
| 326 int info_index = StrongModeFreeVariableNameEntriesIndex() + var; | 373 int info_index = StrongModeFreeVariableNameEntriesIndex() + var; |
| 327 return String::cast(get(info_index)); | 374 return String::cast(get(info_index)); |
| 328 } | 375 } |
| 329 | 376 |
| 330 | 377 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 for (int i = end - 1; i >= start; --i) { | 467 for (int i = end - 1; i >= start; --i) { |
| 421 if (name == get(i)) { | 468 if (name == get(i)) { |
| 422 return i - start; | 469 return i - start; |
| 423 } | 470 } |
| 424 } | 471 } |
| 425 } | 472 } |
| 426 return -1; | 473 return -1; |
| 427 } | 474 } |
| 428 | 475 |
| 429 | 476 |
| 477 int ScopeInfo::ReceiverContextSlotIndex() { |
| 478 if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT) |
| 479 return Smi::cast(get(ReceiverEntryIndex()))->value(); |
| 480 return -1; |
| 481 } |
| 482 |
| 483 |
| 430 int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) { | 484 int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) { |
| 431 DCHECK(name->IsInternalizedString()); | 485 DCHECK(name->IsInternalizedString()); |
| 432 DCHECK(mode != NULL); | 486 DCHECK(mode != NULL); |
| 433 if (length() > 0) { | 487 if (length() > 0) { |
| 434 if (FunctionVariableField::decode(Flags()) == CONTEXT && | 488 if (FunctionVariableField::decode(Flags()) == CONTEXT && |
| 435 FunctionName() == name) { | 489 FunctionName() == name) { |
| 436 *mode = FunctionVariableMode::decode(Flags()); | 490 *mode = FunctionVariableMode::decode(Flags()); |
| 437 return Smi::cast(get(FunctionNameEntryIndex() + 1))->value(); | 491 return Smi::cast(get(FunctionNameEntryIndex() + 1))->value(); |
| 438 } | 492 } |
| 439 } | 493 } |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 507 return ContextLocalInfoEntriesIndex() + ContextLocalCount(); | 561 return ContextLocalInfoEntriesIndex() + ContextLocalCount(); |
| 508 } | 562 } |
| 509 | 563 |
| 510 | 564 |
| 511 int ScopeInfo::StrongModeFreeVariablePositionEntriesIndex() { | 565 int ScopeInfo::StrongModeFreeVariablePositionEntriesIndex() { |
| 512 return StrongModeFreeVariableNameEntriesIndex() + | 566 return StrongModeFreeVariableNameEntriesIndex() + |
| 513 StrongModeFreeVariableCount(); | 567 StrongModeFreeVariableCount(); |
| 514 } | 568 } |
| 515 | 569 |
| 516 | 570 |
| 571 int ScopeInfo::ReceiverEntryIndex() { |
| 572 return StrongModeFreeVariablePositionEntriesIndex() + |
| 573 2 * StrongModeFreeVariableCount(); |
| 574 } |
| 575 |
| 576 |
| 517 int ScopeInfo::FunctionNameEntryIndex() { | 577 int ScopeInfo::FunctionNameEntryIndex() { |
| 518 return StrongModeFreeVariablePositionEntriesIndex() + | 578 return ReceiverEntryIndex() + (HasAllocatedReceiver() ? 1 : 0); |
| 519 2 * StrongModeFreeVariableCount(); | |
| 520 } | 579 } |
| 521 | 580 |
| 522 | 581 |
| 523 int ContextSlotCache::Hash(Object* data, String* name) { | 582 int ContextSlotCache::Hash(Object* data, String* name) { |
| 524 // Uses only lower 32 bits if pointers are larger. | 583 // Uses only lower 32 bits if pointers are larger. |
| 525 uintptr_t addr_hash = | 584 uintptr_t addr_hash = |
| 526 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2; | 585 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2; |
| 527 return static_cast<int>((addr_hash ^ name->Hash()) % kLength); | 586 return static_cast<int>((addr_hash ^ name->Hash()) % kLength); |
| 528 } | 587 } |
| 529 | 588 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 info->set_name(i, *(it.export_name()->string())); | 718 info->set_name(i, *(it.export_name()->string())); |
| 660 info->set_mode(i, var->mode()); | 719 info->set_mode(i, var->mode()); |
| 661 DCHECK(var->index() >= 0); | 720 DCHECK(var->index() >= 0); |
| 662 info->set_index(i, var->index()); | 721 info->set_index(i, var->index()); |
| 663 } | 722 } |
| 664 DCHECK(i == info->length()); | 723 DCHECK(i == info->length()); |
| 665 return info; | 724 return info; |
| 666 } | 725 } |
| 667 | 726 |
| 668 } } // namespace v8::internal | 727 } } // namespace v8::internal |
| OLD | NEW |