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 "src/ast/scopeinfo.h" 6 7 #include <stdlib.h> 8 9 #include "src/ast/scopes.h" 10 #include "src/bootstrapper.h" 11 12 namespace v8 { 13 namespace internal { 14 15 16 Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, 17 Scope* scope) { 18 // Collect stack and context locals. 19 ZoneList<Variable*> stack_locals(scope->StackLocalCount(), zone); 20 ZoneList<Variable*> context_locals(scope->ContextLocalCount(), zone); 21 ZoneList<Variable*> context_globals(scope->ContextGlobalCount(), zone); 22 ZoneList<Variable*> strong_mode_free_variables(0, zone); 23 24 scope->CollectStackAndContextLocals(&stack_locals, &context_locals, 25 &context_globals, 26 &strong_mode_free_variables); 27 const int stack_local_count = stack_locals.length(); 28 const int context_local_count = context_locals.length(); 29 const int context_global_count = context_globals.length(); 30 const int strong_mode_free_variable_count = 31 strong_mode_free_variables.length(); 32 // Make sure we allocate the correct amount. 33 DCHECK_EQ(scope->ContextLocalCount(), context_local_count); 34 DCHECK_EQ(scope->ContextGlobalCount(), context_global_count); 35 36 // Determine use and location of the "this" binding if it is present. 37 VariableAllocationInfo receiver_info; 38 if (scope->has_this_declaration()) { 39 Variable* var = scope->receiver(); 40 if (!var->is_used()) { 41 receiver_info = UNUSED; 42 } else if (var->IsContextSlot()) { 43 receiver_info = CONTEXT; 44 } else { 45 DCHECK(var->IsParameter()); 46 receiver_info = STACK; 47 } 48 } else { 49 receiver_info = NONE; 50 } 51 52 bool has_new_target = scope->new_target_var() != nullptr; 53 54 // Determine use and location of the function variable if it is present. 55 VariableAllocationInfo function_name_info; 56 VariableMode function_variable_mode; 57 if (scope->is_function_scope() && scope->function() != NULL) { 58 Variable* var = scope->function()->proxy()->var(); 59 if (!var->is_used()) { 60 function_name_info = UNUSED; 61 } else if (var->IsContextSlot()) { 62 function_name_info = CONTEXT; 63 } else { 64 DCHECK(var->IsStackLocal()); 65 function_name_info = STACK; 66 } 67 function_variable_mode = var->mode(); 68 } else { 69 function_name_info = NONE; 70 function_variable_mode = VAR; 71 } 72 DCHECK(context_global_count == 0 || scope->scope_type() == SCRIPT_SCOPE); 73 74 const bool has_function_name = function_name_info != NONE; 75 const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT; 76 const int parameter_count = scope->num_parameters(); 77 const int length = kVariablePartIndex + parameter_count + 78 (1 + stack_local_count) + 2 * context_local_count + 79 2 * context_global_count + 80 3 * strong_mode_free_variable_count + 81 (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0); 82 83 Factory* factory = isolate->factory(); 84 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); 85 86 bool has_simple_parameters = 87 scope->is_function_scope() && scope->has_simple_parameters(); 88 89 // Encode the flags. 90 int flags = ScopeTypeField::encode(scope->scope_type()) | 91 CallsEvalField::encode(scope->calls_eval()) | 92 LanguageModeField::encode(scope->language_mode()) | 93 DeclarationScopeField::encode(scope->is_declaration_scope()) | 94 ReceiverVariableField::encode(receiver_info) | 95 HasNewTargetField::encode(has_new_target) | 96 FunctionVariableField::encode(function_name_info) | 97 FunctionVariableMode::encode(function_variable_mode) | 98 AsmModuleField::encode(scope->asm_module()) | 99 AsmFunctionField::encode(scope->asm_function()) | 100 HasSimpleParametersField::encode(has_simple_parameters) | 101 FunctionKindField::encode(scope->function_kind()); 102 scope_info->SetFlags(flags); 103 scope_info->SetParameterCount(parameter_count); 104 scope_info->SetStackLocalCount(stack_local_count); 105 scope_info->SetContextLocalCount(context_local_count); 106 scope_info->SetContextGlobalCount(context_global_count); 107 scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count); 108 109 int index = kVariablePartIndex; 110 // Add parameters. 111 DCHECK(index == scope_info->ParameterEntriesIndex()); 112 for (int i = 0; i < parameter_count; ++i) { 113 scope_info->set(index++, *scope->parameter(i)->name()); 114 } 115 116 // Add stack locals' names. We are assuming that the stack locals' 117 // slots are allocated in increasing order, so we can simply add 118 // them to the ScopeInfo object. 119 int first_slot_index; 120 if (stack_local_count > 0) { 121 first_slot_index = stack_locals[0]->index(); 122 } else { 123 first_slot_index = 0; 124 } 125 DCHECK(index == scope_info->StackLocalFirstSlotIndex()); 126 scope_info->set(index++, Smi::FromInt(first_slot_index)); 127 DCHECK(index == scope_info->StackLocalEntriesIndex()); 128 for (int i = 0; i < stack_local_count; ++i) { 129 DCHECK(stack_locals[i]->index() == first_slot_index + i); 130 scope_info->set(index++, *stack_locals[i]->name()); 131 } 132 133 // Due to usage analysis, context-allocated locals are not necessarily in 134 // increasing order: Some of them may be parameters which are allocated before 135 // the non-parameter locals. When the non-parameter locals are sorted 136 // according to usage, the allocated slot indices may not be in increasing 137 // order with the variable list anymore. Thus, we first need to sort them by 138 // context slot index before adding them to the ScopeInfo object. 139 context_locals.Sort(&Variable::CompareIndex); 140 141 // Add context locals' names. 142 DCHECK(index == scope_info->ContextLocalNameEntriesIndex()); 143 for (int i = 0; i < context_local_count; ++i) { 144 scope_info->set(index++, *context_locals[i]->name()); 145 } 146 147 // Add context globals' names. 148 DCHECK(index == scope_info->ContextGlobalNameEntriesIndex()); 149 for (int i = 0; i < context_global_count; ++i) { 150 scope_info->set(index++, *context_globals[i]->name()); 151 } 152 153 // Add context locals' info. 154 DCHECK(index == scope_info->ContextLocalInfoEntriesIndex()); 155 for (int i = 0; i < context_local_count; ++i) { 156 Variable* var = context_locals[i]; 157 uint32_t value = 158 ContextLocalMode::encode(var->mode()) | 159 ContextLocalInitFlag::encode(var->initialization_flag()) | 160 ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned()); 161 scope_info->set(index++, Smi::FromInt(value)); 162 } 163 164 // Add context globals' info. 165 DCHECK(index == scope_info->ContextGlobalInfoEntriesIndex()); 166 for (int i = 0; i < context_global_count; ++i) { 167 Variable* var = context_globals[i]; 168 // TODO(ishell): do we need this kind of info for globals here? 169 uint32_t value = 170 ContextLocalMode::encode(var->mode()) | 171 ContextLocalInitFlag::encode(var->initialization_flag()) | 172 ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned()); 173 scope_info->set(index++, Smi::FromInt(value)); 174 } 175 176 DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex()); 177 for (int i = 0; i < strong_mode_free_variable_count; ++i) { 178 scope_info->set(index++, *strong_mode_free_variables[i]->name()); 179 } 180 181 DCHECK(index == scope_info->StrongModeFreeVariablePositionEntriesIndex()); 182 for (int i = 0; i < strong_mode_free_variable_count; ++i) { 183 // Unfortunately, the source code positions are stored as int even though 184 // int32_t would be enough (given the maximum source code length). 185 Handle<Object> start_position = factory->NewNumberFromInt( 186 static_cast<int32_t>(strong_mode_free_variables[i] 187 ->strong_mode_reference_start_position())); 188 scope_info->set(index++, *start_position); 189 Handle<Object> end_position = factory->NewNumberFromInt( 190 static_cast<int32_t>(strong_mode_free_variables[i] 191 ->strong_mode_reference_end_position())); 192 scope_info->set(index++, *end_position); 193 } 194 195 // If the receiver is allocated, add its index. 196 DCHECK(index == scope_info->ReceiverEntryIndex()); 197 if (has_receiver) { 198 int var_index = scope->receiver()->index(); 199 scope_info->set(index++, Smi::FromInt(var_index)); 200 // ?? DCHECK(receiver_info != CONTEXT || var_index == 201 // scope_info->ContextLength() - 1); 202 } 203 204 // If present, add the function variable name and its index. 205 DCHECK(index == scope_info->FunctionNameEntryIndex()); 206 if (has_function_name) { 207 int var_index = scope->function()->proxy()->var()->index(); 208 scope_info->set(index++, *scope->function()->proxy()->name()); 209 scope_info->set(index++, Smi::FromInt(var_index)); 210 DCHECK(function_name_info != CONTEXT || 211 var_index == scope_info->ContextLength() - 1); 212 } 213 214 DCHECK(index == scope_info->length()); 215 DCHECK(scope->num_parameters() == scope_info->ParameterCount()); 216 DCHECK(scope->num_heap_slots() == scope_info->ContextLength() || 217 (scope->num_heap_slots() == kVariablePartIndex && 218 scope_info->ContextLength() == 0)); 219 return scope_info; 220 } 221 222 223 Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) { 224 DCHECK(isolate->bootstrapper()->IsActive()); 225 226 const int stack_local_count = 0; 227 const int context_local_count = 1; 228 const int context_global_count = 0; 229 const int strong_mode_free_variable_count = 0; 230 const bool has_simple_parameters = true; 231 const VariableAllocationInfo receiver_info = CONTEXT; 232 const VariableAllocationInfo function_name_info = NONE; 233 const VariableMode function_variable_mode = VAR; 234 const bool has_function_name = false; 235 const bool has_receiver = true; 236 const int parameter_count = 0; 237 const int length = kVariablePartIndex + parameter_count + 238 (1 + stack_local_count) + 2 * context_local_count + 239 2 * context_global_count + 240 3 * strong_mode_free_variable_count + 241 (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0); 242 243 Factory* factory = isolate->factory(); 244 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); 245 246 // Encode the flags. 247 int flags = ScopeTypeField::encode(SCRIPT_SCOPE) | 248 CallsEvalField::encode(false) | 249 LanguageModeField::encode(SLOPPY) | 250 DeclarationScopeField::encode(true) | 251 ReceiverVariableField::encode(receiver_info) | 252 FunctionVariableField::encode(function_name_info) | 253 FunctionVariableMode::encode(function_variable_mode) | 254 AsmModuleField::encode(false) | AsmFunctionField::encode(false) | 255 HasSimpleParametersField::encode(has_simple_parameters) | 256 FunctionKindField::encode(FunctionKind::kNormalFunction); 257 scope_info->SetFlags(flags); 258 scope_info->SetParameterCount(parameter_count); 259 scope_info->SetStackLocalCount(stack_local_count); 260 scope_info->SetContextLocalCount(context_local_count); 261 scope_info->SetContextGlobalCount(context_global_count); 262 scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count); 263 264 int index = kVariablePartIndex; 265 const int first_slot_index = 0; 266 DCHECK(index == scope_info->StackLocalFirstSlotIndex()); 267 scope_info->set(index++, Smi::FromInt(first_slot_index)); 268 DCHECK(index == scope_info->StackLocalEntriesIndex()); 269 270 // Here we add info for context-allocated "this". 271 DCHECK(index == scope_info->ContextLocalNameEntriesIndex()); 272 scope_info->set(index++, *isolate->factory()->this_string()); 273 DCHECK(index == scope_info->ContextLocalInfoEntriesIndex()); 274 const uint32_t value = ContextLocalMode::encode(CONST) | 275 ContextLocalInitFlag::encode(kCreatedInitialized) | 276 ContextLocalMaybeAssignedFlag::encode(kNotAssigned); 277 scope_info->set(index++, Smi::FromInt(value)); 278 279 DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex()); 280 DCHECK(index == scope_info->StrongModeFreeVariablePositionEntriesIndex()); 281 282 // And here we record that this scopeinfo binds a receiver. 283 DCHECK(index == scope_info->ReceiverEntryIndex()); 284 const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0; 285 scope_info->set(index++, Smi::FromInt(receiver_index)); 286 287 DCHECK(index == scope_info->FunctionNameEntryIndex()); 288 289 DCHECK_EQ(index, scope_info->length()); 290 DCHECK_EQ(scope_info->ParameterCount(), 0); 291 DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1); 292 293 return scope_info; 294 } 295 296 297 ScopeInfo* ScopeInfo::Empty(Isolate* isolate) { 298 return reinterpret_cast<ScopeInfo*>(isolate->heap()->empty_fixed_array()); 299 } 300 301 302 ScopeType ScopeInfo::scope_type() { 303 DCHECK(length() > 0); 304 return ScopeTypeField::decode(Flags()); 305 } 306 307 308 bool ScopeInfo::CallsEval() { 309 return length() > 0 && CallsEvalField::decode(Flags()); 310 } 311 312 313 LanguageMode ScopeInfo::language_mode() { 314 return length() > 0 ? LanguageModeField::decode(Flags()) : SLOPPY; 315 } 316 317 318 bool ScopeInfo::is_declaration_scope() { 319 return DeclarationScopeField::decode(Flags()); 320 } 321 322 323 int ScopeInfo::LocalCount() { 324 return StackLocalCount() + ContextLocalCount(); 325 } 326 327 328 int ScopeInfo::StackSlotCount() { 329 if (length() > 0) { 330 bool function_name_stack_slot = 331 FunctionVariableField::decode(Flags()) == STACK; 332 return StackLocalCount() + (function_name_stack_slot ? 1 : 0); 333 } 334 return 0; 335 } 336 337 338 int ScopeInfo::ContextLength() { 339 if (length() > 0) { 340 int context_locals = ContextLocalCount(); 341 int context_globals = ContextGlobalCount(); 342 bool function_name_context_slot = 343 FunctionVariableField::decode(Flags()) == CONTEXT; 344 bool has_context = context_locals > 0 || context_globals > 0 || 345 function_name_context_slot || 346 scope_type() == WITH_SCOPE || 347 (scope_type() == BLOCK_SCOPE && CallsSloppyEval() && 348 is_declaration_scope()) || 349 (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) || 350 scope_type() == MODULE_SCOPE; 351 352 if (has_context) { 353 return Context::MIN_CONTEXT_SLOTS + context_locals + context_globals + 354 (function_name_context_slot ? 1 : 0); 355 } 356 } 357 return 0; 358 } 359 360 361 bool ScopeInfo::HasReceiver() { 362 if (length() > 0) { 363 return NONE != ReceiverVariableField::decode(Flags()); 364 } else { 365 return false; 366 } 367 } 368 369 370 bool ScopeInfo::HasAllocatedReceiver() { 371 if (length() > 0) { 372 VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags()); 373 return allocation == STACK || allocation == CONTEXT; 374 } else { 375 return false; 376 } 377 } 378 379 380 bool ScopeInfo::HasNewTarget() { return HasNewTargetField::decode(Flags()); } 381 382 383 bool ScopeInfo::HasFunctionName() { 384 if (length() > 0) { 385 return NONE != FunctionVariableField::decode(Flags()); 386 } else { 387 return false; 388 } 389 } 390 391 392 bool ScopeInfo::HasHeapAllocatedLocals() { 393 if (length() > 0) { 394 return ContextLocalCount() > 0; 395 } else { 396 return false; 397 } 398 } 399 400 401 bool ScopeInfo::HasContext() { 402 return ContextLength() > 0; 403 } 404 405 406 String* ScopeInfo::FunctionName() { 407 DCHECK(HasFunctionName()); 408 return String::cast(get(FunctionNameEntryIndex())); 409 } 410 411 412 String* ScopeInfo::ParameterName(int var) { 413 DCHECK(0 <= var && var < ParameterCount()); 414 int info_index = ParameterEntriesIndex() + var; 415 return String::cast(get(info_index)); 416 } 417 418 419 String* ScopeInfo::LocalName(int var) { 420 DCHECK(0 <= var && var < LocalCount()); 421 DCHECK(StackLocalEntriesIndex() + StackLocalCount() == 422 ContextLocalNameEntriesIndex()); 423 int info_index = StackLocalEntriesIndex() + var; 424 return String::cast(get(info_index)); 425 } 426 427 428 String* ScopeInfo::StackLocalName(int var) { 429 DCHECK(0 <= var && var < StackLocalCount()); 430 int info_index = StackLocalEntriesIndex() + var; 431 return String::cast(get(info_index)); 432 } 433 434 435 int ScopeInfo::StackLocalIndex(int var) { 436 DCHECK(0 <= var && var < StackLocalCount()); 437 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value(); 438 return first_slot_index + var; 439 } 440 441 442 String* ScopeInfo::ContextLocalName(int var) { 443 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); 444 int info_index = ContextLocalNameEntriesIndex() + var; 445 return String::cast(get(info_index)); 446 } 447 448 449 VariableMode ScopeInfo::ContextLocalMode(int var) { 450 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); 451 int info_index = ContextLocalInfoEntriesIndex() + var; 452 int value = Smi::cast(get(info_index))->value(); 453 return ContextLocalMode::decode(value); 454 } 455 456 457 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) { 458 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); 459 int info_index = ContextLocalInfoEntriesIndex() + var; 460 int value = Smi::cast(get(info_index))->value(); 461 return ContextLocalInitFlag::decode(value); 462 } 463 464 465 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) { 466 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); 467 int info_index = ContextLocalInfoEntriesIndex() + var; 468 int value = Smi::cast(get(info_index))->value(); 469 return ContextLocalMaybeAssignedFlag::decode(value); 470 } 471 472 473 bool ScopeInfo::LocalIsSynthetic(int var) { 474 DCHECK(0 <= var && var < LocalCount()); 475 // There's currently no flag stored on the ScopeInfo to indicate that a 476 // variable is a compiler-introduced temporary. However, to avoid conflict 477 // with user declarations, the current temporaries like .generator_object and 478 // .result start with a dot, so we can use that as a flag. It's a hack! 479 Handle<String> name(LocalName(var)); 480 return (name->length() > 0 && name->Get(0) == '.') || 481 name->Equals(*GetIsolate()->factory()->this_string()); 482 } 483 484 485 String* ScopeInfo::StrongModeFreeVariableName(int var) { 486 DCHECK(0 <= var && var < StrongModeFreeVariableCount()); 487 int info_index = StrongModeFreeVariableNameEntriesIndex() + var; 488 return String::cast(get(info_index)); 489 } 490 491 492 int ScopeInfo::StrongModeFreeVariableStartPosition(int var) { 493 DCHECK(0 <= var && var < StrongModeFreeVariableCount()); 494 int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2; 495 int32_t value = 0; 496 bool ok = get(info_index)->ToInt32(&value); 497 USE(ok); 498 DCHECK(ok); 499 return value; 500 } 501 502 503 int ScopeInfo::StrongModeFreeVariableEndPosition(int var) { 504 DCHECK(0 <= var && var < StrongModeFreeVariableCount()); 505 int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2 + 1; 506 int32_t value = 0; 507 bool ok = get(info_index)->ToInt32(&value); 508 USE(ok); 509 DCHECK(ok); 510 return value; 511 } 512 513 514 int ScopeInfo::StackSlotIndex(String* name) { 515 DCHECK(name->IsInternalizedString()); 516 if (length() > 0) { 517 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value(); 518 int start = StackLocalEntriesIndex(); 519 int end = StackLocalEntriesIndex() + StackLocalCount(); 520 for (int i = start; i < end; ++i) { 521 if (name == get(i)) { 522 return i - start + first_slot_index; 523 } 524 } 525 } 526 return -1; 527 } 528 529 530 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info, 531 Handle<String> name, VariableMode* mode, 532 InitializationFlag* init_flag, 533 MaybeAssignedFlag* maybe_assigned_flag) { 534 DCHECK(name->IsInternalizedString()); 535 DCHECK(mode != NULL); 536 DCHECK(init_flag != NULL); 537 if (scope_info->length() > 0) { 538 ContextSlotCache* context_slot_cache = 539 scope_info->GetIsolate()->context_slot_cache(); 540 int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag, 541 maybe_assigned_flag); 542 if (result != ContextSlotCache::kNotFound) { 543 DCHECK(result < scope_info->ContextLength()); 544 return result; 545 } 546 547 int start = scope_info->ContextLocalNameEntriesIndex(); 548 int end = scope_info->ContextLocalNameEntriesIndex() + 549 scope_info->ContextLocalCount(); 550 for (int i = start; i < end; ++i) { 551 if (*name == scope_info->get(i)) { 552 int var = i - start; 553 *mode = scope_info->ContextLocalMode(var); 554 *init_flag = scope_info->ContextLocalInitFlag(var); 555 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var); 556 result = Context::MIN_CONTEXT_SLOTS + var; 557 558 context_slot_cache->Update(scope_info, name, *mode, *init_flag, 559 *maybe_assigned_flag, result); 560 DCHECK(result < scope_info->ContextLength()); 561 return result; 562 } 563 } 564 // Cache as not found. Mode, init flag and maybe assigned flag don't matter. 565 context_slot_cache->Update(scope_info, name, TEMPORARY, 566 kNeedsInitialization, kNotAssigned, -1); 567 } 568 return -1; 569 } 570 571 572 int ScopeInfo::ContextGlobalSlotIndex(Handle<ScopeInfo> scope_info, 573 Handle<String> name, VariableMode* mode, 574 InitializationFlag* init_flag, 575 MaybeAssignedFlag* maybe_assigned_flag) { 576 DCHECK(name->IsInternalizedString()); 577 DCHECK(mode != NULL); 578 DCHECK(init_flag != NULL); 579 if (scope_info->length() > 0) { 580 // This is to ensure that ContextLocalMode() and co. queries would work. 581 DCHECK_EQ(scope_info->ContextGlobalNameEntriesIndex(), 582 scope_info->ContextLocalNameEntriesIndex() + 583 scope_info->ContextLocalCount()); 584 int base = scope_info->ContextLocalNameEntriesIndex(); 585 int start = scope_info->ContextGlobalNameEntriesIndex(); 586 int end = scope_info->ContextGlobalNameEntriesIndex() + 587 scope_info->ContextGlobalCount(); 588 for (int i = start; i < end; ++i) { 589 if (*name == scope_info->get(i)) { 590 int var = i - base; 591 *mode = scope_info->ContextLocalMode(var); 592 *init_flag = scope_info->ContextLocalInitFlag(var); 593 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var); 594 int result = Context::MIN_CONTEXT_SLOTS + var; 595 DCHECK(result < scope_info->ContextLength()); 596 return result; 597 } 598 } 599 } 600 return -1; 601 } 602 603 604 String* ScopeInfo::ContextSlotName(int slot_index) { 605 int const var = slot_index - Context::MIN_CONTEXT_SLOTS; 606 DCHECK_LE(0, var); 607 DCHECK_LT(var, ContextLocalCount() + ContextGlobalCount()); 608 return ContextLocalName(var); 609 } 610 611 612 int ScopeInfo::ParameterIndex(String* name) { 613 DCHECK(name->IsInternalizedString()); 614 if (length() > 0) { 615 // We must read parameters from the end since for 616 // multiply declared parameters the value of the 617 // last declaration of that parameter is used 618 // inside a function (and thus we need to look 619 // at the last index). Was bug# 1110337. 620 int start = ParameterEntriesIndex(); 621 int end = ParameterEntriesIndex() + ParameterCount(); 622 for (int i = end - 1; i >= start; --i) { 623 if (name == get(i)) { 624 return i - start; 625 } 626 } 627 } 628 return -1; 629 } 630 631 632 int ScopeInfo::ReceiverContextSlotIndex() { 633 if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT) 634 return Smi::cast(get(ReceiverEntryIndex()))->value(); 635 return -1; 636 } 637 638 639 int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) { 640 DCHECK(name->IsInternalizedString()); 641 DCHECK(mode != NULL); 642 if (length() > 0) { 643 if (FunctionVariableField::decode(Flags()) == CONTEXT && 644 FunctionName() == name) { 645 *mode = FunctionVariableMode::decode(Flags()); 646 return Smi::cast(get(FunctionNameEntryIndex() + 1))->value(); 647 } 648 } 649 return -1; 650 } 651 652 653 FunctionKind ScopeInfo::function_kind() { 654 return FunctionKindField::decode(Flags()); 655 } 656 657 658 int ScopeInfo::ParameterEntriesIndex() { 659 DCHECK(length() > 0); 660 return kVariablePartIndex; 661 } 662 663 664 int ScopeInfo::StackLocalFirstSlotIndex() { 665 return ParameterEntriesIndex() + ParameterCount(); 666 } 667 668 669 int ScopeInfo::StackLocalEntriesIndex() { 670 return StackLocalFirstSlotIndex() + 1; 671 } 672 673 674 int ScopeInfo::ContextLocalNameEntriesIndex() { 675 return StackLocalEntriesIndex() + StackLocalCount(); 676 } 677 678 679 int ScopeInfo::ContextGlobalNameEntriesIndex() { 680 return ContextLocalNameEntriesIndex() + ContextLocalCount(); 681 } 682 683 684 int ScopeInfo::ContextLocalInfoEntriesIndex() { 685 return ContextGlobalNameEntriesIndex() + ContextGlobalCount(); 686 } 687 688 689 int ScopeInfo::ContextGlobalInfoEntriesIndex() { 690 return ContextLocalInfoEntriesIndex() + ContextLocalCount(); 691 } 692 693 694 int ScopeInfo::StrongModeFreeVariableNameEntriesIndex() { 695 return ContextGlobalInfoEntriesIndex() + ContextGlobalCount(); 696 } 697 698 699 int ScopeInfo::StrongModeFreeVariablePositionEntriesIndex() { 700 return StrongModeFreeVariableNameEntriesIndex() + 701 StrongModeFreeVariableCount(); 702 } 703 704 705 int ScopeInfo::ReceiverEntryIndex() { 706 return StrongModeFreeVariablePositionEntriesIndex() + 707 2 * StrongModeFreeVariableCount(); 708 } 709 710 711 int ScopeInfo::FunctionNameEntryIndex() { 712 return ReceiverEntryIndex() + (HasAllocatedReceiver() ? 1 : 0); 713 } 714 715 716 int ContextSlotCache::Hash(Object* data, String* name) { 717 // Uses only lower 32 bits if pointers are larger. 718 uintptr_t addr_hash = 719 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2; 720 return static_cast<int>((addr_hash ^ name->Hash()) % kLength); 721 } 722 723 724 int ContextSlotCache::Lookup(Object* data, String* name, VariableMode* mode, 725 InitializationFlag* init_flag, 726 MaybeAssignedFlag* maybe_assigned_flag) { 727 int index = Hash(data, name); 728 Key& key = keys_[index]; 729 if ((key.data == data) && key.name->Equals(name)) { 730 Value result(values_[index]); 731 if (mode != NULL) *mode = result.mode(); 732 if (init_flag != NULL) *init_flag = result.initialization_flag(); 733 if (maybe_assigned_flag != NULL) 734 *maybe_assigned_flag = result.maybe_assigned_flag(); 735 return result.index() + kNotFound; 736 } 737 return kNotFound; 738 } 739 740 741 void ContextSlotCache::Update(Handle<Object> data, Handle<String> name, 742 VariableMode mode, InitializationFlag init_flag, 743 MaybeAssignedFlag maybe_assigned_flag, 744 int slot_index) { 745 DisallowHeapAllocation no_gc; 746 Handle<String> internalized_name; 747 DCHECK(slot_index > kNotFound); 748 if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name). 749 ToHandle(&internalized_name)) { 750 int index = Hash(*data, *internalized_name); 751 Key& key = keys_[index]; 752 key.data = *data; 753 key.name = *internalized_name; 754 // Please note value only takes a uint as index. 755 values_[index] = Value(mode, init_flag, maybe_assigned_flag, 756 slot_index - kNotFound).raw(); 757 #ifdef DEBUG 758 ValidateEntry(data, name, mode, init_flag, maybe_assigned_flag, slot_index); 759 #endif 760 } 761 } 762 763 764 void ContextSlotCache::Clear() { 765 for (int index = 0; index < kLength; index++) keys_[index].data = NULL; 766 } 767 768 769 #ifdef DEBUG 770 771 void ContextSlotCache::ValidateEntry(Handle<Object> data, Handle<String> name, 772 VariableMode mode, 773 InitializationFlag init_flag, 774 MaybeAssignedFlag maybe_assigned_flag, 775 int slot_index) { 776 DisallowHeapAllocation no_gc; 777 Handle<String> internalized_name; 778 if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name). 779 ToHandle(&internalized_name)) { 780 int index = Hash(*data, *name); 781 Key& key = keys_[index]; 782 DCHECK(key.data == *data); 783 DCHECK(key.name->Equals(*name)); 784 Value result(values_[index]); 785 DCHECK(result.mode() == mode); 786 DCHECK(result.initialization_flag() == init_flag); 787 DCHECK(result.maybe_assigned_flag() == maybe_assigned_flag); 788 DCHECK(result.index() + kNotFound == slot_index); 789 } 790 } 791 792 793 static void PrintList(const char* list_name, 794 int nof_internal_slots, 795 int start, 796 int end, 797 ScopeInfo* scope_info) { 798 if (start < end) { 799 PrintF("\n // %s\n", list_name); 800 if (nof_internal_slots > 0) { 801 PrintF(" %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1); 802 } 803 for (int i = nof_internal_slots; start < end; ++i, ++start) { 804 PrintF(" %2d ", i); 805 String::cast(scope_info->get(start))->ShortPrint(); 806 PrintF("\n"); 807 } 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, ParameterEntriesIndex(), 823 ParameterEntriesIndex() + ParameterCount(), this); 824 PrintList("stack slots", 0, StackLocalEntriesIndex(), 825 StackLocalEntriesIndex() + StackLocalCount(), this); 826 PrintList("context slots", Context::MIN_CONTEXT_SLOTS, 827 ContextLocalNameEntriesIndex(), 828 ContextLocalNameEntriesIndex() + ContextLocalCount(), this); 829 } 830 831 PrintF("}\n"); 832 } 833 #endif // DEBUG 834 835 836 //--------------------------------------------------------------------------- 837 // ModuleInfo. 838 839 Handle<ModuleInfo> ModuleInfo::Create(Isolate* isolate, 840 ModuleDescriptor* descriptor, 841 Scope* scope) { 842 Handle<ModuleInfo> info = Allocate(isolate, descriptor->Length()); 843 info->set_host_index(descriptor->Index()); 844 int i = 0; 845 for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done(); 846 it.Advance(), ++i) { 847 Variable* var = scope->LookupLocal(it.local_name()); 848 info->set_name(i, *(it.export_name()->string())); 849 info->set_mode(i, var->mode()); 850 DCHECK(var->index() >= 0); 851 info->set_index(i, var->index()); 852 } 853 DCHECK(i == info->length()); 854 return info; 855 } 856 857 } // namespace internal 858 } // namespace v8 859