scope-info.cc 43.4 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 "src/objects/scope-info.h"

7 8
#include <stdlib.h>

9
#include "src/ast/scopes.h"
10
#include "src/ast/variables.h"
11
#include "src/init/bootstrapper.h"
12
#include "src/objects/module-inl.h"
13
#include "src/objects/objects-inl.h"
14
#include "src/objects/string-set-inl.h"
15
#include "src/roots/roots.h"
16

17 18
namespace v8 {
namespace internal {
19

20 21 22 23 24 25 26
// An entry in ModuleVariableEntries consists of several slots:
enum ModuleVariableEntryOffset {
  kModuleVariableNameOffset,
  kModuleVariableIndexOffset,
  kModuleVariablePropertiesOffset,
  kModuleVariableEntryLength  // Sentinel value.
};
27

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

63
// static
64 65 66 67
template <typename LocalIsolate>
Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone,
                                    Scope* scope,
                                    MaybeHandle<ScopeInfo> outer_scope) {
68
  // Collect variables.
69
  int context_local_count = 0;
70
  int module_vars_count = 0;
71 72 73 74
  // 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.
75
  for (Variable* var : *scope->locals()) {
76 77
    switch (var->location()) {
      case VariableLocation::CONTEXT:
Simon Zünd's avatar
Simon Zünd committed
78
      case VariableLocation::REPL_GLOBAL:
79 80 81 82 83 84 85
        context_local_count++;
        break;
      case VariableLocation::MODULE:
        module_vars_count++;
        break;
      default:
        break;
86 87
    }
  }
88 89
  // Determine use and location of the "this" binding if it is present.
  VariableAllocationInfo receiver_info;
90 91 92
  if (scope->is_declaration_scope() &&
      scope->AsDeclarationScope()->has_this_declaration()) {
    Variable* var = scope->AsDeclarationScope()->receiver();
93
    if (!var->is_used()) {
94
      receiver_info = VariableAllocationInfo::UNUSED;
95
    } else if (var->IsContextSlot()) {
96
      receiver_info = VariableAllocationInfo::CONTEXT;
97
      context_local_count++;
98 99
    } else {
      DCHECK(var->IsParameter());
100
      receiver_info = VariableAllocationInfo::STACK;
101 102
    }
  } else {
103
    receiver_info = VariableAllocationInfo::NONE;
104 105
  }

106 107 108 109 110
  DCHECK(module_vars_count == 0 || scope->is_module_scope());

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

111
  const bool has_new_target =
112 113
      scope->is_declaration_scope() &&
      scope->AsDeclarationScope()->new_target_var() != nullptr;
114 115
  // TODO(cbruni): Don't always waste a field for the inferred name.
  const bool has_inferred_function_name = scope->is_function_scope();
116

117
  // Determine use and location of the function variable if it is present.
118
  VariableAllocationInfo function_name_info;
119 120 121 122
  if (scope->is_function_scope()) {
    if (scope->AsDeclarationScope()->function_var() != nullptr) {
      Variable* var = scope->AsDeclarationScope()->function_var();
      if (!var->is_used()) {
123
        function_name_info = VariableAllocationInfo::UNUSED;
124
      } else if (var->IsContextSlot()) {
125
        function_name_info = VariableAllocationInfo::CONTEXT;
126 127
      } else {
        DCHECK(var->IsStackLocal());
128
        function_name_info = VariableAllocationInfo::STACK;
129
      }
130
    } else {
131
      // Always reserve space for the debug name in the scope info.
132
      function_name_info = VariableAllocationInfo::UNUSED;
133
    }
134 135 136
  } else if (scope->is_module_scope() || scope->is_script_scope() ||
             scope->is_eval_scope()) {
    // Always reserve space for the debug name in the scope info.
137
    function_name_info = VariableAllocationInfo::UNUSED;
138
  } else {
139
    function_name_info = VariableAllocationInfo::NONE;
140 141
  }

142 143 144
  const bool has_brand = scope->is_class_scope()
                             ? scope->AsClassScope()->brand() != nullptr
                             : false;
145 146 147 148
  const bool should_save_class_variable_index =
      scope->is_class_scope()
          ? scope->AsClassScope()->should_save_class_variable_index()
          : false;
149 150
  const bool has_function_name =
      function_name_info != VariableAllocationInfo::NONE;
151
  const bool has_position_info = NeedsPositionInfo(scope->scope_type());
152 153
  const bool has_receiver = receiver_info == VariableAllocationInfo::STACK ||
                            receiver_info == VariableAllocationInfo::CONTEXT;
154 155 156 157
  const int parameter_count =
      scope->is_declaration_scope()
          ? scope->AsDeclarationScope()->num_parameters()
          : 0;
jochen's avatar
jochen committed
158
  const bool has_outer_scope_info = !outer_scope.is_null();
159

160
  const int length = kVariablePartIndex + 2 * context_local_count +
161
                     (should_save_class_variable_index ? 1 : 0) +
162
                     (has_receiver ? 1 : 0) +
163
                     (has_function_name ? kFunctionNameEntries : 0) +
164
                     (has_inferred_function_name ? 1 : 0) +
165
                     (has_position_info ? kPositionInfoEntries : 0) +
jochen's avatar
jochen committed
166
                     (has_outer_scope_info ? 1 : 0) +
167 168 169
                     (scope->is_module_scope()
                          ? 2 + kModuleVariableEntryLength * module_vars_count
                          : 0);
170

171
  Handle<ScopeInfo> scope_info_handle =
172 173 174
      isolate->factory()->NewScopeInfo(length);
  int index = kVariablePartIndex;
  {
175
    DisallowGarbageCollection no_gc;
176
    ScopeInfo scope_info = *scope_info_handle;
177
    WriteBarrierMode mode = scope_info.GetWriteBarrierMode(no_gc);
178

179 180
    bool has_simple_parameters = false;
    bool is_asm_module = false;
181
    bool sloppy_eval_can_extend_vars = false;
182 183 184 185 186 187 188 189
    if (scope->is_function_scope()) {
      DeclarationScope* function_scope = scope->AsDeclarationScope();
      has_simple_parameters = function_scope->has_simple_parameters();
      is_asm_module = function_scope->is_asm_module();
    }
    FunctionKind function_kind = kNormalFunction;
    if (scope->is_declaration_scope()) {
      function_kind = scope->AsDeclarationScope()->function_kind();
190 191
      sloppy_eval_can_extend_vars =
          scope->AsDeclarationScope()->sloppy_eval_can_extend_vars();
192
    }
193

194 195
    // Encode the flags.
    int flags =
196 197 198 199 200 201 202
        ScopeTypeBits::encode(scope->scope_type()) |
        SloppyEvalCanExtendVarsBit::encode(sloppy_eval_can_extend_vars) |
        LanguageModeBit::encode(scope->language_mode()) |
        DeclarationScopeBit::encode(scope->is_declaration_scope()) |
        ReceiverVariableBits::encode(receiver_info) |
        HasClassBrandBit::encode(has_brand) |
        HasSavedClassVariableIndexBit::encode(
203
            should_save_class_variable_index) |
204 205 206 207 208 209 210 211 212
        HasNewTargetBit::encode(has_new_target) |
        FunctionVariableBits::encode(function_name_info) |
        HasInferredFunctionNameBit::encode(has_inferred_function_name) |
        IsAsmModuleBit::encode(is_asm_module) |
        HasSimpleParametersBit::encode(has_simple_parameters) |
        FunctionKindBits::encode(function_kind) |
        HasOuterScopeInfoBit::encode(has_outer_scope_info) |
        IsDebugEvaluateScopeBit::encode(scope->is_debug_evaluate_scope()) |
        ForceContextAllocationBit::encode(
213
            scope->ForceContextForLanguageMode()) |
214
        PrivateNameLookupSkipsOuterClassBit::encode(
215
            scope->private_name_lookup_skips_outer_class()) |
216 217
        HasContextExtensionSlotBit::encode(scope->HasContextExtensionSlot()) |
        IsReplModeScopeBit::encode(scope->is_repl_mode_scope()) |
Dan Elphick's avatar
Dan Elphick committed
218
        HasLocalsBlockListBit::encode(false);
219
    scope_info.SetFlags(flags);
220

221 222
    scope_info.SetParameterCount(parameter_count);
    scope_info.SetContextLocalCount(context_local_count);
223

224 225 226 227
    // Add context locals' names and info, module variables' names and info.
    // Context locals are added using their index.
    int context_local_base = index;
    int context_local_info_base = context_local_base + context_local_count;
228
    int module_var_entry = scope_info.ModuleVariablesIndex();
229

230 231
    for (Variable* var : *scope->locals()) {
      switch (var->location()) {
Simon Zünd's avatar
Simon Zünd committed
232 233
        case VariableLocation::CONTEXT:
        case VariableLocation::REPL_GLOBAL: {
234 235
          // Due to duplicate parameters, context locals aren't guaranteed to
          // come in order.
236
          int local_index = var->index() - scope->ContextHeaderLength();
237 238 239 240 241 242
          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()) |
243 244
              ParameterNumberField::encode(ParameterNumberField::kMax) |
              IsStaticFlagField::encode(var->is_static_flag());
245
          scope_info.set(context_local_base + local_index, *var->name(), mode);
246 247
          scope_info.set(context_local_info_base + local_index,
                         Smi::FromInt(info));
248 249 250
          break;
        }
        case VariableLocation::MODULE: {
251
          scope_info.set(module_var_entry + kModuleVariableNameOffset,
252
                         *var->name(), mode);
253 254
          scope_info.set(module_var_entry + kModuleVariableIndexOffset,
                         Smi::FromInt(var->index()));
255 256 257 258
          uint32_t properties =
              VariableModeField::encode(var->mode()) |
              InitFlagField::encode(var->initialization_flag()) |
              MaybeAssignedFlagField::encode(var->maybe_assigned()) |
259 260
              ParameterNumberField::encode(ParameterNumberField::kMax) |
              IsStaticFlagField::encode(var->is_static_flag());
261 262
          scope_info.set(module_var_entry + kModuleVariablePropertiesOffset,
                         Smi::FromInt(properties));
263 264 265 266 267
          module_var_entry += kModuleVariableEntryLength;
          break;
        }
        default:
          break;
268
      }
269
    }
270

271 272 273 274 275 276 277 278 279 280 281
    if (scope->is_declaration_scope()) {
      // Mark contexts slots with the parameter number they represent. We walk
      // the list of parameters. That can include duplicate entries if a
      // parameter name is repeated. By walking upwards, we'll automatically
      // mark the context slot with the highest parameter number that uses this
      // variable. That will be the parameter number that is represented by the
      // context slot. All lower parameters will only be available on the stack
      // through the arguments object.
      for (int i = 0; i < parameter_count; i++) {
        Variable* parameter = scope->AsDeclarationScope()->parameter(i);
        if (parameter->location() != VariableLocation::CONTEXT) continue;
282
        int index = parameter->index() - scope->ContextHeaderLength();
283
        int info_index = context_local_info_base + index;
284
        int info = Smi::ToInt(scope_info.get(info_index));
285
        info = ParameterNumberField::update(info, i);
286
        scope_info.set(info_index, Smi::FromInt(info));
287
      }
288 289 290 291 292

      // TODO(verwaest): Remove this unnecessary entry.
      if (scope->AsDeclarationScope()->has_this_declaration()) {
        Variable* var = scope->AsDeclarationScope()->receiver();
        if (var->location() == VariableLocation::CONTEXT) {
293
          int local_index = var->index() - scope->ContextHeaderLength();
294 295 296 297
          uint32_t info =
              VariableModeField::encode(var->mode()) |
              InitFlagField::encode(var->initialization_flag()) |
              MaybeAssignedFlagField::encode(var->maybe_assigned()) |
298 299
              ParameterNumberField::encode(ParameterNumberField::kMax) |
              IsStaticFlagField::encode(var->is_static_flag());
300
          scope_info.set(context_local_base + local_index, *var->name(), mode);
301 302
          scope_info.set(context_local_info_base + local_index,
                         Smi::FromInt(info));
303 304
        }
      }
305 306
    }

307
    index += 2 * context_local_count;
308

309 310 311 312 313 314 315 316 317 318
    DCHECK_EQ(index, scope_info.SavedClassVariableInfoIndex());
    // If the scope is a class scope and has used static private methods, save
    // the context slot index of the class variable.
    // Store the class variable index.
    if (should_save_class_variable_index) {
      Variable* class_variable = scope->AsClassScope()->class_variable();
      DCHECK_EQ(class_variable->location(), VariableLocation::CONTEXT);
      scope_info.set(index++, Smi::FromInt(class_variable->index()));
    }

319
    // If the receiver is allocated, add its index.
320
    DCHECK_EQ(index, scope_info.ReceiverInfoIndex());
321 322
    if (has_receiver) {
      int var_index = scope->AsDeclarationScope()->receiver()->index();
323
      scope_info.set(index++, Smi::FromInt(var_index));
324 325 326
      // ?? DCHECK(receiver_info != CONTEXT || var_index ==
      // scope_info->ContextLength() - 1);
    }
327

328
    // If present, add the function variable name and its index.
329
    DCHECK_EQ(index, scope_info.FunctionNameInfoIndex());
330 331 332
    if (has_function_name) {
      Variable* var = scope->AsDeclarationScope()->function_var();
      int var_index = -1;
333
      Object name = Smi::zero();
334 335
      if (var != nullptr) {
        var_index = var->index();
336
        name = *var->name();
337
      }
338 339
      scope_info.set(index++, name, mode);
      scope_info.set(index++, Smi::FromInt(var_index));
340
      DCHECK(function_name_info != VariableAllocationInfo::CONTEXT ||
341
             var_index == scope_info.ContextLength() - 1);
342
    }
343

344
    DCHECK_EQ(index, scope_info.InferredFunctionNameIndex());
345 346 347 348
    if (has_inferred_function_name) {
      // The inferred function name is taken from the SFI.
      index++;
    }
349

350
    DCHECK_EQ(index, scope_info.PositionInfoIndex());
351
    if (has_position_info) {
352 353
      scope_info.set(index++, Smi::FromInt(scope->start_position()));
      scope_info.set(index++, Smi::FromInt(scope->end_position()));
354
    }
355

356
    // If present, add the outer scope info.
357
    DCHECK(index == scope_info.OuterScopeInfoIndex());
358
    if (has_outer_scope_info) {
359
      scope_info.set(index++, *outer_scope.ToHandleChecked(), mode);
360
    }
jochen's avatar
jochen committed
361 362
  }

363 364
  // Module-specific information (only for module scopes).
  if (scope->is_module_scope()) {
365 366
    Handle<SourceTextModuleInfo> module_info = SourceTextModuleInfo::New(
        isolate, zone, scope->AsModuleScope()->module());
367 368 369 370 371
    DCHECK_EQ(index, scope_info_handle->ModuleInfoIndex());
    scope_info_handle->set(index++, *module_info);
    DCHECK_EQ(index, scope_info_handle->ModuleVariableCountIndex());
    scope_info_handle->set(index++, Smi::FromInt(module_vars_count));
    DCHECK_EQ(index, scope_info_handle->ModuleVariablesIndex());
372 373 374 375
    // The variable entries themselves have already been written above.
    index += kModuleVariableEntryLength * module_vars_count;
  }

376
  DCHECK_EQ(index, scope_info_handle->length());
377
  DCHECK_EQ(parameter_count, scope_info_handle->ParameterCount());
378 379
  DCHECK_EQ(scope->num_heap_slots(), scope_info_handle->ContextLength());
  return scope_info_handle;
380 381
}

