scopeinfo.cc 32.6 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
#include <stdlib.h>
6

7
#include "src/ast/context-slot-cache.h"
8
#include "src/ast/scopes.h"
9
#include "src/ast/variables.h"
10
#include "src/bootstrapper.h"
11

12 13
namespace v8 {
namespace internal {
14

15 16 17 18 19 20 21
// An entry in ModuleVariableEntries consists of several slots:
enum ModuleVariableEntryOffset {
  kModuleVariableNameOffset,
  kModuleVariableIndexOffset,
  kModuleVariablePropertiesOffset,
  kModuleVariableEntryLength  // Sentinel value.
};
22

jochen's avatar
jochen committed
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
#ifdef DEBUG
bool ScopeInfo::Equals(ScopeInfo* other) const {
  if (length() != other->length()) return false;
  for (int index = 0; index < length(); ++index) {
    Object* entry = get(index);
    Object* other_entry = other->get(index);
    if (entry->IsSmi()) {
      if (entry != other_entry) return false;
    } else {
      if (HeapObject::cast(entry)->map()->instance_type() !=
          HeapObject::cast(other_entry)->map()->instance_type()) {
        return false;
      }
      if (entry->IsString()) {
        if (!String::cast(entry)->Equals(String::cast(other_entry))) {
          return false;
        }
      } else if (entry->IsScopeInfo()) {
        if (!ScopeInfo::cast(entry)->Equals(ScopeInfo::cast(other_entry))) {
          return false;
        }
      } else if (entry->IsModuleInfo()) {
        if (!ModuleInfo::cast(entry)->Equals(ModuleInfo::cast(other_entry))) {
          return false;
        }
      } else {
        UNREACHABLE();
        return false;
      }
    }
  }
  return true;
}
#endif

Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
                                    MaybeHandle<ScopeInfo> outer_scope) {
60
  // Collect variables.
61 62
  int stack_local_count = 0;
  int context_local_count = 0;
63
  int module_vars_count = 0;
64 65 66 67 68
  // Stack allocated block scope variables are allocated in the parent
  // declaration scope, but are recorded in the block scope's scope info. First
  // slot index indicates at which offset a particular scope starts in the
  // parent declaration scope.
  int first_slot_index = 0;
69
  for (Variable* var : *scope->locals()) {
70 71 72 73 74 75 76 77 78 79 80 81 82
    switch (var->location()) {
      case VariableLocation::LOCAL:
        if (stack_local_count == 0) first_slot_index = var->index();
        stack_local_count++;
        break;
      case VariableLocation::CONTEXT:
        context_local_count++;
        break;
      case VariableLocation::MODULE:
        module_vars_count++;
        break;
      default:
        break;
83 84
    }
  }
85
  DCHECK(module_vars_count == 0 || scope->is_module_scope());
86

87
  // Make sure we allocate the correct amount.
88
  DCHECK_EQ(scope->ContextLocalCount(), context_local_count);
89

90 91
  // Determine use and location of the "this" binding if it is present.
  VariableAllocationInfo receiver_info;
92 93 94
  if (scope->is_declaration_scope() &&
      scope->AsDeclarationScope()->has_this_declaration()) {
    Variable* var = scope->AsDeclarationScope()->receiver();
95 96 97 98 99 100 101 102 103 104 105 106
    if (!var->is_used()) {
      receiver_info = UNUSED;
    } else if (var->IsContextSlot()) {
      receiver_info = CONTEXT;
    } else {
      DCHECK(var->IsParameter());
      receiver_info = STACK;
    }
  } else {
    receiver_info = NONE;
  }

107 108 109
  bool has_new_target =
      scope->is_declaration_scope() &&
      scope->AsDeclarationScope()->new_target_var() != nullptr;
110

111
  // Determine use and location of the function variable if it is present.
112
  VariableAllocationInfo function_name_info;
113
  if (scope->is_function_scope() &&
114 115
      scope->AsDeclarationScope()->function_var() != nullptr) {
    Variable* var = scope->AsDeclarationScope()->function_var();
116 117 118 119 120
    if (!var->is_used()) {
      function_name_info = UNUSED;
    } else if (var->IsContextSlot()) {
      function_name_info = CONTEXT;
    } else {
121
      DCHECK(var->IsStackLocal());
122
      function_name_info = STACK;
123 124
    }
  } else {
125
    function_name_info = NONE;
126 127
  }

128
  const bool has_function_name = function_name_info != NONE;
129
  const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT;
130
  const int parameter_count = scope->num_parameters();
jochen's avatar
jochen committed
131
  const bool has_outer_scope_info = !outer_scope.is_null();
132 133
  const int length = kVariablePartIndex + parameter_count +
                     (1 + stack_local_count) + 2 * context_local_count +
134
                     (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0) +
jochen's avatar
jochen committed
135
                     (has_outer_scope_info ? 1 : 0) +
136 137 138
                     (scope->is_module_scope()
                          ? 2 + kModuleVariableEntryLength * module_vars_count
                          : 0);
139

140
  Factory* factory = isolate->factory();
141
  Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
142

143 144 145 146 147 148 149 150
  bool has_simple_parameters = false;
  bool asm_module = false;
  bool asm_function = false;
  if (scope->is_function_scope()) {
    DeclarationScope* function_scope = scope->AsDeclarationScope();
    has_simple_parameters = function_scope->has_simple_parameters();
    asm_module = function_scope->asm_module();
    asm_function = function_scope->asm_function();
151 152 153 154
  }
  FunctionKind function_kind = kNormalFunction;
  if (scope->is_declaration_scope()) {
    function_kind = scope->AsDeclarationScope()->function_kind();
155
  }
156

157
  // Encode the flags.
158 159 160 161 162 163 164 165 166 167 168 169 170 171
  int flags =
      ScopeTypeField::encode(scope->scope_type()) |
      CallsEvalField::encode(scope->calls_eval()) |
      LanguageModeField::encode(scope->language_mode()) |
      DeclarationScopeField::encode(scope->is_declaration_scope()) |
      ReceiverVariableField::encode(receiver_info) |
      HasNewTargetField::encode(has_new_target) |
      FunctionVariableField::encode(function_name_info) |
      AsmModuleField::encode(asm_module) |
      AsmFunctionField::encode(asm_function) |
      HasSimpleParametersField::encode(has_simple_parameters) |
      FunctionKindField::encode(function_kind) |
      HasOuterScopeInfoField::encode(has_outer_scope_info) |
      IsDebugEvaluateScopeField::encode(scope->is_debug_evaluate_scope());
172
  scope_info->SetFlags(flags);
173

174 175 176 177 178 179
  scope_info->SetParameterCount(parameter_count);
  scope_info->SetStackLocalCount(stack_local_count);
  scope_info->SetContextLocalCount(context_local_count);

  int index = kVariablePartIndex;
  // Add parameters.
180
  DCHECK_EQ(index, scope_info->ParameterNamesIndex());
181 182 183 184 185
  if (scope->is_declaration_scope()) {
    for (int i = 0; i < parameter_count; ++i) {
      scope_info->set(index++,
                      *scope->AsDeclarationScope()->parameter(i)->name());
    }
186 187
  }

188 189 190 191
  // Add stack locals' names, context locals' names and info, module variables'
  // names and info. We are assuming that the stack locals' slots are allocated
  // in increasing order, so we can simply add them to the ScopeInfo object.
  // Context locals are added using their index.
192
  DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex());
193
  scope_info->set(index++, Smi::FromInt(first_slot_index));
194
  DCHECK_EQ(index, scope_info->StackLocalNamesIndex());
195

196 197 198
  int stack_local_base = index;
  int context_local_base = stack_local_base + stack_local_count;
  int context_local_info_base = context_local_base + context_local_count;
199
  int module_var_entry = scope_info->ModuleVariablesIndex();
200

201
  for (Variable* var : *scope->locals()) {
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
    switch (var->location()) {
      case VariableLocation::LOCAL: {
        int local_index = var->index() - first_slot_index;
        DCHECK_LE(0, local_index);
        DCHECK_LT(local_index, stack_local_count);
        scope_info->set(stack_local_base + local_index, *var->name());
        break;
      }
      case VariableLocation::CONTEXT: {
        // Due to duplicate parameters, context locals aren't guaranteed to come
        // in order.
        int local_index = var->index() - Context::MIN_CONTEXT_SLOTS;
        DCHECK_LE(0, local_index);
        DCHECK_LT(local_index, context_local_count);
        uint32_t info = VariableModeField::encode(var->mode()) |
                        InitFlagField::encode(var->initialization_flag()) |
                        MaybeAssignedFlagField::encode(var->maybe_assigned());
        scope_info->set(context_local_base + local_index, *var->name());
        scope_info->set(context_local_info_base + local_index,
                        Smi::FromInt(info));
        break;
      }
      case VariableLocation::MODULE: {
        scope_info->set(module_var_entry + kModuleVariableNameOffset,
                        *var->name());
        scope_info->set(module_var_entry + kModuleVariableIndexOffset,
                        Smi::FromInt(var->index()));
        uint32_t properties =
            VariableModeField::encode(var->mode()) |
            InitFlagField::encode(var->initialization_flag()) |
            MaybeAssignedFlagField::encode(var->maybe_assigned());
        scope_info->set(module_var_entry + kModuleVariablePropertiesOffset,
                        Smi::FromInt(properties));
        module_var_entry += kModuleVariableEntryLength;
        break;
      }
      default:
        break;
240
    }
241 242
  }

243
  index += stack_local_count + 2 * context_local_count;
244

245
  // If the receiver is allocated, add its index.
246
  DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
247
  if (has_receiver) {
248
    int var_index = scope->AsDeclarationScope()->receiver()->index();
249 250 251 252 253
    scope_info->set(index++, Smi::FromInt(var_index));
    // ?? DCHECK(receiver_info != CONTEXT || var_index ==
    // scope_info->ContextLength() - 1);
  }

254
  // If present, add the function variable name and its index.
255
  DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
256
  if (has_function_name) {
257
    int var_index = scope->AsDeclarationScope()->function_var()->index();
258
    scope_info->set(index++,
259
                    *scope->AsDeclarationScope()->function_var()->name());
260
    scope_info->set(index++, Smi::FromInt(var_index));
261
    DCHECK(function_name_info != CONTEXT ||
262 263
           var_index == scope_info->ContextLength() - 1);
  }
264

jochen's avatar
jochen committed
265
  // If present, add the outer scope info.
266
  DCHECK(index == scope_info->OuterScopeInfoIndex());
jochen's avatar
jochen committed
267 268 269 270
  if (has_outer_scope_info) {
    scope_info->set(index++, *outer_scope.ToHandleChecked());
  }

271 272 273
  // Module-specific information (only for module scopes).
  if (scope->is_module_scope()) {
    Handle<ModuleInfo> module_info =
274
        ModuleInfo::New(isolate, zone, scope->AsModuleScope()->module());
275
    DCHECK_EQ(index, scope_info->ModuleInfoIndex());
276 277 278
    scope_info->set(index++, *module_info);
    DCHECK_EQ(index, scope_info->ModuleVariableCountIndex());
    scope_info->set(index++, Smi::FromInt(module_vars_count));
279
    DCHECK_EQ(index, scope_info->ModuleVariablesIndex());
280 281 282 283
    // The variable entries themselves have already been written above.
    index += kModuleVariableEntryLength * module_vars_count;
  }

284 285 286
  DCHECK_EQ(index, scope_info->length());
  DCHECK_EQ(scope->num_parameters(), scope_info->ParameterCount());
  DCHECK_EQ(scope->num_heap_slots(), scope_info->ContextLength());
287
  return scope_info;
288 289
}

