scopeinfo.cc 22 KB
Newer Older
1
// Copyright 2011 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4 5 6

#include <stdlib.h>

7
#include "src/v8.h"
8

9 10
#include "src/scopeinfo.h"
#include "src/scopes.h"
11

12 13
namespace v8 {
namespace internal {
14 15


16 17
Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
                                    Scope* scope) {
18
  // Collect stack and context locals.
19 20
  ZoneList<Variable*> stack_locals(scope->StackLocalCount(), zone);
  ZoneList<Variable*> context_locals(scope->ContextLocalCount(), zone);
21 22 23 24
  ZoneList<Variable*> strong_mode_free_variables(0, zone);

  scope->CollectStackAndContextLocals(&stack_locals, &context_locals,
                                      &strong_mode_free_variables);
25 26
  const int stack_local_count = stack_locals.length();
  const int context_local_count = context_locals.length();
27 28
  const int strong_mode_free_variable_count =
      strong_mode_free_variables.length();
29
  // Make sure we allocate the correct amount.
30
  DCHECK(scope->ContextLocalCount() == context_local_count);
31

32 33 34
  bool simple_parameter_list =
      scope->is_function_scope() ? scope->is_simple_parameter_list() : true;

35 36 37 38
  // Determine use and location of the function variable if it is present.
  FunctionVariableInfo function_name_info;
  VariableMode function_variable_mode;
  if (scope->is_function_scope() && scope->function() != NULL) {
39
    Variable* var = scope->function()->proxy()->var();
40 41 42 43 44
    if (!var->is_used()) {
      function_name_info = UNUSED;
    } else if (var->IsContextSlot()) {
      function_name_info = CONTEXT;
    } else {
45
      DCHECK(var->IsStackLocal());
46
      function_name_info = STACK;
47
    }
48
    function_variable_mode = var->mode();
49
  } else {
50 51
    function_name_info = NONE;
    function_variable_mode = VAR;
52 53
  }

54 55
  const bool has_function_name = function_name_info != NONE;
  const int parameter_count = scope->num_parameters();
56 57
  const int length = kVariablePartIndex + parameter_count +
                     (1 + stack_local_count) + 2 * context_local_count +
58 59
                     3 * strong_mode_free_variable_count +
                     (has_function_name ? 2 : 0);
60

61
  Factory* factory = isolate->factory();
62
  Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
63 64

  // Encode the flags.
65
  int flags = ScopeTypeField::encode(scope->scope_type()) |
66
              CallsEvalField::encode(scope->calls_eval()) |
67
              LanguageModeField::encode(scope->language_mode()) |
68 69 70
              FunctionVariableField::encode(function_name_info) |
              FunctionVariableMode::encode(function_variable_mode) |
              AsmModuleField::encode(scope->asm_module()) |
71
              AsmFunctionField::encode(scope->asm_function()) |
72 73 74
              IsSimpleParameterListField::encode(simple_parameter_list) |
              BlockScopeIsClassScopeField::encode(scope->is_class_scope()) |
              FunctionKindField::encode(scope->function_kind());
75 76 77 78
  scope_info->SetFlags(flags);
  scope_info->SetParameterCount(parameter_count);
  scope_info->SetStackLocalCount(stack_local_count);
  scope_info->SetContextLocalCount(context_local_count);
79
  scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);
80 81 82

  int index = kVariablePartIndex;
  // Add parameters.
83
  DCHECK(index == scope_info->ParameterEntriesIndex());
84 85
  for (int i = 0; i < parameter_count; ++i) {
    scope_info->set(index++, *scope->parameter(i)->name());
86 87
  }

88 89 90
  // Add stack locals' names. We are assuming that the stack locals'
  // slots are allocated in increasing order, so we can simply add
  // them to the ScopeInfo object.
91 92 93 94 95 96 97 98
  int first_slot_index;
  if (stack_local_count > 0) {
    first_slot_index = stack_locals[0]->index();
  } else {
    first_slot_index = 0;
  }
  DCHECK(index == scope_info->StackLocalFirstSlotIndex());
  scope_info->set(index++, Smi::FromInt(first_slot_index));
99
  DCHECK(index == scope_info->StackLocalEntriesIndex());
100
  for (int i = 0; i < stack_local_count; ++i) {
101
    DCHECK(stack_locals[i]->index() == first_slot_index + i);
102 103
    scope_info->set(index++, *stack_locals[i]->name());
  }
104

105 106 107 108 109 110
  // Due to usage analysis, context-allocated locals are not necessarily in
  // increasing order: Some of them may be parameters which are allocated before
  // the non-parameter locals. When the non-parameter locals are sorted
  // according to usage, the allocated slot indices may not be in increasing
  // order with the variable list anymore. Thus, we first need to sort them by
  // context slot index before adding them to the ScopeInfo object.
111
  context_locals.Sort(&Variable::CompareIndex);
112 113