382
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
383 384 385
    Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
                                        Scope* scope,
                                        MaybeHandle<ScopeInfo> outer_scope);
386
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
387 388 389
    Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone,
                                        Scope* scope,
                                        MaybeHandle<ScopeInfo> outer_scope);
390

391
// static
jochen's avatar
jochen committed
392 393 394
Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
    Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope) {
  const bool has_outer_scope_info = !outer_scope.is_null();
395
  const int length = kVariablePartIndex + (has_outer_scope_info ? 1 : 0);
396 397 398 399 400 401

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

  // Encode the flags.
  int flags =
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
      ScopeTypeBits::encode(WITH_SCOPE) |
      SloppyEvalCanExtendVarsBit::encode(false) |
      LanguageModeBit::encode(LanguageMode::kSloppy) |
      DeclarationScopeBit::encode(false) |
      ReceiverVariableBits::encode(VariableAllocationInfo::NONE) |
      HasClassBrandBit::encode(false) |
      HasSavedClassVariableIndexBit::encode(false) |
      HasNewTargetBit::encode(false) |
      FunctionVariableBits::encode(VariableAllocationInfo::NONE) |
      IsAsmModuleBit::encode(false) | HasSimpleParametersBit::encode(true) |
      FunctionKindBits::encode(kNormalFunction) |
      HasOuterScopeInfoBit::encode(has_outer_scope_info) |
      IsDebugEvaluateScopeBit::encode(false) |
      ForceContextAllocationBit::encode(false) |
      PrivateNameLookupSkipsOuterClassBit::encode(false) |
      HasContextExtensionSlotBit::encode(true) |
Dan Elphick's avatar
Dan Elphick committed
418
      IsReplModeScopeBit::encode(false) | HasLocalsBlockListBit::encode(false);
419 420 421 422 423 424
  scope_info->SetFlags(flags);

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

  int index = kVariablePartIndex;
425 426
  DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
  DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
427
  DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
428
  DCHECK_EQ(index, scope_info->PositionInfoIndex());
429
  DCHECK(index == scope_info->OuterScopeInfoIndex());
jochen's avatar
jochen committed
430 431 432
  if (has_outer_scope_info) {
    scope_info->set(index++, *outer_scope.ToHandleChecked());
  }
433 434
  DCHECK_EQ(index, scope_info->length());
  DCHECK_EQ(0, scope_info->ParameterCount());
435
  DCHECK_EQ(scope_info->ContextHeaderLength(), scope_info->ContextLength());
436 437
  return scope_info;
}
438