jochen's avatar
jochen committed
290 291 292 293
Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
    Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope) {
  const bool has_outer_scope_info = !outer_scope.is_null();
  const int length = kVariablePartIndex + 1 + (has_outer_scope_info ? 1 : 0);
294 295 296 297 298 299 300 301 302 303 304

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

  // Encode the flags.
  int flags =
      ScopeTypeField::encode(WITH_SCOPE) | CallsEvalField::encode(false) |
      LanguageModeField::encode(SLOPPY) | DeclarationScopeField::encode(false) |
      ReceiverVariableField::encode(NONE) | HasNewTargetField::encode(false) |
      FunctionVariableField::encode(NONE) | AsmModuleField::encode(false) |
      AsmFunctionField::encode(false) | HasSimpleParametersField::encode(true) |
jochen's avatar
jochen committed
305
      FunctionKindField::encode(kNormalFunction) |
306 307
      HasOuterScopeInfoField::encode(has_outer_scope_info) |
      IsDebugEvaluateScopeField::encode(false);
308 309 310 311 312 313 314
  scope_info->SetFlags(flags);

  scope_info->SetParameterCount(0);
  scope_info->SetStackLocalCount(0);
  scope_info->SetContextLocalCount(0);

  int index = kVariablePartIndex;
315
  DCHECK_EQ(index, scope_info->ParameterNamesIndex());
316
  DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex());