  // Add context locals' names.
114
  DCHECK(index == scope_info->ContextLocalNameEntriesIndex());
115 116 117
  for (int i = 0; i < context_local_count; ++i) {
    scope_info->set(index++, *context_locals[i]->name());
  }
118

119
  // Add context locals' info.
120
  DCHECK(index == scope_info->ContextLocalInfoEntriesIndex());
121
  for (int i = 0; i < context_local_count; ++i) {
122
    Variable* var = context_locals[i];
123 124 125 126
    uint32_t value =
        ContextLocalMode::encode(var->mode()) |
        ContextLocalInitFlag::encode(var->initialization_flag()) |
        ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned());
127
    scope_info->set(index++, Smi::FromInt(value));
128
  }
129

130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
  DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex());
  for (int i = 0; i < strong_mode_free_variable_count; ++i) {
    scope_info->set(index++, *strong_mode_free_variables[i]->name());
  }

  DCHECK(index == scope_info->StrongModeFreeVariablePositionEntriesIndex());
  for (int i = 0; i < strong_mode_free_variable_count; ++i) {
    // Unfortunately, the source code positions are stored as int even though
    // int32_t would be enough (given the maximum source code length).
    Handle<Object> start_position = factory->NewNumberFromInt(
        static_cast<int32_t>(strong_mode_free_variables[i]
                                 ->strong_mode_reference_start_position()));
    scope_info->set(index++, *start_position);
    Handle<Object> end_position = factory->NewNumberFromInt(
        static_cast<int32_t>(strong_mode_free_variables[i]
                                 ->strong_mode_reference_end_position()));
    scope_info->set(index++, *end_position);
  }

149
  // If present, add the function variable name and its index.
150
  DCHECK(index == scope_info->FunctionNameEntryIndex());
151
  if (has_function_name) {
152 153
    int var_index = scope->function()->proxy()->var()->index();
    scope_info->set(index++, *scope->function()->proxy()->name());
154
    scope_info->set(index++, Smi::FromInt(var_index));
155
    DCHECK(function_name_info != CONTEXT ||
156 157
           var_index == scope_info->ContextLength() - 1);
  }
158

159 160 161
  DCHECK(index == scope_info->length());
  DCHECK(scope->num_parameters() == scope_info->ParameterCount());
  DCHECK(scope->num_heap_slots() == scope_info->ContextLength() ||
162 163
         (scope->num_heap_slots() == kVariablePartIndex &&
          scope_info->ContextLength() == 0));
164
  return scope_info;
165 166 167
}


168 169
ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
  return reinterpret_cast<ScopeInfo*>(isolate->heap()->empty_fixed_array());
170 171 172
}


173
ScopeType ScopeInfo::scope_type() {
174
  DCHECK(length() > 0);
175
  return ScopeTypeField::decode(Flags());
176 177 178
}


179 180
bool ScopeInfo::CallsEval() {
  return length() > 0 && CallsEvalField::decode(Flags());
181 182 183
}


184 185
LanguageMode ScopeInfo::language_mode() {
  return length() > 0 ? LanguageModeField::decode(Flags()) : SLOPPY;
186 187 188
}


189 190
int ScopeInfo::LocalCount() {
  return StackLocalCount() + ContextLocalCount();
191 192 193
}


194 195 196 197 198 199 200
int ScopeInfo::StackSlotCount() {
  if (length() > 0) {
    bool function_name_stack_slot =
        FunctionVariableField::decode(Flags()) == STACK;
    return StackLocalCount() + (function_name_stack_slot ? 1 : 0);
  }
  return 0;
201 202 203
}