439
// static
440
Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
441
  return CreateForBootstrapping(isolate, BootstrappingType::kScript);
442 443 444 445
}

// static
Handle<ScopeInfo> ScopeInfo::CreateForEmptyFunction(Isolate* isolate) {
446
  return CreateForBootstrapping(isolate, BootstrappingType::kFunction);
447 448 449
}

// static
450 451 452
Handle<ScopeInfo> ScopeInfo::CreateForNativeContext(Isolate* isolate) {
  return CreateForBootstrapping(isolate, BootstrappingType::kNative);
}
453

454 455 456
// static
Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate,
                                                    BootstrappingType type) {
457
  const int parameter_count = 0;
458 459 460 461 462 463
  const bool is_empty_function = type == BootstrappingType::kFunction;
  const bool is_native_context = type == BootstrappingType::kNative;
  const bool is_script = type == BootstrappingType::kScript;
  const int context_local_count =
      is_empty_function || is_native_context ? 0 : 1;
  const bool has_receiver = is_script;
464
  const bool has_inferred_function_name = is_empty_function;
465
  const bool has_position_info = true;
466 467
  const int length = kVariablePartIndex + 2 * context_local_count +
                     (has_receiver ? 1 : 0) +
468 469
                     (is_empty_function ? kFunctionNameEntries : 0) +
                     (has_inferred_function_name ? 1 : 0) +
470
                     (has_position_info ? kPositionInfoEntries : 0);
471 472

  Factory* factory = isolate->factory();
473 474
  Handle<ScopeInfo> scope_info =
      factory->NewScopeInfo(length, AllocationType::kReadOnly);
475 476

  // Encode the flags.
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
  int flags =
      ScopeTypeBits::encode(is_empty_function ? FUNCTION_SCOPE : SCRIPT_SCOPE) |
      SloppyEvalCanExtendVarsBit::encode(false) |
      LanguageModeBit::encode(LanguageMode::kSloppy) |
      DeclarationScopeBit::encode(true) |
      ReceiverVariableBits::encode(is_script ? VariableAllocationInfo::CONTEXT
                                             : VariableAllocationInfo::UNUSED) |
      HasClassBrandBit::encode(false) |
      HasSavedClassVariableIndexBit::encode(false) |
      HasNewTargetBit::encode(false) |
      FunctionVariableBits::encode(is_empty_function
                                       ? VariableAllocationInfo::UNUSED
                                       : VariableAllocationInfo::NONE) |
      HasInferredFunctionNameBit::encode(has_inferred_function_name) |
      IsAsmModuleBit::encode(false) | HasSimpleParametersBit::encode(true) |
      FunctionKindBits::encode(FunctionKind::kNormalFunction) |
      HasOuterScopeInfoBit::encode(false) |
      IsDebugEvaluateScopeBit::encode(false) |
      ForceContextAllocationBit::encode(false) |
      PrivateNameLookupSkipsOuterClassBit::encode(false) |
      HasContextExtensionSlotBit::encode(is_native_context) |
Dan Elphick's avatar
Dan Elphick committed
498
      IsReplModeScopeBit::encode(false) | HasLocalsBlockListBit::encode(false);
499 500 501 502 503 504 505
  scope_info->SetFlags(flags);
  scope_info->SetParameterCount(parameter_count);
  scope_info->SetContextLocalCount(context_local_count);

  int index = kVariablePartIndex;

  // Here we add info for context-allocated "this".
506
  DCHECK_EQ(index, scope_info->ContextLocalNamesIndex());
507
  if (context_local_count) {
508
    scope_info->set(index++, ReadOnlyRoots(isolate).this_string());
509
  }
510
  DCHECK_EQ(index, scope_info->ContextLocalInfosIndex());
511
  if (context_local_count > 0) {
512 513 514 515
    const uint32_t value =
        VariableModeField::encode(VariableMode::kConst) |
        InitFlagField::encode(kCreatedInitialized) |
        MaybeAssignedFlagField::encode(kNotAssigned) |
516 517
        ParameterNumberField::encode(ParameterNumberField::kMax) |
        IsStaticFlagField::encode(IsStaticFlag::kNotStatic);
518 519
    scope_info->set(index++, Smi::FromInt(value));
  }
520 521

  // And here we record that this scopeinfo binds a receiver.
522
  DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
523 524
  if (has_receiver) {
    const int receiver_index = scope_info->ContextHeaderLength();
525 526
    scope_info->set(index++, Smi::FromInt(receiver_index));
  }
527

528
  DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
529 530
  if (is_empty_function) {
    scope_info->set(index++, *isolate->factory()->empty_string());
531
    scope_info->set(index++, Smi::zero());
532
  }
533
  DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
534 535 536
  if (has_inferred_function_name) {
    scope_info->set(index++, *isolate->factory()->empty_string());
  }
537 538
  DCHECK_EQ(index, scope_info->PositionInfoIndex());
  // Store dummy position to be in sync with the {scope_type}.
539 540
  scope_info->set(index++, Smi::zero());
  scope_info->set(index++, Smi::zero());
541
  DCHECK_EQ(index, scope_info->OuterScopeInfoIndex());
542
  DCHECK_EQ(index, scope_info->length());
543
  DCHECK_EQ(scope_info->ParameterCount(), parameter_count);
544
  if (is_empty_function || is_native_context) {
545 546
    DCHECK_EQ(scope_info->ContextLength(), 0);
  } else {
547 548
    DCHECK_EQ(scope_info->ContextLength(),
              scope_info->ContextHeaderLength() + 1);
549
  }
550 551 552 553

  return scope_info;
}

