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