204 205 206 207 208
int ScopeInfo::ContextLength() {
  if (length() > 0) {
    int context_locals = ContextLocalCount();
    bool function_name_context_slot =
        FunctionVariableField::decode(Flags()) == CONTEXT;
209 210
    bool has_context = context_locals > 0 || function_name_context_slot ||
                       scope_type() == WITH_SCOPE ||
211 212
                       (scope_type() == ARROW_SCOPE && CallsSloppyEval()) ||
                       (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) ||
213
                       scope_type() == MODULE_SCOPE;
214 215 216 217
    if (has_context) {
      return Context::MIN_CONTEXT_SLOTS + context_locals +
          (function_name_context_slot ? 1 : 0);
    }
218
  }
219
  return 0;
220 221 222
}


223 224 225
bool ScopeInfo::HasFunctionName() {
  if (length() > 0) {
    return NONE != FunctionVariableField::decode(Flags());
226
  } else {
227
    return false;
228
  }
229 230 231
}


232 233 234 235 236
bool ScopeInfo::HasHeapAllocatedLocals() {
  if (length() > 0) {
    return ContextLocalCount() > 0;
  } else {
    return false;
237 238 239 240
  }
}


241
bool ScopeInfo::HasContext() {
242
  return ContextLength() > 0;
243 244 245
}


246
String* ScopeInfo::FunctionName() {
247
  DCHECK(HasFunctionName());
248
  return String::cast(get(FunctionNameEntryIndex()));
249 250 251
}


252
String* ScopeInfo::ParameterName(int var) {
253
  DCHECK(0 <= var && var < ParameterCount());
254 255
  int info_index = ParameterEntriesIndex() + var;
  return String::cast(get(info_index));
256 257 258
}


259
String* ScopeInfo::LocalName(int var) {
260 261
  DCHECK(0 <= var && var < LocalCount());
  DCHECK(StackLocalEntriesIndex() + StackLocalCount() ==
262 263 264
         ContextLocalNameEntriesIndex());
  int info_index = StackLocalEntriesIndex() + var;
  return String::cast(get(info_index));
265 266 267
}


268
String* ScopeInfo::StackLocalName(int var) {
269
  DCHECK(0 <= var && var < StackLocalCount());
270 271
  int info_index = StackLocalEntriesIndex() + var;
  return String::cast(get(info_index));
272 273 274
}


275 276 277 278 279 280 281
int ScopeInfo::StackLocalIndex(int var) {
  DCHECK(0 <= var && var < StackLocalCount());
  int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
  return first_slot_index + var;
}


282
String* ScopeInfo::ContextLocalName(int var) {
283
  DCHECK(0 <= var && var < ContextLocalCount());
284 285
  int info_index = ContextLocalNameEntriesIndex() + var;
  return String::cast(get(info_index));
286 287 288
}


289
VariableMode ScopeInfo::ContextLocalMode(int var) {
290
  DCHECK(0 <= var && var < ContextLocalCount());
291 292 293 294 295 296 297
  int info_index = ContextLocalInfoEntriesIndex() + var;
  int value = Smi::cast(get(info_index))->value();
  return ContextLocalMode::decode(value);
}


InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
298
  DCHECK(0 <= var && var < ContextLocalCount());
299 300 301
  int info_index = ContextLocalInfoEntriesIndex() + var;
  int value = Smi::cast(get(info_index))->value();
  return ContextLocalInitFlag::decode(value);
302 303 304
}


305
MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) {
306
  DCHECK(0 <= var && var < ContextLocalCount());
307 308 309 310 311 312
  int info_index = ContextLocalInfoEntriesIndex() + var;
  int value = Smi::cast(get(info_index))->value();
  return ContextLocalMaybeAssignedFlag::decode(value);
}


313
bool ScopeInfo::LocalIsSynthetic(int var) {
314
  DCHECK(0 <= var && var < LocalCount());
315 316 317 318 319 320 321 322 323
  // There's currently no flag stored on the ScopeInfo to indicate that a
  // variable is a compiler-introduced temporary. However, to avoid conflict
  // with user declarations, the current temporaries like .generator_object and
  // .result start with a dot, so we can use that as a flag. It's a hack!
  Handle<String> name(LocalName(var));
  return name->length() > 0 && name->Get(0) == '.';
}