554
// static
Dan Elphick's avatar
Dan Elphick committed
555 556
Handle<ScopeInfo> ScopeInfo::RecreateWithBlockList(
    Isolate* isolate, Handle<ScopeInfo> original, Handle<StringSet> blocklist) {
557
  DCHECK(!original.is_null());
Dan Elphick's avatar
Dan Elphick committed
558
  if (original->HasLocalsBlockList()) return original;
559 560 561 562 563

  Handle<ScopeInfo> scope_info =
      isolate->factory()->NewScopeInfo(original->length() + 1);

  // Copy the static part first and update the flags to include the
Dan Elphick's avatar
Dan Elphick committed
564
  // blocklist field, so {LocalsBlockListIndex} returns the correct value.
565 566 567
  scope_info->CopyElements(isolate, 0, *original, 0, kVariablePartIndex,
                           WriteBarrierMode::UPDATE_WRITE_BARRIER);
  scope_info->SetFlags(
Dan Elphick's avatar
Dan Elphick committed
568
      HasLocalsBlockListBit::update(scope_info->Flags(), true));
569

Dan Elphick's avatar
Dan Elphick committed
570 571 572
  // Copy the dynamic part including the provided blocklist:
  //   1) copy all the fields up to the blocklist index
  //   2) add the blocklist
573 574 575
  //   3) copy the remaining fields
  scope_info->CopyElements(
      isolate, kVariablePartIndex, *original, kVariablePartIndex,
Dan Elphick's avatar
Dan Elphick committed
576
      scope_info->LocalsBlockListIndex() - kVariablePartIndex,
577
      WriteBarrierMode::UPDATE_WRITE_BARRIER);
Dan Elphick's avatar
Dan Elphick committed
578
  scope_info->set(scope_info->LocalsBlockListIndex(), *blocklist);
579
  scope_info->CopyElements(
Dan Elphick's avatar
Dan Elphick committed
580 581 582
      isolate, scope_info->LocalsBlockListIndex() + 1, *original,
      scope_info->LocalsBlockListIndex(),
      scope_info->length() - scope_info->LocalsBlockListIndex() - 1,
583 584 585 586
      WriteBarrierMode::UPDATE_WRITE_BARRIER);
  return scope_info;
}