317
  scope_info->set(index++, Smi::kZero);
318 319 320 321
  DCHECK_EQ(index, scope_info->StackLocalNamesIndex());
  DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
  DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
  DCHECK(index == scope_info->OuterScopeInfoIndex());
jochen's avatar
jochen committed
322 323 324
  if (has_outer_scope_info) {
    scope_info->set(index++, *outer_scope.ToHandleChecked());
  }
325 326 327 328 329
  DCHECK_EQ(index, scope_info->length());
  DCHECK_EQ(0, scope_info->ParameterCount());
  DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, scope_info->ContextLength());
  return scope_info;
}
330

331 332 333 334 335
Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
  DCHECK(isolate->bootstrapper()->IsActive());

  const int stack_local_count = 0;
  const int context_local_count = 1;
336
  const bool has_simple_parameters = true;
337 338 339 340
  const VariableAllocationInfo receiver_info = CONTEXT;
  const VariableAllocationInfo function_name_info = NONE;
  const bool has_function_name = false;
  const bool has_receiver = true;
jochen's avatar
jochen committed
341
  const bool has_outer_scope_info = false;
342 343 344
  const int parameter_count = 0;
  const int length = kVariablePartIndex + parameter_count +
                     (1 + stack_local_count) + 2 * context_local_count +