324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
String* ScopeInfo::StrongModeFreeVariableName(int var) {
  DCHECK(0 <= var && var < StrongModeFreeVariableCount());
  int info_index = StrongModeFreeVariableNameEntriesIndex() + var;
  return String::cast(get(info_index));
}


int ScopeInfo::StrongModeFreeVariableStartPosition(int var) {
  DCHECK(0 <= var && var < StrongModeFreeVariableCount());
  int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2;
  int32_t value = 0;
  bool ok = get(info_index)->ToInt32(&value);
  USE(ok);
  DCHECK(ok);
  return value;
}


int ScopeInfo::StrongModeFreeVariableEndPosition(int var) {
  DCHECK(0 <= var && var < StrongModeFreeVariableCount());
  int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2 + 1;
  int32_t value = 0;
  bool ok = get(info_index)->ToInt32(&value);
  USE(ok);
  DCHECK(ok);
  return value;
}


353
int ScopeInfo::StackSlotIndex(String* name) {
354
  DCHECK(name->IsInternalizedString());
355
  if (length() > 0) {
356
    int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
357 358 359 360
    int start = StackLocalEntriesIndex();
    int end = StackLocalEntriesIndex() + StackLocalCount();
    for (int i = start; i < end; ++i) {
      if (name == get(i)) {
361
        return i - start + first_slot_index;
362
      }
363 364 365 366 367
    }
  }
  return -1;
}

368

369
int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
370 371 372
                                Handle<String> name, VariableMode* mode,
                                InitializationFlag* init_flag,
                                MaybeAssignedFlag* maybe_assigned_flag) {
373 374 375
  DCHECK(name->IsInternalizedString());
  DCHECK(mode != NULL);
  DCHECK(init_flag != NULL);
376 377 378
  if (scope_info->length() > 0) {
    ContextSlotCache* context_slot_cache =
        scope_info->GetIsolate()->context_slot_cache();
379 380
    int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag,
                                            maybe_assigned_flag);
381
    if (result != ContextSlotCache::kNotFound) {
382
      DCHECK(result < scope_info->ContextLength());
383 384 385
      return result;
    }

386 387 388
    int start = scope_info->ContextLocalNameEntriesIndex();
    int end = scope_info->ContextLocalNameEntriesIndex() +
        scope_info->ContextLocalCount();
389
    for (int i = start; i < end; ++i) {
390
      if (*name == scope_info->get(i)) {
391
        int var = i - start;
392 393
        *mode = scope_info->ContextLocalMode(var);
        *init_flag = scope_info->ContextLocalInitFlag(var);
394
        *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
395
        result = Context::MIN_CONTEXT_SLOTS + var;
396 397
        context_slot_cache->Update(scope_info, name, *mode, *init_flag,
                                   *maybe_assigned_flag, result);
398
        DCHECK(result < scope_info->ContextLength());
399
        return result;
400 401
      }
    }
402 403 404
    // Cache as not found. Mode, init flag and maybe assigned flag don't matter.
    context_slot_cache->Update(scope_info, name, INTERNAL, kNeedsInitialization,
                               kNotAssigned, -1);
405 406 407 408 409
  }
  return -1;
}


410
int ScopeInfo::ParameterIndex(String* name) {
411
  DCHECK(name->IsInternalizedString());
412
  if (length() > 0) {
413 414 415 416 417
    // We must read parameters from the end since for
    // multiply declared parameters the value of the
    // last declaration of that parameter is used
    // inside a function (and thus we need to look
    // at the last index). Was bug# 1110337.
418 419 420 421 422 423
    int start = ParameterEntriesIndex();
    int end = ParameterEntriesIndex() + ParameterCount();
    for (int i = end - 1; i >= start; --i) {
      if (name == get(i)) {
        return i - start;
      }
424 425 426 427 428 429
    }
  }
  return -1;
}


430
int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) {
431 432
  DCHECK(name->IsInternalizedString());
  DCHECK(mode != NULL);
433
  if (length() > 0) {
434 435 436 437
    if (FunctionVariableField::decode(Flags()) == CONTEXT &&
        FunctionName() == name) {
      *mode = FunctionVariableMode::decode(Flags());
      return Smi::cast(get(FunctionNameEntryIndex() + 1))->value();
438 439 440 441 442 443
    }
  }
  return -1;
}