587
ScopeInfo ScopeInfo::Empty(Isolate* isolate) {
588
  return ReadOnlyRoots(isolate).empty_scope_info();
589 590
}

591 592
bool ScopeInfo::IsEmpty() const { return IsEmptyBit::decode(Flags()); }

593
ScopeType ScopeInfo::scope_type() const {
594
  DCHECK(!IsEmpty());
595
  return ScopeTypeBits::decode(Flags());
596 597
}

598
bool ScopeInfo::is_script_scope() const {
599
  return !IsEmpty() && scope_type() == SCRIPT_SCOPE;
600 601
}

602 603
bool ScopeInfo::SloppyEvalCanExtendVars() const {
  bool sloppy_eval_can_extend_vars =
604
      SloppyEvalCanExtendVarsBit::decode(Flags());
605 606 607
  DCHECK_IMPLIES(sloppy_eval_can_extend_vars, is_sloppy(language_mode()));
  DCHECK_IMPLIES(sloppy_eval_can_extend_vars, is_declaration_scope());
  return sloppy_eval_can_extend_vars;
608 609
}

610
LanguageMode ScopeInfo::language_mode() const {
611
  return LanguageModeBit::decode(Flags());
612 613
}

614
bool ScopeInfo::is_declaration_scope() const {
615
  return DeclarationScopeBit::decode(Flags());
616 617
}

618
int ScopeInfo::ContextLength() const {
619
  if (!IsEmpty()) {
620
    int context_locals = ContextLocalCount();
621 622 623
    bool function_name_context_slot = FunctionVariableBits::decode(Flags()) ==
                                      VariableAllocationInfo::CONTEXT;
    bool force_context = ForceContextAllocationBit::decode(Flags());
624 625 626
    bool has_context =
        context_locals > 0 || force_context || function_name_context_slot ||
        scope_type() == WITH_SCOPE || scope_type() == CLASS_SCOPE ||
627
        (scope_type() == BLOCK_SCOPE && SloppyEvalCanExtendVars() &&
628
         is_declaration_scope()) ||
629
        (scope_type() == FUNCTION_SCOPE && SloppyEvalCanExtendVars()) ||
630 631
        (scope_type() == FUNCTION_SCOPE && IsAsmModule()) ||
        scope_type() == MODULE_SCOPE;
632

633
    if (has_context) {
634
      return ContextHeaderLength() + context_locals +
635
             (function_name_context_slot ? 1 : 0);
636
    }
637
  }
638
  return 0;
639 640
}

641
bool ScopeInfo::HasContextExtensionSlot() const {
642
  return HasContextExtensionSlotBit::decode(Flags());
643 644 645
}

int ScopeInfo::ContextHeaderLength() const {
646 647
  return HasContextExtensionSlot() ? Context::MIN_CONTEXT_EXTENDED_SLOTS
                                   : Context::MIN_CONTEXT_SLOTS;
648 649
}

650
bool ScopeInfo::HasReceiver() const {
651
  return VariableAllocationInfo::NONE != ReceiverVariableBits::decode(Flags());
652 653
}

654
bool ScopeInfo::HasAllocatedReceiver() const {
655 656 657
  VariableAllocationInfo allocation = ReceiverVariableBits::decode(Flags());
  return allocation == VariableAllocationInfo::STACK ||
         allocation == VariableAllocationInfo::CONTEXT;
658 659
}

660
bool ScopeInfo::HasClassBrand() const {
661
  return HasClassBrandBit::decode(Flags());
662 663
}

664
bool ScopeInfo::HasSavedClassVariableIndex() const {
665
  return HasSavedClassVariableIndexBit::decode(Flags());
666 667
}

668
bool ScopeInfo::HasNewTarget() const {
669
  return HasNewTargetBit::decode(Flags());
670
}
671

672
bool ScopeInfo::HasFunctionName() const {
673
  return VariableAllocationInfo::NONE != FunctionVariableBits::decode(Flags());
674 675
}

676
bool ScopeInfo::HasInferredFunctionName() const {
677
  return HasInferredFunctionNameBit::decode(Flags());
678 679
}

680
bool ScopeInfo::HasPositionInfo() const {
681
  if (IsEmpty()) return false;
682 683 684 685 686 687 688
  return NeedsPositionInfo(scope_type());
}

// static
bool ScopeInfo::NeedsPositionInfo(ScopeType type) {
  return type == FUNCTION_SCOPE || type == SCRIPT_SCOPE || type == EVAL_SCOPE ||
         type == MODULE_SCOPE;
689 690
}

691 692
bool ScopeInfo::HasSharedFunctionName() const {
  return FunctionName() != SharedFunctionInfo::kNoSharedNameSentinel;
693 694
}

695
void ScopeInfo::SetFunctionName(Object name) {
696
  DCHECK(HasFunctionName());
697
  DCHECK(name.IsString() || name == SharedFunctionInfo::kNoSharedNameSentinel);
698 699 700
  set(FunctionNameInfoIndex(), name);
}

701
void ScopeInfo::SetInferredFunctionName(String name) {
702 703 704 705
  DCHECK(HasInferredFunctionName());
  set(InferredFunctionNameIndex(), name);
}

706
bool ScopeInfo::HasOuterScopeInfo() const {
707
  return HasOuterScopeInfoBit::decode(Flags());
jochen's avatar
jochen committed
708
}
709

710
bool ScopeInfo::IsDebugEvaluateScope() const {
711
  return IsDebugEvaluateScopeBit::decode(Flags());
712 713 714
}

void ScopeInfo::SetIsDebugEvaluateScope() {
715 716 717
  CHECK(!IsEmpty());
  DCHECK_EQ(scope_type(), WITH_SCOPE);
  SetFlags(Flags() | IsDebugEvaluateScopeBit::encode(true));
718 719
}

720
bool ScopeInfo::PrivateNameLookupSkipsOuterClass() const {
721
  return PrivateNameLookupSkipsOuterClassBit::decode(Flags());
722 723
}

Simon Zünd's avatar
Simon Zünd committed
724
bool ScopeInfo::IsReplModeScope() const {
725
  return IsReplModeScopeBit::decode(Flags());
Simon Zünd's avatar
Simon Zünd committed
726 727
}

