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