444 445 446 447 448 449 450 451 452 453
bool ScopeInfo::block_scope_is_class_scope() {
  return BlockScopeIsClassScopeField::decode(Flags());
}


FunctionKind ScopeInfo::function_kind() {
  return FunctionKindField::decode(Flags());
}


454 455 456 457 458
bool ScopeInfo::CopyContextLocalsToScopeObject(Handle<ScopeInfo> scope_info,
                                               Handle<Context> context,
                                               Handle<JSObject> scope_object) {
  Isolate* isolate = scope_info->GetIsolate();
  int local_count = scope_info->ContextLocalCount();
459 460
  if (local_count == 0) return true;
  // Fill all context locals to the context extension.
461
  int first_context_var = scope_info->StackLocalCount();
462
  int start = scope_info->ContextLocalNameEntriesIndex();
463 464 465
  for (int i = 0; i < local_count; ++i) {
    if (scope_info->LocalIsSynthetic(first_context_var + i)) continue;
    int context_index = Context::MIN_CONTEXT_SLOTS + i;
466
    Handle<Object> value = Handle<Object>(context->get(context_index), isolate);
467
    // Reflect variables under TDZ as undefined in scope object.
468
    if (value->IsTheHole()) continue;
469
    RETURN_ON_EXCEPTION_VALUE(
470 471 472 473
        isolate, Runtime::DefineObjectProperty(
                     scope_object,
                     Handle<String>(String::cast(scope_info->get(i + start))),
                     value, ::NONE),
474
        false);
475 476 477 478 479
  }
  return true;
}


480
int ScopeInfo::ParameterEntriesIndex() {
481
  DCHECK(length() > 0);
482 483 484 485
  return kVariablePartIndex;
}


486
int ScopeInfo::StackLocalFirstSlotIndex() {
487 488 489 490
  return ParameterEntriesIndex() + ParameterCount();
}


491 492 493 494 495
int ScopeInfo::StackLocalEntriesIndex() {
  return StackLocalFirstSlotIndex() + 1;
}


496 497 498 499 500
int ScopeInfo::ContextLocalNameEntriesIndex() {
  return StackLocalEntriesIndex() + StackLocalCount();
}


501
int ScopeInfo::ContextLocalInfoEntriesIndex() {
502 503 504 505
  return ContextLocalNameEntriesIndex() + ContextLocalCount();
}


506
int ScopeInfo::StrongModeFreeVariableNameEntriesIndex() {
507
  return ContextLocalInfoEntriesIndex() + ContextLocalCount();
508 509 510
}


511 512 513 514 515 516 517 518 519 520 521 522
int ScopeInfo::StrongModeFreeVariablePositionEntriesIndex() {
  return StrongModeFreeVariableNameEntriesIndex() +
         StrongModeFreeVariableCount();
}


int ScopeInfo::FunctionNameEntryIndex() {
  return StrongModeFreeVariablePositionEntriesIndex() +
         2 * StrongModeFreeVariableCount();
}


523
int ContextSlotCache::Hash(Object* data, String* name) {
524 525
  // Uses only lower 32 bits if pointers are larger.
  uintptr_t addr_hash =
526
      static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2;
527
  return static_cast<int>((addr_hash ^ name->Hash()) % kLength);
528 529 530
}


531 532 533
int ContextSlotCache::Lookup(Object* data, String* name, VariableMode* mode,
                             InitializationFlag* init_flag,
                             MaybeAssignedFlag* maybe_assigned_flag) {
534
  int index = Hash(data, name);
535
  Key& key = keys_[index];
536
  if ((key.data == data) && key.name->Equals(name)) {
537 538
    Value result(values_[index]);
    if (mode != NULL) *mode = result.mode();
539
    if (init_flag != NULL) *init_flag = result.initialization_flag();
540 541
    if (maybe_assigned_flag != NULL)
      *maybe_assigned_flag = result.maybe_assigned_flag();
542 543 544 545 546 547
    return result.index() + kNotFound;
  }
  return kNotFound;
}