Dan Elphick's avatar
Dan Elphick committed
728 729
bool ScopeInfo::HasLocalsBlockList() const {
  return HasLocalsBlockListBit::decode(Flags());
730 731
}

Dan Elphick's avatar
Dan Elphick committed
732 733 734
StringSet ScopeInfo::LocalsBlockList() const {
  DCHECK(HasLocalsBlockList());
  return StringSet::cast(get(LocalsBlockListIndex()));
735 736
}

737
bool ScopeInfo::HasContext() const { return ContextLength() > 0; }
738

739
Object ScopeInfo::FunctionName() const {
740
  DCHECK(HasFunctionName());
741
  return get(FunctionNameInfoIndex());
742 743
}

744
Object ScopeInfo::InferredFunctionName() const {
745 746 747 748
  DCHECK(HasInferredFunctionName());
  return get(InferredFunctionNameIndex());
}

749
String ScopeInfo::FunctionDebugName() const {
750
  if (!HasFunctionName()) return GetReadOnlyRoots().empty_string();
751
  Object name = FunctionName();
752
  if (name.IsString() && String::cast(name).length() > 0) {
753 754 755 756
    return String::cast(name);
  }
  if (HasInferredFunctionName()) {
    name = InferredFunctionName();
757
    if (name.IsString()) return String::cast(name);
758
  }
759
  return GetReadOnlyRoots().empty_string();
760 761
}

762
int ScopeInfo::StartPosition() const {
763
  DCHECK(HasPositionInfo());
764
  return Smi::ToInt(get(PositionInfoIndex()));
765 766
}

767
int ScopeInfo::EndPosition() const {
768
  DCHECK(HasPositionInfo());
769
  return Smi::ToInt(get(PositionInfoIndex() + 1));
770 771 772 773 774 775 776 777 778
}

void ScopeInfo::SetPositionInfo(int start, int end) {
  DCHECK(HasPositionInfo());
  DCHECK_LE(start, end);
  set(PositionInfoIndex(), Smi::FromInt(start));
  set(PositionInfoIndex() + 1, Smi::FromInt(end));
}

779
ScopeInfo ScopeInfo::OuterScopeInfo() const {
jochen's avatar
jochen committed
780
  DCHECK(HasOuterScopeInfo());
781
  return ScopeInfo::cast(get(OuterScopeInfoIndex()));
jochen's avatar
jochen committed
782 783
}

784
SourceTextModuleInfo ScopeInfo::ModuleDescriptorInfo() const {
785
  DCHECK(scope_type() == MODULE_SCOPE);
786
  return SourceTextModuleInfo::cast(get(ModuleInfoIndex()));
787
}
788

789
String ScopeInfo::ContextLocalName(int var) const {
790 791
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
792
  int info_index = ContextLocalNamesIndex() + var;
793
  return String::cast(get(info_index));
794 795
}

796
VariableMode ScopeInfo::ContextLocalMode(int var) const {
797 798
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
799
  int info_index = ContextLocalInfosIndex() + var;
jgruber's avatar
jgruber committed
800
  int value = Smi::ToInt(get(info_index));
801
  return VariableModeField::decode(value);
802 803
}

804 805 806 807 808 809 810 811
IsStaticFlag ScopeInfo::ContextLocalIsStaticFlag(int var) const {
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
  int info_index = ContextLocalInfosIndex() + var;
  int value = Smi::ToInt(get(info_index));
  return IsStaticFlagField::decode(value);
}

812
InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) const {
813 814
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
815
  int info_index = ContextLocalInfosIndex() + var;
jgruber's avatar
jgruber committed
816
  int value = Smi::ToInt(get(info_index));
817
  return InitFlagField::decode(value);
818 819
}

820 821 822 823 824 825 826 827 828 829 830 831 832 833 834
bool ScopeInfo::ContextLocalIsParameter(int var) const {
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
  int info_index = ContextLocalInfosIndex() + var;
  int value = Smi::ToInt(get(info_index));
  return ParameterNumberField::decode(value) != ParameterNumberField::kMax;
}

uint32_t ScopeInfo::ContextLocalParameterNumber(int var) const {
  DCHECK(ContextLocalIsParameter(var));
  int info_index = ContextLocalInfosIndex() + var;
  int value = Smi::ToInt(get(info_index));
  return ParameterNumberField::decode(value);
}

835
MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) const {
836 837
  DCHECK_LE(0, var);
  DCHECK_LT(var, ContextLocalCount());
838
  int info_index = ContextLocalInfosIndex() + var;
jgruber's avatar
jgruber committed
839
  int value = Smi::ToInt(get(info_index));
840
  return MaybeAssignedFlagField::decode(value);
841 842
}

843
// static
844
bool ScopeInfo::VariableIsSynthetic(String name) {
845 846 847 848
  // 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!
849
  return name.length() == 0 || name.Get(0) == '.' || name.Get(0) == '#' ||
850
         name.Equals(name.GetReadOnlyRoots().this_string());
851 852
}

853
int ScopeInfo::ModuleIndex(String name, VariableMode* mode,
854 855
                           InitializationFlag* init_flag,
                           MaybeAssignedFlag* maybe_assigned_flag) {
856
  DisallowGarbageCollection no_gc;
857
  DCHECK(name.IsInternalizedString());
858 859 860 861 862
  DCHECK_EQ(scope_type(), MODULE_SCOPE);
  DCHECK_NOT_NULL(mode);
  DCHECK_NOT_NULL(init_flag);
  DCHECK_NOT_NULL(maybe_assigned_flag);

jgruber's avatar
jgruber committed
863
  int module_vars_count = Smi::ToInt(get(ModuleVariableCountIndex()));
864
  int entry = ModuleVariablesIndex();
865
  for (int i = 0; i < module_vars_count; ++i) {
866
    String var_name = String::cast(get(entry + kModuleVariableNameOffset));
867
    if (name.Equals(var_name)) {
868 869
      int index;
      ModuleVariable(i, nullptr, &index, mode, init_flag, maybe_assigned_flag);
870 871 872 873 874
      return index;
    }
    entry += kModuleVariableEntryLength;
  }

875
  return 0;
876
}
877