jochen's avatar
jochen committed
345 346
                     (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0) +
                     (has_outer_scope_info ? 1 : 0);
347 348 349 350 351

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

  // Encode the flags.
jochen's avatar
jochen committed
352 353 354 355 356 357 358 359
  int flags =
      ScopeTypeField::encode(SCRIPT_SCOPE) | CallsEvalField::encode(false) |
      LanguageModeField::encode(SLOPPY) | DeclarationScopeField::encode(true) |
      ReceiverVariableField::encode(receiver_info) |
      FunctionVariableField::encode(function_name_info) |
      AsmModuleField::encode(false) | AsmFunctionField::encode(false) |
      HasSimpleParametersField::encode(has_simple_parameters) |
      FunctionKindField::encode(FunctionKind::kNormalFunction) |
360 361
      HasOuterScopeInfoField::encode(has_outer_scope_info) |
      IsDebugEvaluateScopeField::encode(false);
362 363 364 365 366 367 368
  scope_info->SetFlags(flags);
  scope_info->SetParameterCount(parameter_count);
  scope_info->SetStackLocalCount(stack_local_count);
  scope_info->SetContextLocalCount(context_local_count);

  int index = kVariablePartIndex;
  const int first_slot_index = 0;
369
  DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex());
370
  scope_info->set(index++, Smi::FromInt(first_slot_index));
371
  DCHECK_EQ(index, scope_info->StackLocalNamesIndex());
372 373

  // Here we add info for context-allocated "this".
374
  DCHECK_EQ(index, scope_info->ContextLocalNamesIndex());
375
  scope_info->set(index++, isolate->heap()->this_string());
376
  DCHECK_EQ(index, scope_info->ContextLocalInfosIndex());
377 378 379
  const uint32_t value = VariableModeField::encode(CONST) |
                         InitFlagField::encode(kCreatedInitialized) |
                         MaybeAssignedFlagField::encode(kNotAssigned);
380 381 382
  scope_info->set(index++, Smi::FromInt(value));

  // And here we record that this scopeinfo binds a receiver.
383
  DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
384 385 386
  const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0;
  scope_info->set(index++, Smi::FromInt(receiver_index));

387 388
  DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
  DCHECK_EQ(index, scope_info->OuterScopeInfoIndex());
389 390 391 392 393 394 395 396
  DCHECK_EQ(index, scope_info->length());
  DCHECK_EQ(scope_info->ParameterCount(), 0);
  DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1);

  return scope_info;
}


397
ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
398
  return isolate->heap()->empty_scope_info();
399 400 401
}


402
ScopeType ScopeInfo::scope_type() {
403
  DCHECK_LT(0, length());
404
  return ScopeTypeField::decode(Flags());
405 406 407
}


408 409
bool ScopeInfo::CallsEval() {
  return length() > 0 && CallsEvalField::decode(Flags());
410 411 412
}


413 414
LanguageMode ScopeInfo::language_mode() {
  return length() > 0 ? LanguageModeField::decode(Flags()) : SLOPPY;
415 416 417
}


418 419 420 421 422
bool ScopeInfo::is_declaration_scope() {
  return DeclarationScopeField::decode(Flags());
}


423 424
int ScopeInfo::LocalCount() {
  return StackLocalCount() + ContextLocalCount();
425 426 427
}


428 429 430 431 432 433 434
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;
435 436 437
}


438 439 440 441 442
int ScopeInfo::ContextLength() {
  if (length() > 0) {
    int context_locals = ContextLocalCount();
    bool function_name_context_slot =
        FunctionVariableField::decode(Flags()) == CONTEXT;
443
    bool has_context = context_locals > 0 || function_name_context_slot ||
444
                       scope_type() == WITH_SCOPE ||
445
                       (scope_type() == BLOCK_SCOPE && CallsSloppyEval() &&
446
                        is_declaration_scope()) ||
447
                       (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) ||
448
                       (scope_type() == FUNCTION_SCOPE && IsAsmModule()) ||
449
                       scope_type() == MODULE_SCOPE;
450

451
    if (has_context) {
452
      return Context::MIN_CONTEXT_SLOTS + context_locals +
453
             (function_name_context_slot ? 1 : 0);
454
    }
455
  }
456
  return 0;
457 458 459
}


