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