878
// static
879 880
int ScopeInfo::ContextSlotIndex(ScopeInfo scope_info, String name,
                                VariableMode* mode,
881
                                InitializationFlag* init_flag,
882 883
                                MaybeAssignedFlag* maybe_assigned_flag,
                                IsStaticFlag* is_static_flag) {
884
  DisallowGarbageCollection no_gc;
885
  DCHECK(name.IsInternalizedString());
886 887 888 889
  DCHECK_NOT_NULL(mode);
  DCHECK_NOT_NULL(init_flag);
  DCHECK_NOT_NULL(maybe_assigned_flag);

890
  if (scope_info.IsEmpty()) return -1;
891

892 893
  int start = scope_info.ContextLocalNamesIndex();
  int end = start + scope_info.ContextLocalCount();
894
  for (int i = start; i < end; ++i) {
895
    if (name != scope_info.get(i)) continue;
896
    int var = i - start;
897
    *mode = scope_info.ContextLocalMode(var);
898
    *is_static_flag = scope_info.ContextLocalIsStaticFlag(var);
899 900
    *init_flag = scope_info.ContextLocalInitFlag(var);
    *maybe_assigned_flag = scope_info.ContextLocalMaybeAssignedFlag(var);
901
    int result = scope_info.ContextHeaderLength() + var;
902

903
    DCHECK_LT(result, scope_info.ContextLength());
904
    return result;
905
  }
906

907 908 909
  return -1;
}

910
int ScopeInfo::SavedClassVariableContextLocalIndex() const {
911
  if (HasSavedClassVariableIndexBit::decode(Flags())) {
912 913 914 915 916 917
    int index = Smi::ToInt(get(SavedClassVariableInfoIndex()));
    return index - Context::MIN_CONTEXT_SLOTS;
  }
  return -1;
}

918
int ScopeInfo::ReceiverContextSlotIndex() const {
919 920
  if (ReceiverVariableBits::decode(Flags()) ==
      VariableAllocationInfo::CONTEXT) {
jgruber's avatar
jgruber committed
921
    return Smi::ToInt(get(ReceiverInfoIndex()));
922
  }
923 924 925
  return -1;
}

926
int ScopeInfo::FunctionContextSlotIndex(String name) const {
927
  DCHECK(name.IsInternalizedString());
928 929 930 931
  if (FunctionVariableBits::decode(Flags()) ==
          VariableAllocationInfo::CONTEXT &&
      FunctionName() == name) {
    return Smi::ToInt(get(FunctionNameInfoIndex() + 1));
932 933 934 935
  }
  return -1;
}

936
FunctionKind ScopeInfo::function_kind() const {
937
  return FunctionKindBits::decode(Flags());
938 939
}

940
int ScopeInfo::ContextLocalNamesIndex() const {
941
  DCHECK_LE(kVariablePartIndex, length());
942 943 944
  return kVariablePartIndex;
}

945
int ScopeInfo::ContextLocalInfosIndex() const {
946
  return ContextLocalNamesIndex() + ContextLocalCount();
947 948
}

949
int ScopeInfo::SavedClassVariableInfoIndex() const {
950
  return ContextLocalInfosIndex() + ContextLocalCount();
951 952
}

953 954 955 956
int ScopeInfo::ReceiverInfoIndex() const {
  return SavedClassVariableInfoIndex() + (HasSavedClassVariableIndex() ? 1 : 0);
}

957
int ScopeInfo::FunctionNameInfoIndex() const {
958
  return ReceiverInfoIndex() + (HasAllocatedReceiver() ? 1 : 0);
959 960
}

961
int ScopeInfo::InferredFunctionNameIndex() const {
962 963 964 965
  return FunctionNameInfoIndex() +
         (HasFunctionName() ? kFunctionNameEntries : 0);
}

966 967 968 969
int ScopeInfo::PositionInfoIndex() const {
  return InferredFunctionNameIndex() + (HasInferredFunctionName() ? 1 : 0);
}

970
int ScopeInfo::OuterScopeInfoIndex() const {
971
  return PositionInfoIndex() + (HasPositionInfo() ? kPositionInfoEntries : 0);
972 973
}

Dan Elphick's avatar
Dan Elphick committed
974
int ScopeInfo::LocalsBlockListIndex() const {
975
  return OuterScopeInfoIndex() + (HasOuterScopeInfo() ? 1 : 0);
jochen's avatar
jochen committed
976 977
}

978
int ScopeInfo::ModuleInfoIndex() const {
Dan Elphick's avatar
Dan Elphick committed
979
  return LocalsBlockListIndex() + (HasLocalsBlockList() ? 1 : 0);
980 981
}

982 983 984
int ScopeInfo::ModuleVariableCountIndex() const {
  return ModuleInfoIndex() + 1;
}
985

986 987 988
int ScopeInfo::ModuleVariablesIndex() const {
  return ModuleVariableCountIndex() + 1;
}
989

990
void ScopeInfo::ModuleVariable(int i, String* name, int* index,
991 992 993 994
                               VariableMode* mode,
                               InitializationFlag* init_flag,
                               MaybeAssignedFlag* maybe_assigned_flag) {
  DCHECK_LE(0, i);
jgruber's avatar
jgruber committed
995
  DCHECK_LT(i, Smi::ToInt(get(ModuleVariableCountIndex())));
996 997

  int entry = ModuleVariablesIndex() + i * kModuleVariableEntryLength;
jgruber's avatar
jgruber committed
998
  int properties = Smi::ToInt(get(entry + kModuleVariablePropertiesOffset));
999 1000 1001 1002 1003

  if (name != nullptr) {
    *name = String::cast(get(entry + kModuleVariableNameOffset));
  }
  if (index != nullptr) {
jgruber's avatar
jgruber committed
1004
    *index = Smi::ToInt(get(entry + kModuleVariableIndexOffset));
1005
    DCHECK_NE(*index, 0);
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017
  }
  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);
  }
}

1018
std::ostream& operator<<(std::ostream& os, VariableAllocationInfo var_info) {
1019
  switch (var_info) {
1020
    case VariableAllocationInfo::NONE:
1021
      return os << "NONE";
1022
    case VariableAllocationInfo::STACK:
1023
      return os << "STACK";
1024
    case VariableAllocationInfo::CONTEXT:
1025
      return os << "CONTEXT";
1026
    case VariableAllocationInfo::UNUSED:
1027 1028 1029 1030 1031 1032
      return os << "UNUSED";
  }
  UNREACHABLE();
  return os;
}

1033 1034 1035
template <typename LocalIsolate>
Handle<ModuleRequest> ModuleRequest::New(LocalIsolate* isolate,
                                         Handle<String> specifier,
1036 1037
                                         Handle<FixedArray> import_assertions,
                                         int position) {
1038 1039 1040 1041
  Handle<ModuleRequest> result = Handle<ModuleRequest>::cast(
      isolate->factory()->NewStruct(MODULE_REQUEST_TYPE, AllocationType::kOld));
  result->set_specifier(*specifier);
  result->set_import_assertions(*import_assertions);
1042
  result->set_position(position);
1043 1044 1045 1046 1047
  return result;
}