460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
bool ScopeInfo::HasReceiver() {
  if (length() > 0) {
    return NONE != ReceiverVariableField::decode(Flags());
  } else {
    return false;
  }
}


bool ScopeInfo::HasAllocatedReceiver() {
  if (length() > 0) {
    VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags());
    return allocation == STACK || allocation == CONTEXT;
  } else {
    return false;
  }
}


479 480 481
bool ScopeInfo::HasNewTarget() { return HasNewTargetField::decode(Flags()); }


482 483 484
bool ScopeInfo::HasFunctionName() {
  if (length() > 0) {
    return NONE != FunctionVariableField::decode(Flags());
485
  } else {
486
    return false;
487
  }
488 489
}

jochen's avatar
jochen committed
490 491 492 493 494 495 496
bool ScopeInfo::HasOuterScopeInfo() {
  if (length() > 0) {
    return HasOuterScopeInfoField::decode(Flags());
  } else {
    return false;
  }
}
497

498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
bool ScopeInfo::IsDebugEvaluateScope() {
  if (length() > 0) {
    return IsDebugEvaluateScopeField::decode(Flags());
  } else {
    return false;
  }
}

void ScopeInfo::SetIsDebugEvaluateScope() {
  if (length() > 0) {
    DCHECK_EQ(scope_type(), WITH_SCOPE);
    SetFlags(Flags() | IsDebugEvaluateScopeField::encode(true));
  } else {
    UNREACHABLE();
  }
}

515 516 517 518 519
bool ScopeInfo::HasHeapAllocatedLocals() {
  if (length() > 0) {
    return ContextLocalCount() > 0;
  } else {
    return false;
520 521 522 523
  }
}


524
bool ScopeInfo::HasContext() {
525
  return ContextLength() > 0;
526 527 528
}


529
String* ScopeInfo::FunctionName() {
530
  DCHECK(HasFunctionName());
531
  return String::cast(get(FunctionNameInfoIndex()));
532 533
}

jochen's avatar
jochen committed
534 535
ScopeInfo* ScopeInfo::OuterScopeInfo() {
  DCHECK(HasOuterScopeInfo());
536
  return ScopeInfo::cast(get(OuterScopeInfoIndex()));
jochen's avatar
jochen committed
537 538
}

539 540
ModuleInfo* ScopeInfo::ModuleDescriptorInfo() {
  DCHECK(scope_type() == MODULE_SCOPE);
541
  return ModuleInfo::cast(get(ModuleInfoIndex()));
542
}
543

544
String* ScopeInfo::ParameterName(int var) {
545 546
  DCHECK_LE(0, var);
  DCHECK_LT(var, ParameterCount());
547
  int info_index = ParameterNamesIndex() + var;
548
  return String::cast(get(info_index));
549 550 551
}


552
String* ScopeInfo::LocalName(int var) {
553 554
  DCHECK_LE(0, var);
  DCHECK_LT(var, LocalCount());
555 556 557
  DCHECK(StackLocalNamesIndex() + StackLocalCount() ==
         ContextLocalNamesIndex());
  int info_index = StackLocalNamesIndex() + var;
558
  return String::cast(get(info_index));
559 560 561
}


562
String* ScopeInfo::StackLocalName(int var) {
563 564
  DCHECK_LE(0, var);
  DCHECK_LT(var, StackLocalCount());
565
  int info_index = StackLocalNamesIndex() + var;
566
  return String::cast(get(info_index));
567 568 569
}


570
int ScopeInfo::StackLocalIndex(int var) {
571 572
  DCHECK_LE(0, var);
  DCHECK_LT(var, StackLocalCount());
573 574 575 576 577
  int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
  return first_slot_index + var;
}


578
String* ScopeInfo::ContextLocalName(int var) {
579 580
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
581
  int info_index = ContextLocalNamesIndex() + var;
582
  return String::cast(get(info_index));
583 584 585
}


586
VariableMode ScopeInfo::ContextLocalMode(int var) {
587 588
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
589
  int info_index = ContextLocalInfosIndex() + var;
590
  int value = Smi::cast(get(info_index))->value();
591
  return VariableModeField::decode(value);
592 593 594 595
}


InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
596 597
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
598
  int info_index = ContextLocalInfosIndex() + var;
599
  int value = Smi::cast(get(info_index))->value();
600
  return InitFlagField::decode(value);
601 602 603
}


604
MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) {
605 606
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
607
  int info_index = ContextLocalInfosIndex() + var;
608
  int value = Smi::cast(get(info_index))->value();
609
  return MaybeAssignedFlagField::decode(value);
610 611
}

612
bool ScopeInfo::VariableIsSynthetic(String* name) {
613 614 615 616
  // 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!
617 618
  return name->length() == 0 || name->Get(0) == '.' ||
         name->Equals(name->GetHeap()->this_string());
619 620 621
}