548 549 550
void ContextSlotCache::Update(Handle<Object> data, Handle<String> name,
                              VariableMode mode, InitializationFlag init_flag,
                              MaybeAssignedFlag maybe_assigned_flag,
551
                              int slot_index) {
552
  DisallowHeapAllocation no_gc;
553
  Handle<String> internalized_name;
554
  DCHECK(slot_index > kNotFound);
555 556 557
  if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name).
      ToHandle(&internalized_name)) {
    int index = Hash(*data, *internalized_name);
558
    Key& key = keys_[index];
559
    key.data = *data;
560
    key.name = *internalized_name;
561
    // Please note value only takes a uint as index.
562 563
    values_[index] = Value(mode, init_flag, maybe_assigned_flag,
                           slot_index - kNotFound).raw();
564
#ifdef DEBUG
565
    ValidateEntry(data, name, mode, init_flag, maybe_assigned_flag, slot_index);
566 567 568 569 570 571
#endif
  }
}


void ContextSlotCache::Clear() {
572
  for (int index = 0; index < kLength; index++) keys_[index].data = NULL;
573 574 575
}


576
#ifdef DEBUG
577

578
void ContextSlotCache::ValidateEntry(Handle<Object> data, Handle<String> name,
579
                                     VariableMode mode,
580
                                     InitializationFlag init_flag,
581
                                     MaybeAssignedFlag maybe_assigned_flag,
582
                                     int slot_index) {
583
  DisallowHeapAllocation no_gc;
584 585 586
  Handle<String> internalized_name;
  if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name).
      ToHandle(&internalized_name)) {
587
    int index = Hash(*data, *name);
588
    Key& key = keys_[index];
589 590
    DCHECK(key.data == *data);
    DCHECK(key.name->Equals(*name));
591
    Value result(values_[index]);
592 593 594 595
    DCHECK(result.mode() == mode);
    DCHECK(result.initialization_flag() == init_flag);
    DCHECK(result.maybe_assigned_flag() == maybe_assigned_flag);
    DCHECK(result.index() + kNotFound == slot_index);
596 597 598 599
  }
}


600 601
static void PrintList(const char* list_name,
                      int nof_internal_slots,
602 603 604 605
                      int start,
                      int end,
                      ScopeInfo* scope_info) {
  if (start < end) {
606 607 608 609
    PrintF("\n  // %s\n", list_name);
    if (nof_internal_slots > 0) {
      PrintF("  %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
    }
610 611 612
    for (int i = nof_internal_slots; start < end; ++i, ++start) {
      PrintF("  %2d ", i);
      String::cast(scope_info->get(start))->ShortPrint();
613 614 615 616 617 618
      PrintF("\n");
    }
  }
}


619
void ScopeInfo::Print() {
620
  PrintF("ScopeInfo ");
621 622 623
  if (HasFunctionName()) {
    FunctionName()->ShortPrint();
  } else {
624
    PrintF("/* no function name */");
625
  }
626 627
  PrintF("{");

628 629 630 631 632 633 634 635 636 637 638 639 640
  PrintList("parameters", 0,
            ParameterEntriesIndex(),
            ParameterEntriesIndex() + ParameterCount(),
            this);
  PrintList("stack slots", 0,
            StackLocalEntriesIndex(),
            StackLocalEntriesIndex() + StackLocalCount(),
            this);
  PrintList("context slots",
            Context::MIN_CONTEXT_SLOTS,
            ContextLocalNameEntriesIndex(),
            ContextLocalNameEntriesIndex() + ContextLocalCount(),
            this);
641 642 643 644 645

  PrintF("}\n");
}
#endif  // DEBUG

646 647 648 649

//---------------------------------------------------------------------------
// ModuleInfo.

650 651 652 653 654
Handle<ModuleInfo> ModuleInfo::Create(Isolate* isolate,
                                      ModuleDescriptor* descriptor,
                                      Scope* scope) {
  Handle<ModuleInfo> info = Allocate(isolate, descriptor->Length());
  info->set_host_index(descriptor->Index());
655
  int i = 0;
656 657
  for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done();
       it.Advance(), ++i) {
658 659
    Variable* var = scope->LookupLocal(it.local_name());
    info->set_name(i, *(it.export_name()->string()));
660
    info->set_mode(i, var->mode());
661 662
    DCHECK(var->index() >= 0);
    info->set_index(i, var->index());
663
  }
664
  DCHECK(i == info->length());
665 666 667
  return info;
}

668
} }  // namespace v8::internal