template Handle<ModuleRequest> ModuleRequest::New(
    Isolate* isolate, Handle<String> specifier,
1048
    Handle<FixedArray> import_assertions, int position);
1049 1050
template Handle<ModuleRequest> ModuleRequest::New(
    LocalIsolate* isolate, Handle<String> specifier,
1051
    Handle<FixedArray> import_assertions, int position);
1052

1053 1054 1055 1056 1057 1058 1059 1060 1061
template <typename LocalIsolate>
Handle<SourceTextModuleInfoEntry> SourceTextModuleInfoEntry::New(
    LocalIsolate* isolate, Handle<PrimitiveHeapObject> export_name,
    Handle<PrimitiveHeapObject> local_name,
    Handle<PrimitiveHeapObject> import_name, int module_request, int cell_index,
    int beg_pos, int end_pos) {
  Handle<SourceTextModuleInfoEntry> result =
      Handle<SourceTextModuleInfoEntry>::cast(isolate->factory()->NewStruct(
          SOURCE_TEXT_MODULE_INFO_ENTRY_TYPE, AllocationType::kOld));
1062 1063 1064 1065 1066 1067 1068
  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);
1069 1070 1071
  return result;
}

1072 1073 1074 1075 1076
template Handle<SourceTextModuleInfoEntry> SourceTextModuleInfoEntry::New(
    Isolate* isolate, Handle<PrimitiveHeapObject> export_name,
    Handle<PrimitiveHeapObject> local_name,
    Handle<PrimitiveHeapObject> import_name, int module_request, int cell_index,
    int beg_pos, int end_pos);
1077
template Handle<SourceTextModuleInfoEntry> SourceTextModuleInfoEntry::New(
1078
    LocalIsolate* isolate, Handle<PrimitiveHeapObject> export_name,
1079 1080 1081 1082 1083 1084 1085
    Handle<PrimitiveHeapObject> local_name,
    Handle<PrimitiveHeapObject> import_name, int module_request, int cell_index,
    int beg_pos, int end_pos);

template <typename LocalIsolate>
Handle<SourceTextModuleInfo> SourceTextModuleInfo::New(
    LocalIsolate* isolate, Zone* zone, SourceTextModuleDescriptor* descr) {
1086
  // Serialize module requests.
1087
  int size = static_cast<int>(descr->module_requests().size());
1088
  Handle<FixedArray> module_requests = isolate->factory()->NewFixedArray(size);
1089
  for (const auto& elem : descr->module_requests()) {
1090 1091
    Handle<ModuleRequest> serialized_module_request = elem->Serialize(isolate);
    module_requests->set(elem->index(), *serialized_module_request);
1092 1093
  }

1094
  // Serialize special exports.
1095 1096
  Handle<FixedArray> special_exports = isolate->factory()->NewFixedArray(
      static_cast<int>(descr->special_exports().size()));
1097 1098 1099
  {
    int i = 0;
    for (auto entry : descr->special_exports()) {
1100
      Handle<SourceTextModuleInfoEntry> serialized_entry =
1101
          entry->Serialize(isolate);
1102
      special_exports->set(i++, *serialized_entry);
1103 1104 1105
    }
  }

1106
  // Serialize namespace imports.
1107 1108
  Handle<FixedArray> namespace_imports = isolate->factory()->NewFixedArray(
      static_cast<int>(descr->namespace_imports().size()));
1109 1110
  {
    int i = 0;
1111
    for (auto entry : descr->namespace_imports()) {
1112
      Handle<SourceTextModuleInfoEntry> serialized_entry =
1113
          entry->Serialize(isolate);
1114
      namespace_imports->set(i++, *serialized_entry);
1115 1116 1117
    }
  }

1118
  // Serialize regular exports.
1119
  Handle<FixedArray> regular_exports =
1120
      descr->SerializeRegularExports(isolate, zone);
1121

1122
  // Serialize regular imports.
1123 1124
  Handle<FixedArray> regular_imports = isolate->factory()->NewFixedArray(
      static_cast<int>(descr->regular_imports().size()));
1125 1126 1127
  {
    int i = 0;
    for (const auto& elem : descr->regular_imports()) {
1128
      Handle<SourceTextModuleInfoEntry> serialized_entry =
1129 1130
          elem.second->Serialize(isolate);
      regular_imports->set(i++, *serialized_entry);
1131 1132 1133
    }
  }

1134
  Handle<SourceTextModuleInfo> result =
1135
      isolate->factory()->NewSourceTextModuleInfo();
1136
  result->set(kModuleRequestsIndex, *module_requests);
1137 1138
  result->set(kSpecialExportsIndex, *special_exports);
  result->set(kRegularExportsIndex, *regular_exports);
1139
  result->set(kNamespaceImportsIndex, *namespace_imports);
1140
  result->set(kRegularImportsIndex, *regular_imports);
1141 1142
  return result;
}
1143 1144
template Handle<SourceTextModuleInfo> SourceTextModuleInfo::New(
    Isolate* isolate, Zone* zone, SourceTextModuleDescriptor* descr);
1145
template Handle<SourceTextModuleInfo> SourceTextModuleInfo::New(
1146
    LocalIsolate* isolate, Zone* zone, SourceTextModuleDescriptor* descr);
1147

1148
int SourceTextModuleInfo::RegularExportCount() const {
1149 1150
  DCHECK_EQ(regular_exports().length() % kRegularExportLength, 0);
  return regular_exports().length() / kRegularExportLength;
1151 1152
}

1153
String SourceTextModuleInfo::RegularExportLocalName(int i) const {
1154 1155
  return String::cast(regular_exports().get(i * kRegularExportLength +
                                            kRegularExportLocalNameOffset));
1156 1157
}

1158
int SourceTextModuleInfo::RegularExportCellIndex(int i) const {
1159 1160
  return Smi::ToInt(regular_exports().get(i * kRegularExportLength +
                                          kRegularExportCellIndexOffset));
1161 1162
}

1163
FixedArray SourceTextModuleInfo::RegularExportExportNames(int i) const {
1164
  return FixedArray::cast(regular_exports().get(
1165 1166 1167
      i * kRegularExportLength + kRegularExportExportNamesOffset));
}

1168 1169
}  // namespace internal
}  // namespace v8