622
int ScopeInfo::StackSlotIndex(String* name) {
623
  DCHECK(name->IsInternalizedString());
624
  if (length() > 0) {
625
    int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
626
    int start = StackLocalNamesIndex();
627
    int end = start + StackLocalCount();
628 629
    for (int i = start; i < end; ++i) {
      if (name == get(i)) {
630
        return i - start + first_slot_index;
631
      }
632 633 634 635 636
    }
  }
  return -1;
}

637 638 639 640 641 642 643 644 645 646
int ScopeInfo::ModuleIndex(Handle<String> name, VariableMode* mode,
                           InitializationFlag* init_flag,
                           MaybeAssignedFlag* maybe_assigned_flag) {
  DCHECK_EQ(scope_type(), MODULE_SCOPE);
  DCHECK(name->IsInternalizedString());
  DCHECK_NOT_NULL(mode);
  DCHECK_NOT_NULL(init_flag);
  DCHECK_NOT_NULL(maybe_assigned_flag);

  int module_vars_count = Smi::cast(get(ModuleVariableCountIndex()))->value();
647
  int entry = ModuleVariablesIndex();
648 649
  for (int i = 0; i < module_vars_count; ++i) {
    if (*name == get(entry + kModuleVariableNameOffset)) {
650 651
      int index;
      ModuleVariable(i, nullptr, &index, mode, init_flag, maybe_assigned_flag);
652 653 654 655 656
      return index;
    }
    entry += kModuleVariableEntryLength;
  }

657
  return 0;
658
}
659

660
int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
661 662 663
                                Handle<String> name, VariableMode* mode,
                                InitializationFlag* init_flag,
                                MaybeAssignedFlag* maybe_assigned_flag) {
664
  DCHECK(name->IsInternalizedString());
665 666 667 668
  DCHECK_NOT_NULL(mode);
  DCHECK_NOT_NULL(init_flag);
  DCHECK_NOT_NULL(maybe_assigned_flag);

669
  if (scope_info->length() > 0) {
670 671 672 673 674
    ContextSlotCache* context_slot_cache =
        scope_info->GetIsolate()->context_slot_cache();
    int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag,
                                            maybe_assigned_flag);
    if (result != ContextSlotCache::kNotFound) {
675
      DCHECK_LT(result, scope_info->ContextLength());
676 677 678
      return result;
    }

679
    int start = scope_info->ContextLocalNamesIndex();
680
    int end = start + scope_info->ContextLocalCount();
681 682 683 684 685 686
    for (int i = start; i < end; ++i) {
      if (*name == scope_info->get(i)) {
        int var = i - start;
        *mode = scope_info->ContextLocalMode(var);
        *init_flag = scope_info->ContextLocalInitFlag(var);
        *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
687 688 689 690
        result = Context::MIN_CONTEXT_SLOTS + var;

        context_slot_cache->Update(scope_info, name, *mode, *init_flag,
                                   *maybe_assigned_flag, result);
691
        DCHECK_LT(result, scope_info->ContextLength());
692 693 694
        return result;
      }
    }
695 696 697
    // Cache as not found. Mode, init flag and maybe assigned flag don't matter.
    context_slot_cache->Update(scope_info, name, TEMPORARY,
                               kNeedsInitialization, kNotAssigned, -1);
698
  }
699

700 701 702
  return -1;
}

703
String* ScopeInfo::ContextSlotName(int slot_index) {
704
  int const var = slot_index - Context::MIN_CONTEXT_SLOTS;
705
  DCHECK_LE(0, var);
706
  DCHECK_LT(var, ContextLocalCount());
707
  return ContextLocalName(var);
708 709 710
}


711
int ScopeInfo::ParameterIndex(String* name) {
712
  DCHECK(name->IsInternalizedString());
713
  if (length() > 0) {
714 715 716 717 718
    // 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.
719
    int start = ParameterNamesIndex();
720
    int end = start + ParameterCount();
721 722 723 724
    for (int i = end - 1; i >= start; --i) {
      if (name == get(i)) {
        return i - start;
      }
725 726 727 728 729 730
    }
  }
  return -1;
}


731 732
int ScopeInfo::ReceiverContextSlotIndex() {
  if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT)
733
    return Smi::cast(get(ReceiverInfoIndex()))->value();
734 735 736
  return -1;
}

737
int ScopeInfo::FunctionContextSlotIndex(String* name) {
738
  DCHECK(name->IsInternalizedString());
739
  if (length() > 0) {
740 741
    if (FunctionVariableField::decode(Flags()) == CONTEXT &&
        FunctionName() == name) {
742
      return Smi::cast(get(FunctionNameInfoIndex() + 1))->value();
743 744 745 746 747 748
    }
  }
  return -1;
}


