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 3 // found in the LICENSE file. 4 5 #include <stdlib.h> 6 7 #include "src/ast/context-slot-cache.h" 8 #include "src/ast/scopes.h" 9 #include "src/ast/variables.h" 10 #include "src/bootstrapper.h" 11 12 namespace v8 { 13 namespace internal { 14 15 // An entry in ModuleVariableEntries consists of several slots: 16 enum ModuleVariableEntryOffset { 17 kModuleVariableNameOffset, 18 kModuleVariableIndexOffset, 19 kModuleVariablePropertiesOffset, 20 kModuleVariableEntryLength // Sentinel value. 21 }; 22 23 #ifdef DEBUG 24 bool ScopeInfo::Equals(ScopeInfo* other) const { 25 if (length() != other->length()) return false; 26 for (int index = 0; index < length(); ++index) { 27 Object* entry = get(index); 28 Object* other_entry = other->get(index); 29 if (entry->IsSmi()) { 30 if (entry != other_entry) return false; 31 } else { 32 if (HeapObject::cast(entry)->map()->instance_type() != 33 HeapObject::cast(other_entry)->map()->instance_type()) { 34 return false; 35 } 36 if (entry->IsString()) { 37 if (!String::cast(entry)->Equals(String::cast(other_entry))) { 38 return false; 39 } 40 } else if (entry->IsScopeInfo()) { 41 if (!ScopeInfo::cast(entry)->Equals(ScopeInfo::cast(other_entry))) { 42 return false; 43 } 44 } else if (entry->IsModuleInfo()) { 45 if (!ModuleInfo::cast(entry)->Equals(ModuleInfo::cast(other_entry))) { 46 return false; 47 } 48 } else { 49 UNREACHABLE(); 50 return false; 51 } 52 } 53 } 54 return true; 55 } 56 #endif 57 58 Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope, 59 MaybeHandle<ScopeInfo> outer_scope) { 60 // Collect variables. 61 int stack_local_count = 0; 62 int context_local_count = 0; 63 int module_vars_count = 0; 64 // Stack allocated block scope variables are allocated in the parent 65 // declaration scope, but are recorded in the block scope's scope info. First 66 // slot index indicates at which offset a particular scope starts in the 67 // parent declaration scope. 68 int first_slot_index = 0; 69 for (Variable* var : *scope->locals()) { 70 switch (var->location()) { 71 case VariableLocation::LOCAL: 72 if (stack_local_count == 0) first_slot_index = var->index(); 73 stack_local_count++; 74 break; 75 case VariableLocation::CONTEXT: 76 context_local_count++; 77 break; 78 case VariableLocation::MODULE: 79 module_vars_count++; 80 break; 81 default: 82 break; 83 } 84 } 85 DCHECK(module_vars_count == 0 || scope->is_module_scope()); 86 87 // Make sure we allocate the correct amount. 88 DCHECK_EQ(scope->ContextLocalCount(), context_local_count); 89 90 // Determine use and location of the "this" binding if it is present. 91 VariableAllocationInfo receiver_info; 92 if (scope->is_declaration_scope() && 93 scope->AsDeclarationScope()->has_this_declaration()) { 94 Variable* var = scope->AsDeclarationScope()->receiver(); 95 if (!var->is_used()) { 96 receiver_info = UNUSED; 97 } else if (var->IsContextSlot()) { 98 receiver_info = CONTEXT; 99 } else { 100 DCHECK(var->IsParameter()); 101 receiver_info = STACK; 102 } 103 } else { 104 receiver_info = NONE; 105 } 106 107 bool has_new_target = 108 scope->is_declaration_scope() && 109 scope->AsDeclarationScope()->new_target_var() != nullptr; 110 111 // Determine use and location of the function variable if it is present. 112 VariableAllocationInfo function_name_info; 113 if (scope->is_function_scope() && 114 scope->AsDeclarationScope()->function_var() != nullptr) { 115 Variable* var = scope->AsDeclarationScope()->function_var(); 116 if (!var->is_used()) { 117 function_name_info = UNUSED; 118 } else if (var->IsContextSlot()) { 119 function_name_info = CONTEXT; 120 } else { 121 DCHECK(var->IsStackLocal()); 122 function_name_info = STACK; 123 } 124 } else { 125 function_name_info = NONE; 126 } 127 128 const bool has_function_name = function_name_info != NONE; 129 const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT; 130 const int parameter_count = scope->num_parameters(); 131 const bool has_outer_scope_info = !outer_scope.is_null(); 132 const int length = kVariablePartIndex + parameter_count + 133 (1 + stack_local_count) + 2 * context_local_count + 134 (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0) + 135 (has_outer_scope_info ? 1 : 0) + 136 (scope->is_module_scope() 137 ? 2 + kModuleVariableEntryLength * module_vars_count 138 : 0); 139 140 Factory* factory = isolate->factory(); 141 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); 142 143 bool has_simple_parameters = false; 144 bool asm_module = false; 145 bool asm_function = false; 146 FunctionKind function_kind = kNormalFunction; 147 if (scope->is_function_scope()) { 148 DeclarationScope* function_scope = scope->AsDeclarationScope(); 149 has_simple_parameters = function_scope->has_simple_parameters(); 150 asm_module = function_scope->asm_module(); 151 asm_function = function_scope->asm_function(); 152 function_kind = function_scope->function_kind(); 153 } 154 155 // Encode the flags. 156 int flags = 157 ScopeTypeField::encode(scope->scope_type()) | 158 CallsEvalField::encode(scope->calls_eval()) | 159 LanguageModeField::encode(scope->language_mode()) | 160 DeclarationScopeField::encode(scope->is_declaration_scope()) | 161 ReceiverVariableField::encode(receiver_info) | 162 HasNewTargetField::encode(has_new_target) | 163 FunctionVariableField::encode(function_name_info) | 164 AsmModuleField::encode(asm_module) | 165 AsmFunctionField::encode(asm_function) | 166 HasSimpleParametersField::encode(has_simple_parameters) | 167 FunctionKindField::encode(function_kind) | 168 HasOuterScopeInfoField::encode(has_outer_scope_info) | 169 IsDebugEvaluateScopeField::encode(scope->is_debug_evaluate_scope()); 170 scope_info->SetFlags(flags); 171 172 scope_info->SetParameterCount(parameter_count); 173 scope_info->SetStackLocalCount(stack_local_count); 174 scope_info->SetContextLocalCount(context_local_count); 175 176 int index = kVariablePartIndex; 177 // Add parameters. 178 DCHECK_EQ(index, scope_info->ParameterNamesIndex()); 179 if (scope->is_declaration_scope()) { 180 for (int i = 0; i < parameter_count; ++i) { 181 scope_info->set(index++, 182 *scope->AsDeclarationScope()->parameter(i)->name()); 183 } 184 } 185 186 // Add stack locals' names, context locals' names and info, module variables' 187 // names and info. We are assuming that the stack locals' slots are allocated 188 // in increasing order, so we can simply add them to the ScopeInfo object. 189 // Context locals are added using their index. 190 DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex()); 191 scope_info->set(index++, Smi::FromInt(first_slot_index)); 192 DCHECK_EQ(index, scope_info->StackLocalNamesIndex()); 193 194 int stack_local_base = index; 195 int context_local_base = stack_local_base + stack_local_count; 196 int context_local_info_base = context_local_base + context_local_count; 197 int module_var_entry = scope_info->ModuleVariablesIndex(); 198 199 for (Variable* var : *scope->locals()) { 200 switch (var->location()) { 201 case VariableLocation::LOCAL: { 202 int local_index = var->index() - first_slot_index; 203 DCHECK_LE(0, local_index); 204 DCHECK_LT(local_index, stack_local_count); 205 scope_info->set(stack_local_base + local_index, *var->name()); 206 break; 207 } 208 case VariableLocation::CONTEXT: { 209 // Due to duplicate parameters, context locals aren't guaranteed to come 210 // in order. 211 int local_index = var->index() - Context::MIN_CONTEXT_SLOTS; 212 DCHECK_LE(0, local_index); 213 DCHECK_LT(local_index, context_local_count); 214 uint32_t info = VariableModeField::encode(var->mode()) | 215 InitFlagField::encode(var->initialization_flag()) | 216 MaybeAssignedFlagField::encode(var->maybe_assigned()); 217 scope_info->set(context_local_base + local_index, *var->name()); 218 scope_info->set(context_local_info_base + local_index, 219 Smi::FromInt(info)); 220 break; 221 } 222 case VariableLocation::MODULE: { 223 scope_info->set(module_var_entry + kModuleVariableNameOffset, 224 *var->name()); 225 scope_info->set(module_var_entry + kModuleVariableIndexOffset, 226 Smi::FromInt(var->index())); 227 uint32_t properties = 228 VariableModeField::encode(var->mode()) | 229 InitFlagField::encode(var->initialization_flag()) | 230 MaybeAssignedFlagField::encode(var->maybe_assigned()); 231 scope_info->set(module_var_entry + kModuleVariablePropertiesOffset, 232 Smi::FromInt(properties)); 233 module_var_entry += kModuleVariableEntryLength; 234 break; 235 } 236 default: 237 break; 238 } 239 } 240 241 index += stack_local_count + 2 * context_local_count; 242 243 // If the receiver is allocated, add its index. 244 DCHECK_EQ(index, scope_info->ReceiverInfoIndex()); 245 if (has_receiver) { 246 int var_index = scope->AsDeclarationScope()->receiver()->index(); 247 scope_info->set(index++, Smi::FromInt(var_index)); 248 // ?? DCHECK(receiver_info != CONTEXT || var_index == 249 // scope_info->ContextLength() - 1); 250 } 251 252 // If present, add the function variable name and its index. 253 DCHECK_EQ(index, scope_info->FunctionNameInfoIndex()); 254 if (has_function_name) { 255 int var_index = scope->AsDeclarationScope()->function_var()->index(); 256 scope_info->set(index++, 257 *scope->AsDeclarationScope()->function_var()->name()); 258 scope_info->set(index++, Smi::FromInt(var_index)); 259 DCHECK(function_name_info != CONTEXT || 260 var_index == scope_info->ContextLength() - 1); 261 } 262 263 // If present, add the outer scope info. 264 DCHECK(index == scope_info->OuterScopeInfoIndex()); 265 if (has_outer_scope_info) { 266 scope_info->set(index++, *outer_scope.ToHandleChecked()); 267 } 268 269 // Module-specific information (only for module scopes). 270 if (scope->is_module_scope()) { 271 Handle<ModuleInfo> module_info = 272 ModuleInfo::New(isolate, zone, scope->AsModuleScope()->module()); 273 DCHECK_EQ(index, scope_info->ModuleInfoIndex()); 274 scope_info->set(index++, *module_info); 275 DCHECK_EQ(index, scope_info->ModuleVariableCountIndex()); 276 scope_info->set(index++, Smi::FromInt(module_vars_count)); 277 DCHECK_EQ(index, scope_info->ModuleVariablesIndex()); 278 // The variable entries themselves have already been written above. 279 index += kModuleVariableEntryLength * module_vars_count; 280 } 281 282 DCHECK_EQ(index, scope_info->length()); 283 DCHECK_EQ(scope->num_parameters(), scope_info->ParameterCount()); 284 DCHECK_EQ(scope->num_heap_slots(), scope_info->ContextLength()); 285 return scope_info; 286 } 287 288 Handle<ScopeInfo> ScopeInfo::CreateForWithScope( 289 Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope) { 290 const bool has_outer_scope_info = !outer_scope.is_null(); 291 const int length = kVariablePartIndex + 1 + (has_outer_scope_info ? 1 : 0); 292 293 Factory* factory = isolate->factory(); 294 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); 295 296 // Encode the flags. 297 int flags = 298 ScopeTypeField::encode(WITH_SCOPE) | CallsEvalField::encode(false) | 299 LanguageModeField::encode(SLOPPY) | DeclarationScopeField::encode(false) | 300 ReceiverVariableField::encode(NONE) | HasNewTargetField::encode(false) | 301 FunctionVariableField::encode(NONE) | AsmModuleField::encode(false) | 302 AsmFunctionField::encode(false) | HasSimpleParametersField::encode(true) | 303 FunctionKindField::encode(kNormalFunction) | 304 HasOuterScopeInfoField::encode(has_outer_scope_info) | 305 IsDebugEvaluateScopeField::encode(false); 306 scope_info->SetFlags(flags); 307 308 scope_info->SetParameterCount(0); 309 scope_info->SetStackLocalCount(0); 310 scope_info->SetContextLocalCount(0); 311 312 int index = kVariablePartIndex; 313 DCHECK_EQ(index, scope_info->ParameterNamesIndex()); 314 DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex()); 315 scope_info->set(index++, Smi::kZero); 316 DCHECK_EQ(index, scope_info->StackLocalNamesIndex()); 317 DCHECK_EQ(index, scope_info->ReceiverInfoIndex()); 318 DCHECK_EQ(index, scope_info->FunctionNameInfoIndex()); 319 DCHECK(index == scope_info->OuterScopeInfoIndex()); 320 if (has_outer_scope_info) { 321 scope_info->set(index++, *outer_scope.ToHandleChecked()); 322 } 323 DCHECK_EQ(index, scope_info->length()); 324 DCHECK_EQ(0, scope_info->ParameterCount()); 325 DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, scope_info->ContextLength()); 326 return scope_info; 327 } 328 329 Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) { 330 DCHECK(isolate->bootstrapper()->IsActive()); 331 332 const int stack_local_count = 0; 333 const int context_local_count = 1; 334 const bool has_simple_parameters = true; 335 const VariableAllocationInfo receiver_info = CONTEXT; 336 const VariableAllocationInfo function_name_info = NONE; 337 const bool has_function_name = false; 338 const bool has_receiver = true; 339 const bool has_outer_scope_info = false; 340 const int parameter_count = 0; 341 const int length = kVariablePartIndex + parameter_count + 342 (1 + stack_local_count) + 2 * context_local_count + 343 (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0) + 344 (has_outer_scope_info ? 1 : 0); 345 346 Factory* factory = isolate->factory(); 347 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); 348 349 // Encode the flags. 350 int flags = 351 ScopeTypeField::encode(SCRIPT_SCOPE) | CallsEvalField::encode(false) | 352 LanguageModeField::encode(SLOPPY) | DeclarationScopeField::encode(true) | 353 ReceiverVariableField::encode(receiver_info) | 354 FunctionVariableField::encode(function_name_info) | 355 AsmModuleField::encode(false) | AsmFunctionField::encode(false) | 356 HasSimpleParametersField::encode(has_simple_parameters) | 357 FunctionKindField::encode(FunctionKind::kNormalFunction) | 358 HasOuterScopeInfoField::encode(has_outer_scope_info) | 359 IsDebugEvaluateScopeField::encode(false); 360 scope_info->SetFlags(flags); 361 scope_info->SetParameterCount(parameter_count); 362 scope_info->SetStackLocalCount(stack_local_count); 363 scope_info->SetContextLocalCount(context_local_count); 364 365 int index = kVariablePartIndex; 366 const int first_slot_index = 0; 367 DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex()); 368 scope_info->set(index++, Smi::FromInt(first_slot_index)); 369 DCHECK_EQ(index, scope_info->StackLocalNamesIndex()); 370 371 // Here we add info for context-allocated "this". 372 DCHECK_EQ(index, scope_info->ContextLocalNamesIndex()); 373 scope_info->set(index++, isolate->heap()->this_string()); 374 DCHECK_EQ(index, scope_info->ContextLocalInfosIndex()); 375 const uint32_t value = VariableModeField::encode(CONST) | 376 InitFlagField::encode(kCreatedInitialized) | 377 MaybeAssignedFlagField::encode(kNotAssigned); 378 scope_info->set(index++, Smi::FromInt(value)); 379 380 // And here we record that this scopeinfo binds a receiver. 381 DCHECK_EQ(index, scope_info->ReceiverInfoIndex()); 382 const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0; 383 scope_info->set(index++, Smi::FromInt(receiver_index)); 384 385 DCHECK_EQ(index, scope_info->FunctionNameInfoIndex()); 386 DCHECK_EQ(index, scope_info->OuterScopeInfoIndex()); 387 DCHECK_EQ(index, scope_info->length()); 388 DCHECK_EQ(scope_info->ParameterCount(), 0); 389 DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1); 390 391 return scope_info; 392 } 393 394 395 ScopeInfo* ScopeInfo::Empty(Isolate* isolate) { 396 return isolate->heap()->empty_scope_info(); 397 } 398 399 400 ScopeType ScopeInfo::scope_type() { 401 DCHECK_LT(0, length()); 402 return ScopeTypeField::decode(Flags()); 403 } 404 405 406 bool ScopeInfo::CallsEval() { 407 return length() > 0 && CallsEvalField::decode(Flags()); 408 } 409 410 411 LanguageMode ScopeInfo::language_mode() { 412 return length() > 0 ? LanguageModeField::decode(Flags()) : SLOPPY; 413 } 414 415 416 bool ScopeInfo::is_declaration_scope() { 417 return DeclarationScopeField::decode(Flags()); 418 } 419 420 421 int ScopeInfo::LocalCount() { 422 return StackLocalCount() + ContextLocalCount(); 423 } 424 425 426 int ScopeInfo::StackSlotCount() { 427 if (length() > 0) { 428 bool function_name_stack_slot = 429 FunctionVariableField::decode(Flags()) == STACK; 430 return StackLocalCount() + (function_name_stack_slot ? 1 : 0); 431 } 432 return 0; 433 } 434 435 436 int ScopeInfo::ContextLength() { 437 if (length() > 0) { 438 int context_locals = ContextLocalCount(); 439 bool function_name_context_slot = 440 FunctionVariableField::decode(Flags()) == CONTEXT; 441 bool has_context = context_locals > 0 || function_name_context_slot || 442 scope_type() == WITH_SCOPE || 443 (scope_type() == BLOCK_SCOPE && CallsSloppyEval() && 444 is_declaration_scope()) || 445 (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) || 446 scope_type() == MODULE_SCOPE; 447 448 if (has_context) { 449 return Context::MIN_CONTEXT_SLOTS + context_locals + 450 (function_name_context_slot ? 1 : 0); 451 } 452 } 453 return 0; 454 } 455 456 457 bool ScopeInfo::HasReceiver() { 458 if (length() > 0) { 459 return NONE != ReceiverVariableField::decode(Flags()); 460 } else { 461 return false; 462 } 463 } 464 465 466 bool ScopeInfo::HasAllocatedReceiver() { 467 if (length() > 0) { 468 VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags()); 469 return allocation == STACK || allocation == CONTEXT; 470 } else { 471 return false; 472 } 473 } 474 475 476 bool ScopeInfo::HasNewTarget() { return HasNewTargetField::decode(Flags()); } 477 478 479 bool ScopeInfo::HasFunctionName() { 480 if (length() > 0) { 481 return NONE != FunctionVariableField::decode(Flags()); 482 } else { 483 return false; 484 } 485 } 486 487 bool ScopeInfo::HasOuterScopeInfo() { 488 if (length() > 0) { 489 return HasOuterScopeInfoField::decode(Flags()); 490 } else { 491 return false; 492 } 493 } 494 495 bool ScopeInfo::IsDebugEvaluateScope() { 496 if (length() > 0) { 497 return IsDebugEvaluateScopeField::decode(Flags()); 498 } else { 499 return false; 500 } 501 } 502 503 void ScopeInfo::SetIsDebugEvaluateScope() { 504 if (length() > 0) { 505 DCHECK_EQ(scope_type(), WITH_SCOPE); 506 SetFlags(Flags() | IsDebugEvaluateScopeField::encode(true)); 507 } else { 508 UNREACHABLE(); 509 } 510 } 511 512 bool ScopeInfo::HasHeapAllocatedLocals() { 513 if (length() > 0) { 514 return ContextLocalCount() > 0; 515 } else { 516 return false; 517 } 518 } 519 520 521 bool ScopeInfo::HasContext() { 522 return ContextLength() > 0; 523 } 524 525 526 String* ScopeInfo::FunctionName() { 527 DCHECK(HasFunctionName()); 528 return String::cast(get(FunctionNameInfoIndex())); 529 } 530 531 ScopeInfo* ScopeInfo::OuterScopeInfo() { 532 DCHECK(HasOuterScopeInfo()); 533 return ScopeInfo::cast(get(OuterScopeInfoIndex())); 534 } 535 536 ModuleInfo* ScopeInfo::ModuleDescriptorInfo() { 537 DCHECK(scope_type() == MODULE_SCOPE); 538 return ModuleInfo::cast(get(ModuleInfoIndex())); 539 } 540 541 String* ScopeInfo::ParameterName(int var) { 542 DCHECK_LE(0, var); 543 DCHECK_LT(var, ParameterCount()); 544 int info_index = ParameterNamesIndex() + var; 545 return String::cast(get(info_index)); 546 } 547 548 549 String* ScopeInfo::LocalName(int var) { 550 DCHECK_LE(0, var); 551 DCHECK_LT(var, LocalCount()); 552 DCHECK(StackLocalNamesIndex() + StackLocalCount() == 553 ContextLocalNamesIndex()); 554 int info_index = StackLocalNamesIndex() + var; 555 return String::cast(get(info_index)); 556 } 557 558 559 String* ScopeInfo::StackLocalName(int var) { 560 DCHECK_LE(0, var); 561 DCHECK_LT(var, StackLocalCount()); 562 int info_index = StackLocalNamesIndex() + var; 563 return String::cast(get(info_index)); 564 } 565 566 567 int ScopeInfo::StackLocalIndex(int var) { 568 DCHECK_LE(0, var); 569 DCHECK_LT(var, StackLocalCount()); 570 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value(); 571 return first_slot_index + var; 572 } 573 574 575 String* ScopeInfo::ContextLocalName(int var) { 576 DCHECK_LE(0, var); 577 DCHECK_LT(var, ContextLocalCount()); 578 int info_index = ContextLocalNamesIndex() + var; 579 return String::cast(get(info_index)); 580 } 581 582 583 VariableMode ScopeInfo::ContextLocalMode(int var) { 584 DCHECK_LE(0, var); 585 DCHECK_LT(var, ContextLocalCount()); 586 int info_index = ContextLocalInfosIndex() + var; 587 int value = Smi::cast(get(info_index))->value(); 588 return VariableModeField::decode(value); 589 } 590 591 592 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) { 593 DCHECK_LE(0, var); 594 DCHECK_LT(var, ContextLocalCount()); 595 int info_index = ContextLocalInfosIndex() + var; 596 int value = Smi::cast(get(info_index))->value(); 597 return InitFlagField::decode(value); 598 } 599 600 601 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) { 602 DCHECK_LE(0, var); 603 DCHECK_LT(var, ContextLocalCount()); 604 int info_index = ContextLocalInfosIndex() + var; 605 int value = Smi::cast(get(info_index))->value(); 606 return MaybeAssignedFlagField::decode(value); 607 } 608 609 bool ScopeInfo::VariableIsSynthetic(String* name) { 610 // There's currently no flag stored on the ScopeInfo to indicate that a 611 // variable is a compiler-introduced temporary. However, to avoid conflict 612 // with user declarations, the current temporaries like .generator_object and 613 // .result start with a dot, so we can use that as a flag. It's a hack! 614 return name->length() == 0 || name->Get(0) == '.' || 615 name->Equals(name->GetHeap()->this_string()); 616 } 617 618 619 int ScopeInfo::StackSlotIndex(String* name) { 620 DCHECK(name->IsInternalizedString()); 621 if (length() > 0) { 622 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value(); 623 int start = StackLocalNamesIndex(); 624 int end = start + StackLocalCount(); 625 for (int i = start; i < end; ++i) { 626 if (name == get(i)) { 627 return i - start + first_slot_index; 628 } 629 } 630 } 631 return -1; 632 } 633 634 int ScopeInfo::ModuleIndex(Handle<String> name, VariableMode* mode, 635 InitializationFlag* init_flag, 636 MaybeAssignedFlag* maybe_assigned_flag) { 637 DCHECK_EQ(scope_type(), MODULE_SCOPE); 638 DCHECK(name->IsInternalizedString()); 639 DCHECK_NOT_NULL(mode); 640 DCHECK_NOT_NULL(init_flag); 641 DCHECK_NOT_NULL(maybe_assigned_flag); 642 643 int module_vars_count = Smi::cast(get(ModuleVariableCountIndex()))->value(); 644 int entry = ModuleVariablesIndex(); 645 for (int i = 0; i < module_vars_count; ++i) { 646 if (*name == get(entry + kModuleVariableNameOffset)) { 647 int index; 648 ModuleVariable(i, nullptr, &index, mode, init_flag, maybe_assigned_flag); 649 return index; 650 } 651 entry += kModuleVariableEntryLength; 652 } 653 654 return 0; 655 } 656 657 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info, 658 Handle<String> name, VariableMode* mode, 659 InitializationFlag* init_flag, 660 MaybeAssignedFlag* maybe_assigned_flag) { 661 DCHECK(name->IsInternalizedString()); 662 DCHECK_NOT_NULL(mode); 663 DCHECK_NOT_NULL(init_flag); 664 DCHECK_NOT_NULL(maybe_assigned_flag); 665 666 if (scope_info->length() > 0) { 667 ContextSlotCache* context_slot_cache = 668 scope_info->GetIsolate()->context_slot_cache(); 669 int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag, 670 maybe_assigned_flag); 671 if (result != ContextSlotCache::kNotFound) { 672 DCHECK_LT(result, scope_info->ContextLength()); 673 return result; 674 } 675 676 int start = scope_info->ContextLocalNamesIndex(); 677 int end = start + scope_info->ContextLocalCount(); 678 for (int i = start; i < end; ++i) { 679 if (*name == scope_info->get(i)) { 680 int var = i - start; 681 *mode = scope_info->ContextLocalMode(var); 682 *init_flag = scope_info->ContextLocalInitFlag(var); 683 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var); 684 result = Context::MIN_CONTEXT_SLOTS + var; 685 686 context_slot_cache->Update(scope_info, name, *mode, *init_flag, 687 *maybe_assigned_flag, result); 688 DCHECK_LT(result, scope_info->ContextLength()); 689 return result; 690 } 691 } 692 // Cache as not found. Mode, init flag and maybe assigned flag don't matter. 693 context_slot_cache->Update(scope_info, name, TEMPORARY, 694 kNeedsInitialization, kNotAssigned, -1); 695 } 696 697 return -1; 698 } 699 700 String* ScopeInfo::ContextSlotName(int slot_index) { 701 int const var = slot_index - Context::MIN_CONTEXT_SLOTS; 702 DCHECK_LE(0, var); 703 DCHECK_LT(var, ContextLocalCount()); 704 return ContextLocalName(var); 705 } 706 707 708 int ScopeInfo::ParameterIndex(String* name) { 709 DCHECK(name->IsInternalizedString()); 710 if (length() > 0) { 711 // We must read parameters from the end since for 712 // multiply declared parameters the value of the 713 // last declaration of that parameter is used 714 // inside a function (and thus we need to look 715 // at the last index). Was bug# 1110337. 716 int start = ParameterNamesIndex(); 717 int end = start + ParameterCount(); 718 for (int i = end - 1; i >= start; --i) { 719 if (name == get(i)) { 720 return i - start; 721 } 722 } 723 } 724 return -1; 725 } 726 727 728 int ScopeInfo::ReceiverContextSlotIndex() { 729 if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT) 730 return Smi::cast(get(ReceiverInfoIndex()))->value(); 731 return -1; 732 } 733 734 int ScopeInfo::FunctionContextSlotIndex(String* name) { 735 DCHECK(name->IsInternalizedString()); 736 if (length() > 0) { 737 if (FunctionVariableField::decode(Flags()) == CONTEXT && 738 FunctionName() == name) { 739 return Smi::cast(get(FunctionNameInfoIndex() + 1))->value(); 740 } 741 } 742 return -1; 743 } 744 745 746 FunctionKind ScopeInfo::function_kind() { 747 return FunctionKindField::decode(Flags()); 748 } 749 750 int ScopeInfo::ParameterNamesIndex() { 751 DCHECK_LT(0, length()); 752 return kVariablePartIndex; 753 } 754 755 756 int ScopeInfo::StackLocalFirstSlotIndex() { 757 return ParameterNamesIndex() + ParameterCount(); 758 } 759 760 int ScopeInfo::StackLocalNamesIndex() { return StackLocalFirstSlotIndex() + 1; } 761 762 int ScopeInfo::ContextLocalNamesIndex() { 763 return StackLocalNamesIndex() + StackLocalCount(); 764 } 765 766 int ScopeInfo::ContextLocalInfosIndex() { 767 return ContextLocalNamesIndex() + ContextLocalCount(); 768 } 769 770 int ScopeInfo::ReceiverInfoIndex() { 771 return ContextLocalInfosIndex() + ContextLocalCount(); 772 } 773 774 int ScopeInfo::FunctionNameInfoIndex() { 775 return ReceiverInfoIndex() + (HasAllocatedReceiver() ? 1 : 0); 776 } 777 778 int ScopeInfo::OuterScopeInfoIndex() { 779 return FunctionNameInfoIndex() + (HasFunctionName() ? 2 : 0); 780 } 781 782 int ScopeInfo::ModuleInfoIndex() { 783 return OuterScopeInfoIndex() + (HasOuterScopeInfo() ? 1 : 0); 784 } 785 786 int ScopeInfo::ModuleVariableCountIndex() { return ModuleInfoIndex() + 1; } 787 788 int ScopeInfo::ModuleVariablesIndex() { return ModuleVariableCountIndex() + 1; } 789 790 void ScopeInfo::ModuleVariable(int i, String** name, int* index, 791 VariableMode* mode, 792 InitializationFlag* init_flag, 793 MaybeAssignedFlag* maybe_assigned_flag) { 794 DCHECK_LE(0, i); 795 DCHECK_LT(i, Smi::cast(get(ModuleVariableCountIndex()))->value()); 796 797 int entry = ModuleVariablesIndex() + i * kModuleVariableEntryLength; 798 int properties = 799 Smi::cast(get(entry + kModuleVariablePropertiesOffset))->value(); 800 801 if (name != nullptr) { 802 *name = String::cast(get(entry + kModuleVariableNameOffset)); 803 } 804 if (index != nullptr) { 805 *index = Smi::cast(get(entry + kModuleVariableIndexOffset))->value(); 806 DCHECK_NE(*index, 0); 807 } 808 if (mode != nullptr) { 809 *mode = VariableModeField::decode(properties); 810 } 811 if (init_flag != nullptr) { 812 *init_flag = InitFlagField::decode(properties); 813 } 814 if (maybe_assigned_flag != nullptr) { 815 *maybe_assigned_flag = MaybeAssignedFlagField::decode(properties); 816 } 817 } 818 819 #ifdef DEBUG 820 821 static void PrintList(const char* list_name, 822 int nof_internal_slots, 823 int start, 824 int end, 825 ScopeInfo* scope_info) { 826 if (start < end) { 827 PrintF("\n // %s\n", list_name); 828 if (nof_internal_slots > 0) { 829 PrintF(" %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1); 830 } 831 for (int i = nof_internal_slots; start < end; ++i, ++start) { 832 PrintF(" %2d ", i); 833 String::cast(scope_info->get(start))->ShortPrint(); 834 PrintF("\n"); 835 } 836 } 837 } 838 839 840 void ScopeInfo::Print() { 841 PrintF("ScopeInfo "); 842 if (HasFunctionName()) { 843 FunctionName()->ShortPrint(); 844 } else { 845 PrintF("/* no function name */"); 846 } 847 PrintF("{"); 848 849 if (length() > 0) { 850 PrintList("parameters", 0, ParameterNamesIndex(), 851 ParameterNamesIndex() + ParameterCount(), this); 852 PrintList("stack slots", 0, StackLocalNamesIndex(), 853 StackLocalNamesIndex() + StackLocalCount(), this); 854 PrintList("context slots", Context::MIN_CONTEXT_SLOTS, 855 ContextLocalNamesIndex(), 856 ContextLocalNamesIndex() + ContextLocalCount(), this); 857 // TODO(neis): Print module stuff if present. 858 } 859 860 PrintF("}\n"); 861 } 862 #endif // DEBUG 863 864 Handle<ModuleInfoEntry> ModuleInfoEntry::New(Isolate* isolate, 865 Handle<Object> export_name, 866 Handle<Object> local_name, 867 Handle<Object> import_name, 868 int module_request, int cell_index, 869 int beg_pos, int end_pos) { 870 Handle<ModuleInfoEntry> result = Handle<ModuleInfoEntry>::cast( 871 isolate->factory()->NewStruct(MODULE_INFO_ENTRY_TYPE)); 872 result->set_export_name(*export_name); 873 result->set_local_name(*local_name); 874 result->set_import_name(*import_name); 875 result->set_module_request(module_request); 876 result->set_cell_index(cell_index); 877 result->set_beg_pos(beg_pos); 878 result->set_end_pos(end_pos); 879 return result; 880 } 881 882 Handle<ModuleInfo> ModuleInfo::New(Isolate* isolate, Zone* zone, 883 ModuleDescriptor* descr) { 884 // Serialize module requests. 885 Handle<FixedArray> module_requests = isolate->factory()->NewFixedArray( 886 static_cast<int>(descr->module_requests().size())); 887 for (const auto& elem : descr->module_requests()) { 888 module_requests->set(elem.second, *elem.first->string()); 889 } 890 891 // Serialize special exports. 892 Handle<FixedArray> special_exports = 893 isolate->factory()->NewFixedArray(descr->special_exports().length()); 894 { 895 int i = 0; 896 for (auto entry : descr->special_exports()) { 897 Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate); 898 special_exports->set(i++, *serialized_entry); 899 } 900 } 901 902 // Serialize namespace imports. 903 Handle<FixedArray> namespace_imports = 904 isolate->factory()->NewFixedArray(descr->namespace_imports().length()); 905 { 906 int i = 0; 907 for (auto entry : descr->namespace_imports()) { 908 Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate); 909 namespace_imports->set(i++, *serialized_entry); 910 } 911 } 912 913 // Serialize regular exports. 914 Handle<FixedArray> regular_exports = 915 descr->SerializeRegularExports(isolate, zone); 916 917 // Serialize regular imports. 918 Handle<FixedArray> regular_imports = isolate->factory()->NewFixedArray( 919 static_cast<int>(descr->regular_imports().size())); 920 { 921 int i = 0; 922 for (const auto& elem : descr->regular_imports()) { 923 Handle<ModuleInfoEntry> serialized_entry = 924 elem.second->Serialize(isolate); 925 regular_imports->set(i++, *serialized_entry); 926 } 927 } 928 929 Handle<ModuleInfo> result = isolate->factory()->NewModuleInfo(); 930 result->set(kModuleRequestsIndex, *module_requests); 931 result->set(kSpecialExportsIndex, *special_exports); 932 result->set(kRegularExportsIndex, *regular_exports); 933 result->set(kNamespaceImportsIndex, *namespace_imports); 934 result->set(kRegularImportsIndex, *regular_imports); 935 return result; 936 } 937 938 int ModuleInfo::RegularExportCount() const { 939 DCHECK_EQ(regular_exports()->length() % kRegularExportLength, 0); 940 return regular_exports()->length() / kRegularExportLength; 941 } 942 943 String* ModuleInfo::RegularExportLocalName(int i) const { 944 return String::cast(regular_exports()->get(i * kRegularExportLength + 945 kRegularExportLocalNameOffset)); 946 } 947 948 int ModuleInfo::RegularExportCellIndex(int i) const { 949 return Smi::cast(regular_exports()->get(i * kRegularExportLength + 950 kRegularExportCellIndexOffset)) 951 ->value(); 952 } 953 954 FixedArray* ModuleInfo::RegularExportExportNames(int i) const { 955 return FixedArray::cast(regular_exports()->get( 956 i * kRegularExportLength + kRegularExportExportNamesOffset)); 957 } 958 959 Handle<ModuleInfoEntry> ModuleInfo::LookupRegularImport( 960 Handle<ModuleInfo> info, Handle<String> local_name) { 961 Isolate* isolate = info->GetIsolate(); 962 Handle<FixedArray> regular_imports(info->regular_imports(), isolate); 963 for (int i = 0, n = regular_imports->length(); i < n; ++i) { 964 Handle<ModuleInfoEntry> entry( 965 ModuleInfoEntry::cast(regular_imports->get(i)), isolate); 966 if (String::cast(entry->local_name())->Equals(*local_name)) { 967 return entry; 968 } 969 } 970 UNREACHABLE(); 971 return Handle<ModuleInfoEntry>(); 972 } 973 974 } // namespace internal 975 } // namespace v8 976