749 750 751 752
FunctionKind ScopeInfo::function_kind() {
  return FunctionKindField::decode(Flags());
}

753
int ScopeInfo::ParameterNamesIndex() {
754
  DCHECK_LT(0, length());
755 756 757 758
  return kVariablePartIndex;
}


759
int ScopeInfo::StackLocalFirstSlotIndex() {
760
  return ParameterNamesIndex() + ParameterCount();
761 762
}

763
int ScopeInfo::StackLocalNamesIndex() { return StackLocalFirstSlotIndex() + 1; }
764

765 766
int ScopeInfo::ContextLocalNamesIndex() {
  return StackLocalNamesIndex() + StackLocalCount();
767 768
}

769 770
int ScopeInfo::ContextLocalInfosIndex() {
  return ContextLocalNamesIndex() + ContextLocalCount();
771 772
}

773 774
int ScopeInfo::ReceiverInfoIndex() {
  return ContextLocalInfosIndex() + ContextLocalCount();
775 776
}

777 778
int ScopeInfo::FunctionNameInfoIndex() {
  return ReceiverInfoIndex() + (HasAllocatedReceiver() ? 1 : 0);
779 780
}

781 782
int ScopeInfo::OuterScopeInfoIndex() {
  return FunctionNameInfoIndex() + (HasFunctionName() ? 2 : 0);
783 784
}

785 786
int ScopeInfo::ModuleInfoIndex() {
  return OuterScopeInfoIndex() + (HasOuterScopeInfo() ? 1 : 0);
jochen's avatar
jochen committed
787 788
}

789
int ScopeInfo::ModuleVariableCountIndex() { return ModuleInfoIndex() + 1; }
790

791
int ScopeInfo::ModuleVariablesIndex() { return ModuleVariableCountIndex() + 1; }
792

793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808
void ScopeInfo::ModuleVariable(int i, String** name, int* index,
                               VariableMode* mode,
                               InitializationFlag* init_flag,
                               MaybeAssignedFlag* maybe_assigned_flag) {
  DCHECK_LE(0, i);
  DCHECK_LT(i, Smi::cast(get(ModuleVariableCountIndex()))->value());

  int entry = ModuleVariablesIndex() + i * kModuleVariableEntryLength;
  int properties =
      Smi::cast(get(entry + kModuleVariablePropertiesOffset))->value();

  if (name != nullptr) {
    *name = String::cast(get(entry + kModuleVariableNameOffset));
  }
  if (index != nullptr) {
    *index = Smi::cast(get(entry + kModuleVariableIndexOffset))->value();
809
    DCHECK_NE(*index, 0);
810 811 812 813 814 815 816 817 818 819 820 821
  }
  if (mode != nullptr) {
    *mode = VariableModeField::decode(properties);
  }
  if (init_flag != nullptr) {
    *init_flag = InitFlagField::decode(properties);
  }
  if (maybe_assigned_flag != nullptr) {
    *maybe_assigned_flag = MaybeAssignedFlagField::decode(properties);
  }
}

822 823
#ifdef DEBUG

824 825
static void PrintList(const char* list_name,
                      int nof_internal_slots,
826 827 828 829
                      int start,
                      int end,
                      ScopeInfo* scope_info) {
  if (start < end) {
830 831 832 833
    PrintF("\n  // %s\n", list_name);
    if (nof_internal_slots > 0) {
      PrintF("  %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
    }
834 835 836
    for (int i = nof_internal_slots; start < end; ++i, ++start) {
      PrintF("  %2d ", i);
      String::cast(scope_info->get(start))->ShortPrint();
837 838 839 840 841 842
      PrintF("\n");
    }
  }
}


843
void ScopeInfo::Print() {
844
  PrintF("ScopeInfo ");
845 846 847
  if (HasFunctionName()) {
    FunctionName()->ShortPrint();
  } else {
848
    PrintF("/* no function name */");
849
  }
850 851
  PrintF("{");

852
  if (length() > 0) {
853 854 855 856
    PrintList("parameters", 0, ParameterNamesIndex(),
              ParameterNamesIndex() + ParameterCount(), this);
    PrintList("stack slots", 0, StackLocalNamesIndex(),
              StackLocalNamesIndex() + StackLocalCount(), this);
857
    PrintList("context slots", Context::MIN_CONTEXT_SLOTS,
858 859
              ContextLocalNamesIndex(),
              ContextLocalNamesIndex() + ContextLocalCount(), this);
860
    // TODO(neis): Print module stuff if present.
861
  }
862 863 864 865 866

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

867 868 869 870
Handle<ModuleInfoEntry> ModuleInfoEntry::New(Isolate* isolate,
                                             Handle<Object> export_name,
                                             Handle<Object> local_name,
                                             Handle<Object> import_name,
871
                                             int module_request, int cell_index,
872
                                             int beg_pos, int end_pos) {
873 874 875 876 877 878 879 880 881
  Handle<ModuleInfoEntry> result = Handle<ModuleInfoEntry>::cast(
      isolate->factory()->NewStruct(MODULE_INFO_ENTRY_TYPE));
  result->set_export_name(*export_name);
  result->set_local_name(*local_name);
  result->set_import_name(*import_name);
  result->set_module_request(module_request);
  result->set_cell_index(cell_index);
  result->set_beg_pos(beg_pos);
  result->set_end_pos(end_pos);
882 883 884
  return result;
}

885 886
Handle<ModuleInfo> ModuleInfo::New(Isolate* isolate, Zone* zone,
                                   ModuleDescriptor* descr) {
887 888 889 890 891 892 893
  // Serialize module requests.
  Handle<FixedArray> module_requests = isolate->factory()->NewFixedArray(
      static_cast<int>(descr->module_requests().size()));
  for (const auto& elem : descr->module_requests()) {
    module_requests->set(elem.second, *elem.first->string());
  }

894 895 896 897 898 899
  // Serialize special exports.
  Handle<FixedArray> special_exports =
      isolate->factory()->NewFixedArray(descr->special_exports().length());
  {
    int i = 0;
    for (auto entry : descr->special_exports()) {
900 901
      Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate);
      special_exports->set(i++, *serialized_entry);
902 903 904
    }
  }

905 906 907
  // Serialize namespace imports.
  Handle<FixedArray> namespace_imports =
      isolate->factory()->NewFixedArray(descr->namespace_imports().length());
908 909
  {
    int i = 0;
910
    for (auto entry : descr->namespace_imports()) {
911 912
      Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate);
      namespace_imports->set(i++, *serialized_entry);
913 914 915
    }
  }

916
  // Serialize regular exports.
917 918
  Handle<FixedArray> regular_exports =
      descr->SerializeRegularExports(isolate, zone);
919

920 921 922 923 924 925
  // Serialize regular imports.
  Handle<FixedArray> regular_imports = isolate->factory()->NewFixedArray(
      static_cast<int>(descr->regular_imports().size()));
  {
    int i = 0;
    for (const auto& elem : descr->regular_imports()) {
926 927 928
      Handle<ModuleInfoEntry> serialized_entry =
          elem.second->Serialize(isolate);
      regular_imports->set(i++, *serialized_entry);
929 930 931
    }
  }

932
  Handle<ModuleInfo> result = isolate->factory()->NewModuleInfo();
933
  result->set(kModuleRequestsIndex, *module_requests);
934 935
  result->set(kSpecialExportsIndex, *special_exports);
  result->set(kRegularExportsIndex, *regular_exports);
936
  result->set(kNamespaceImportsIndex, *namespace_imports);
937
  result->set(kRegularImportsIndex, *regular_imports);
938 939
  return result;
}
940

941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961
int ModuleInfo::RegularExportCount() const {
  DCHECK_EQ(regular_exports()->length() % kRegularExportLength, 0);
  return regular_exports()->length() / kRegularExportLength;
}

String* ModuleInfo::RegularExportLocalName(int i) const {
  return String::cast(regular_exports()->get(i * kRegularExportLength +
                                             kRegularExportLocalNameOffset));
}

int ModuleInfo::RegularExportCellIndex(int i) const {
  return Smi::cast(regular_exports()->get(i * kRegularExportLength +
                                          kRegularExportCellIndexOffset))
      ->value();
}

FixedArray* ModuleInfo::RegularExportExportNames(int i) const {
  return FixedArray::cast(regular_exports()->get(
      i * kRegularExportLength + kRegularExportExportNamesOffset));
}

962 963 964 965 966 967 968 969 970 971 972 973 974 975 976
Handle<ModuleInfoEntry> ModuleInfo::LookupRegularImport(
    Handle<ModuleInfo> info, Handle<String> local_name) {
  Isolate* isolate = info->GetIsolate();
  Handle<FixedArray> regular_imports(info->regular_imports(), isolate);
  for (int i = 0, n = regular_imports->length(); i < n; ++i) {
    Handle<ModuleInfoEntry> entry(
        ModuleInfoEntry::cast(regular_imports->get(i)), isolate);
    if (String::cast(entry->local_name())->Equals(*local_name)) {
      return entry;
    }
  }
  UNREACHABLE();
  return Handle<ModuleInfoEntry>();
}

977 978
}  // namespace internal
}  // namespace v8