1// Copyright 2011 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <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
12namespace v8 {
13namespace internal {
14
15// An entry in ModuleVariableEntries consists of several slots:
16enum ModuleVariableEntryOffset {
17  kModuleVariableNameOffset,
18  kModuleVariableIndexOffset,
19  kModuleVariablePropertiesOffset,
20  kModuleVariableEntryLength  // Sentinel value.
21};
22
23#ifdef DEBUG
24bool ScopeInfo::Equals(ScopeInfo* other) const {
25  if (length() != other->length()) return false;
26  for (int index = 0; index < length(); ++index) {
27    Object* entry = get(index);
28    Object* other_entry = other->get(index);
29    if (entry->IsSmi()) {
30      if (entry != other_entry) return false;
31    } else {
32      if (HeapObject::cast(entry)->map()->instance_type() !=
33          HeapObject::cast(other_entry)->map()->instance_type()) {
34        return false;
35      }
36      if (entry->IsString()) {
37        if (!String::cast(entry)->Equals(String::cast(other_entry))) {
38          return false;
39        }
40      } else if (entry->IsScopeInfo()) {
41        if (!ScopeInfo::cast(entry)->Equals(ScopeInfo::cast(other_entry))) {
42          return false;
43        }
44      } else if (entry->IsModuleInfo()) {
45        if (!ModuleInfo::cast(entry)->Equals(ModuleInfo::cast(other_entry))) {
46          return false;
47        }
48      } else {
49        UNREACHABLE();
50        return false;
51      }
52    }
53  }
54  return true;
55}
56#endif
57
58Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
59                                    MaybeHandle<ScopeInfo> outer_scope) {
60  // Collect variables.
61  int stack_local_count = 0;
62  int context_local_count = 0;
63  int module_vars_count = 0;
64  // Stack allocated block scope variables are allocated in the parent
65  // declaration scope, but are recorded in the block scope's scope info. First
66  // slot index indicates at which offset a particular scope starts in the
67  // parent declaration scope.
68  int first_slot_index = 0;
69  for (Variable* var : *scope->locals()) {
70    switch (var->location()) {
71      case VariableLocation::LOCAL:
72        if (stack_local_count == 0) first_slot_index = var->index();
73        stack_local_count++;
74        break;
75      case VariableLocation::CONTEXT:
76        context_local_count++;
77        break;
78      case VariableLocation::MODULE:
79        module_vars_count++;
80        break;
81      default:
82        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  // Determine use and location of the "this" binding if it is present.
91  VariableAllocationInfo receiver_info;
92  if (scope->is_declaration_scope() &&
93      scope->AsDeclarationScope()->has_this_declaration()) {
94    Variable* var = scope->AsDeclarationScope()->receiver();
95    if (!var->is_used()) {
96      receiver_info = UNUSED;
97    } else if (var->IsContextSlot()) {
98      receiver_info = CONTEXT;
99    } else {
100      DCHECK(var->IsParameter());
101      receiver_info = STACK;
102    }
103  } else {
104    receiver_info = NONE;
105  }
106
107  bool has_new_target =
108      scope->is_declaration_scope() &&
109      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      scope->AsDeclarationScope()->function_var() != nullptr) {
115    Variable* var = scope->AsDeclarationScope()->function_var();
116    if (!var->is_used()) {
117      function_name_info = UNUSED;
118    } else if (var->IsContextSlot()) {
119      function_name_info = CONTEXT;
120    } 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();
131  const bool has_outer_scope_info = !outer_scope.is_null();
132  const int length = kVariablePartIndex + parameter_count +
133                     (1 + stack_local_count) + 2 * context_local_count +
134                     (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0) +
135                     (has_outer_scope_info ? 1 : 0) +
136                     (scope->is_module_scope()
137                          ? 2 + kModuleVariableEntryLength * module_vars_count
138                          : 0);
139
140  Factory* factory = isolate->factory();
141  Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
142
143  bool has_simple_parameters = false;
144  bool asm_module = false;
145  bool asm_function = false;
146  FunctionKind function_kind = kNormalFunction;
147  if (scope->is_function_scope()) {
148    DeclarationScope* function_scope = scope->AsDeclarationScope();
149    has_simple_parameters = function_scope->has_simple_parameters();
150    asm_module = function_scope->asm_module();
151    asm_function = function_scope->asm_function();
152    function_kind = function_scope->function_kind();
153  }
154
155  // Encode the flags.
156  int flags =
157      ScopeTypeField::encode(scope->scope_type()) |
158      CallsEvalField::encode(scope->calls_eval()) |
159      LanguageModeField::encode(scope->language_mode()) |
160      DeclarationScopeField::encode(scope->is_declaration_scope()) |
161      ReceiverVariableField::encode(receiver_info) |
162      HasNewTargetField::encode(has_new_target) |
163      FunctionVariableField::encode(function_name_info) |
164      AsmModuleField::encode(asm_module) |
165      AsmFunctionField::encode(asm_function) |
166      HasSimpleParametersField::encode(has_simple_parameters) |
167      FunctionKindField::encode(function_kind) |
168      HasOuterScopeInfoField::encode(has_outer_scope_info) |
169      IsDebugEvaluateScopeField::encode(scope->is_debug_evaluate_scope());
170  scope_info->SetFlags(flags);
171
172  scope_info->SetParameterCount(parameter_count);
173  scope_info->SetStackLocalCount(stack_local_count);
174  scope_info->SetContextLocalCount(context_local_count);
175
176  int index = kVariablePartIndex;
177  // Add parameters.
178  DCHECK_EQ(index, scope_info->ParameterNamesIndex());
179  if (scope->is_declaration_scope()) {
180    for (int i = 0; i < parameter_count; ++i) {
181      scope_info->set(index++,
182                      *scope->AsDeclarationScope()->parameter(i)->name());
183    }
184  }
185
186  // Add stack locals' names, context locals' names and info, module variables'
187  // names and info. We are assuming that the stack locals' slots are allocated
188  // in increasing order, so we can simply add them to the ScopeInfo object.
189  // Context locals are added using their index.
190  DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex());
191  scope_info->set(index++, Smi::FromInt(first_slot_index));
192  DCHECK_EQ(index, scope_info->StackLocalNamesIndex());
193
194  int stack_local_base = index;
195  int context_local_base = stack_local_base + stack_local_count;
196  int context_local_info_base = context_local_base + context_local_count;
197  int module_var_entry = scope_info->ModuleVariablesIndex();
198
199  for (Variable* var : *scope->locals()) {
200    switch (var->location()) {
201      case VariableLocation::LOCAL: {
202        int local_index = var->index() - first_slot_index;
203        DCHECK_LE(0, local_index);
204        DCHECK_LT(local_index, stack_local_count);
205        scope_info->set(stack_local_base + local_index, *var->name());
206        break;
207      }
208      case VariableLocation::CONTEXT: {
209        // Due to duplicate parameters, context locals aren't guaranteed to come
210        // in order.
211        int local_index = var->index() - Context::MIN_CONTEXT_SLOTS;
212        DCHECK_LE(0, local_index);
213        DCHECK_LT(local_index, context_local_count);
214        uint32_t info = VariableModeField::encode(var->mode()) |
215                        InitFlagField::encode(var->initialization_flag()) |
216                        MaybeAssignedFlagField::encode(var->maybe_assigned());
217        scope_info->set(context_local_base + local_index, *var->name());
218        scope_info->set(context_local_info_base + local_index,
219                        Smi::FromInt(info));
220        break;
221      }
222      case VariableLocation::MODULE: {
223        scope_info->set(module_var_entry + kModuleVariableNameOffset,
224                        *var->name());
225        scope_info->set(module_var_entry + kModuleVariableIndexOffset,
226                        Smi::FromInt(var->index()));
227        uint32_t properties =
228            VariableModeField::encode(var->mode()) |
229            InitFlagField::encode(var->initialization_flag()) |
230            MaybeAssignedFlagField::encode(var->maybe_assigned());
231        scope_info->set(module_var_entry + kModuleVariablePropertiesOffset,
232                        Smi::FromInt(properties));
233        module_var_entry += kModuleVariableEntryLength;
234        break;
235      }
236      default:
237        break;
238    }
239  }
240
241  index += stack_local_count + 2 * context_local_count;
242
243  // If the receiver is allocated, add its index.
244  DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
245  if (has_receiver) {
246    int var_index = scope->AsDeclarationScope()->receiver()->index();
247    scope_info->set(index++, Smi::FromInt(var_index));
248    // ?? DCHECK(receiver_info != CONTEXT || var_index ==
249    // scope_info->ContextLength() - 1);
250  }
251
252  // If present, add the function variable name and its index.
253  DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
254  if (has_function_name) {
255    int var_index = scope->AsDeclarationScope()->function_var()->index();
256    scope_info->set(index++,
257                    *scope->AsDeclarationScope()->function_var()->name());
258    scope_info->set(index++, Smi::FromInt(var_index));
259    DCHECK(function_name_info != CONTEXT ||
260           var_index == scope_info->ContextLength() - 1);
261  }
262
263  // If present, add the outer scope info.
264  DCHECK(index == scope_info->OuterScopeInfoIndex());
265  if (has_outer_scope_info) {
266    scope_info->set(index++, *outer_scope.ToHandleChecked());
267  }
268
269  // Module-specific information (only for module scopes).
270  if (scope->is_module_scope()) {
271    Handle<ModuleInfo> module_info =
272        ModuleInfo::New(isolate, zone, scope->AsModuleScope()->module());
273    DCHECK_EQ(index, scope_info->ModuleInfoIndex());
274    scope_info->set(index++, *module_info);
275    DCHECK_EQ(index, scope_info->ModuleVariableCountIndex());
276    scope_info->set(index++, Smi::FromInt(module_vars_count));
277    DCHECK_EQ(index, scope_info->ModuleVariablesIndex());
278    // The variable entries themselves have already been written above.
279    index += kModuleVariableEntryLength * module_vars_count;
280  }
281
282  DCHECK_EQ(index, scope_info->length());
283  DCHECK_EQ(scope->num_parameters(), scope_info->ParameterCount());
284  DCHECK_EQ(scope->num_heap_slots(), scope_info->ContextLength());
285  return scope_info;
286}
287
288Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
289    Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope) {
290  const bool has_outer_scope_info = !outer_scope.is_null();
291  const int length = kVariablePartIndex + 1 + (has_outer_scope_info ? 1 : 0);
292
293  Factory* factory = isolate->factory();
294  Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
295
296  // Encode the flags.
297  int flags =
298      ScopeTypeField::encode(WITH_SCOPE) | CallsEvalField::encode(false) |
299      LanguageModeField::encode(SLOPPY) | DeclarationScopeField::encode(false) |
300      ReceiverVariableField::encode(NONE) | HasNewTargetField::encode(false) |
301      FunctionVariableField::encode(NONE) | AsmModuleField::encode(false) |
302      AsmFunctionField::encode(false) | HasSimpleParametersField::encode(true) |
303      FunctionKindField::encode(kNormalFunction) |
304      HasOuterScopeInfoField::encode(has_outer_scope_info) |
305      IsDebugEvaluateScopeField::encode(false);
306  scope_info->SetFlags(flags);
307
308  scope_info->SetParameterCount(0);
309  scope_info->SetStackLocalCount(0);
310  scope_info->SetContextLocalCount(0);
311
312  int index = kVariablePartIndex;
313  DCHECK_EQ(index, scope_info->ParameterNamesIndex());
314  DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex());
315  scope_info->set(index++, Smi::kZero);
316  DCHECK_EQ(index, scope_info->StackLocalNamesIndex());
317  DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
318  DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
319  DCHECK(index == scope_info->OuterScopeInfoIndex());
320  if (has_outer_scope_info) {
321    scope_info->set(index++, *outer_scope.ToHandleChecked());
322  }
323  DCHECK_EQ(index, scope_info->length());
324  DCHECK_EQ(0, scope_info->ParameterCount());
325  DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, scope_info->ContextLength());
326  return scope_info;
327}
328
329Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
330  DCHECK(isolate->bootstrapper()->IsActive());
331
332  const int stack_local_count = 0;
333  const int context_local_count = 1;
334  const bool has_simple_parameters = true;
335  const VariableAllocationInfo receiver_info = CONTEXT;
336  const VariableAllocationInfo function_name_info = NONE;
337  const bool has_function_name = false;
338  const bool has_receiver = true;
339  const bool has_outer_scope_info = false;
340  const int parameter_count = 0;
341  const int length = kVariablePartIndex + parameter_count +
342                     (1 + stack_local_count) + 2 * context_local_count +
343                     (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0) +
344                     (has_outer_scope_info ? 1 : 0);
345
346  Factory* factory = isolate->factory();
347  Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
348
349  // Encode the flags.
350  int flags =
351      ScopeTypeField::encode(SCRIPT_SCOPE) | CallsEvalField::encode(false) |
352      LanguageModeField::encode(SLOPPY) | DeclarationScopeField::encode(true) |
353      ReceiverVariableField::encode(receiver_info) |
354      FunctionVariableField::encode(function_name_info) |
355      AsmModuleField::encode(false) | AsmFunctionField::encode(false) |
356      HasSimpleParametersField::encode(has_simple_parameters) |
357      FunctionKindField::encode(FunctionKind::kNormalFunction) |
358      HasOuterScopeInfoField::encode(has_outer_scope_info) |
359      IsDebugEvaluateScopeField::encode(false);
360  scope_info->SetFlags(flags);
361  scope_info->SetParameterCount(parameter_count);
362  scope_info->SetStackLocalCount(stack_local_count);
363  scope_info->SetContextLocalCount(context_local_count);
364
365  int index = kVariablePartIndex;
366  const int first_slot_index = 0;
367  DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex());
368  scope_info->set(index++, Smi::FromInt(first_slot_index));
369  DCHECK_EQ(index, scope_info->StackLocalNamesIndex());
370
371  // Here we add info for context-allocated "this".
372  DCHECK_EQ(index, scope_info->ContextLocalNamesIndex());
373  scope_info->set(index++, isolate->heap()->this_string());
374  DCHECK_EQ(index, scope_info->ContextLocalInfosIndex());
375  const uint32_t value = VariableModeField::encode(CONST) |
376                         InitFlagField::encode(kCreatedInitialized) |
377                         MaybeAssignedFlagField::encode(kNotAssigned);
378  scope_info->set(index++, Smi::FromInt(value));
379
380  // And here we record that this scopeinfo binds a receiver.
381  DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
382  const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0;
383  scope_info->set(index++, Smi::FromInt(receiver_index));
384
385  DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
386  DCHECK_EQ(index, scope_info->OuterScopeInfoIndex());
387  DCHECK_EQ(index, scope_info->length());
388  DCHECK_EQ(scope_info->ParameterCount(), 0);
389  DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1);
390
391  return scope_info;
392}
393
394
395ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
396  return isolate->heap()->empty_scope_info();
397}
398
399
400ScopeType ScopeInfo::scope_type() {
401  DCHECK_LT(0, length());
402  return ScopeTypeField::decode(Flags());
403}
404
405
406bool ScopeInfo::CallsEval() {
407  return length() > 0 && CallsEvalField::decode(Flags());
408}
409
410
411LanguageMode ScopeInfo::language_mode() {
412  return length() > 0 ? LanguageModeField::decode(Flags()) : SLOPPY;
413}
414
415
416bool ScopeInfo::is_declaration_scope() {
417  return DeclarationScopeField::decode(Flags());
418}
419
420
421int ScopeInfo::LocalCount() {
422  return StackLocalCount() + ContextLocalCount();
423}
424
425
426int ScopeInfo::StackSlotCount() {
427  if (length() > 0) {
428    bool function_name_stack_slot =
429        FunctionVariableField::decode(Flags()) == STACK;
430    return StackLocalCount() + (function_name_stack_slot ? 1 : 0);
431  }
432  return 0;
433}
434
435
436int ScopeInfo::ContextLength() {
437  if (length() > 0) {
438    int context_locals = ContextLocalCount();
439    bool function_name_context_slot =
440        FunctionVariableField::decode(Flags()) == CONTEXT;
441    bool has_context = context_locals > 0 || function_name_context_slot ||
442                       scope_type() == WITH_SCOPE ||
443                       (scope_type() == BLOCK_SCOPE && CallsSloppyEval() &&
444                        is_declaration_scope()) ||
445                       (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) ||
446                       scope_type() == MODULE_SCOPE;
447
448    if (has_context) {
449      return Context::MIN_CONTEXT_SLOTS + context_locals +
450             (function_name_context_slot ? 1 : 0);
451    }
452  }
453  return 0;
454}
455
456
457bool ScopeInfo::HasReceiver() {
458  if (length() > 0) {
459    return NONE != ReceiverVariableField::decode(Flags());
460  } else {
461    return false;
462  }
463}
464
465
466bool ScopeInfo::HasAllocatedReceiver() {
467  if (length() > 0) {
468    VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags());
469    return allocation == STACK || allocation == CONTEXT;
470  } else {
471    return false;
472  }
473}
474
475
476bool ScopeInfo::HasNewTarget() { return HasNewTargetField::decode(Flags()); }
477
478
479bool ScopeInfo::HasFunctionName() {
480  if (length() > 0) {
481    return NONE != FunctionVariableField::decode(Flags());
482  } else {
483    return false;
484  }
485}
486
487bool ScopeInfo::HasOuterScopeInfo() {
488  if (length() > 0) {
489    return HasOuterScopeInfoField::decode(Flags());
490  } else {
491    return false;
492  }
493}
494
495bool ScopeInfo::IsDebugEvaluateScope() {
496  if (length() > 0) {
497    return IsDebugEvaluateScopeField::decode(Flags());
498  } else {
499    return false;
500  }
501}
502
503void ScopeInfo::SetIsDebugEvaluateScope() {
504  if (length() > 0) {
505    DCHECK_EQ(scope_type(), WITH_SCOPE);
506    SetFlags(Flags() | IsDebugEvaluateScopeField::encode(true));
507  } else {
508    UNREACHABLE();
509  }
510}
511
512bool ScopeInfo::HasHeapAllocatedLocals() {
513  if (length() > 0) {
514    return ContextLocalCount() > 0;
515  } else {
516    return false;
517  }
518}
519
520
521bool ScopeInfo::HasContext() {
522  return ContextLength() > 0;
523}
524
525
526String* ScopeInfo::FunctionName() {
527  DCHECK(HasFunctionName());
528  return String::cast(get(FunctionNameInfoIndex()));
529}
530
531ScopeInfo* ScopeInfo::OuterScopeInfo() {
532  DCHECK(HasOuterScopeInfo());
533  return ScopeInfo::cast(get(OuterScopeInfoIndex()));
534}
535
536ModuleInfo* ScopeInfo::ModuleDescriptorInfo() {
537  DCHECK(scope_type() == MODULE_SCOPE);
538  return ModuleInfo::cast(get(ModuleInfoIndex()));
539}
540
541String* ScopeInfo::ParameterName(int var) {
542  DCHECK_LE(0, var);
543  DCHECK_LT(var, ParameterCount());
544  int info_index = ParameterNamesIndex() + var;
545  return String::cast(get(info_index));
546}
547
548
549String* ScopeInfo::LocalName(int var) {
550  DCHECK_LE(0, var);
551  DCHECK_LT(var, LocalCount());
552  DCHECK(StackLocalNamesIndex() + StackLocalCount() ==
553         ContextLocalNamesIndex());
554  int info_index = StackLocalNamesIndex() + var;
555  return String::cast(get(info_index));
556}
557
558
559String* ScopeInfo::StackLocalName(int var) {
560  DCHECK_LE(0, var);
561  DCHECK_LT(var, StackLocalCount());
562  int info_index = StackLocalNamesIndex() + var;
563  return String::cast(get(info_index));
564}
565
566
567int ScopeInfo::StackLocalIndex(int var) {
568  DCHECK_LE(0, var);
569  DCHECK_LT(var, StackLocalCount());
570  int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
571  return first_slot_index + var;
572}
573
574
575String* ScopeInfo::ContextLocalName(int var) {
576  DCHECK_LE(0, var);
577  DCHECK_LT(var, ContextLocalCount());
578  int info_index = ContextLocalNamesIndex() + var;
579  return String::cast(get(info_index));
580}
581
582
583VariableMode ScopeInfo::ContextLocalMode(int var) {
584  DCHECK_LE(0, var);
585  DCHECK_LT(var, ContextLocalCount());
586  int info_index = ContextLocalInfosIndex() + var;
587  int value = Smi::cast(get(info_index))->value();
588  return VariableModeField::decode(value);
589}
590
591
592InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
593  DCHECK_LE(0, var);
594  DCHECK_LT(var, ContextLocalCount());
595  int info_index = ContextLocalInfosIndex() + var;
596  int value = Smi::cast(get(info_index))->value();
597  return InitFlagField::decode(value);
598}
599
600
601MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) {
602  DCHECK_LE(0, var);
603  DCHECK_LT(var, ContextLocalCount());
604  int info_index = ContextLocalInfosIndex() + var;
605  int value = Smi::cast(get(info_index))->value();
606  return MaybeAssignedFlagField::decode(value);
607}
608
609bool ScopeInfo::VariableIsSynthetic(String* name) {
610  // There's currently no flag stored on the ScopeInfo to indicate that a
611  // variable is a compiler-introduced temporary. However, to avoid conflict
612  // with user declarations, the current temporaries like .generator_object and
613  // .result start with a dot, so we can use that as a flag. It's a hack!
614  return name->length() == 0 || name->Get(0) == '.' ||
615         name->Equals(name->GetHeap()->this_string());
616}
617
618
619int ScopeInfo::StackSlotIndex(String* name) {
620  DCHECK(name->IsInternalizedString());
621  if (length() > 0) {
622    int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
623    int start = StackLocalNamesIndex();
624    int end = start + StackLocalCount();
625    for (int i = start; i < end; ++i) {
626      if (name == get(i)) {
627        return i - start + first_slot_index;
628      }
629    }
630  }
631  return -1;
632}
633
634int ScopeInfo::ModuleIndex(Handle<String> name, VariableMode* mode,
635                           InitializationFlag* init_flag,
636                           MaybeAssignedFlag* maybe_assigned_flag) {
637  DCHECK_EQ(scope_type(), MODULE_SCOPE);
638  DCHECK(name->IsInternalizedString());
639  DCHECK_NOT_NULL(mode);
640  DCHECK_NOT_NULL(init_flag);
641  DCHECK_NOT_NULL(maybe_assigned_flag);
642
643  int module_vars_count = Smi::cast(get(ModuleVariableCountIndex()))->value();
644  int entry = ModuleVariablesIndex();
645  for (int i = 0; i < module_vars_count; ++i) {
646    if (*name == get(entry + kModuleVariableNameOffset)) {
647      int index;
648      ModuleVariable(i, nullptr, &index, mode, init_flag, maybe_assigned_flag);
649      return index;
650    }
651    entry += kModuleVariableEntryLength;
652  }
653
654  return 0;
655}
656
657int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
658                                Handle<String> name, VariableMode* mode,
659                                InitializationFlag* init_flag,
660                                MaybeAssignedFlag* maybe_assigned_flag) {
661  DCHECK(name->IsInternalizedString());
662  DCHECK_NOT_NULL(mode);
663  DCHECK_NOT_NULL(init_flag);
664  DCHECK_NOT_NULL(maybe_assigned_flag);
665
666  if (scope_info->length() > 0) {
667    ContextSlotCache* context_slot_cache =
668        scope_info->GetIsolate()->context_slot_cache();
669    int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag,
670                                            maybe_assigned_flag);
671    if (result != ContextSlotCache::kNotFound) {
672      DCHECK_LT(result, scope_info->ContextLength());
673      return result;
674    }
675
676    int start = scope_info->ContextLocalNamesIndex();
677    int end = start + scope_info->ContextLocalCount();
678    for (int i = start; i < end; ++i) {
679      if (*name == scope_info->get(i)) {
680        int var = i - start;
681        *mode = scope_info->ContextLocalMode(var);
682        *init_flag = scope_info->ContextLocalInitFlag(var);
683        *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
684        result = Context::MIN_CONTEXT_SLOTS + var;
685
686        context_slot_cache->Update(scope_info, name, *mode, *init_flag,
687                                   *maybe_assigned_flag, result);
688        DCHECK_LT(result, scope_info->ContextLength());
689        return result;
690      }
691    }
692    // Cache as not found. Mode, init flag and maybe assigned flag don't matter.
693    context_slot_cache->Update(scope_info, name, TEMPORARY,
694                               kNeedsInitialization, kNotAssigned, -1);
695  }
696
697  return -1;
698}
699
700String* ScopeInfo::ContextSlotName(int slot_index) {
701  int const var = slot_index - Context::MIN_CONTEXT_SLOTS;
702  DCHECK_LE(0, var);
703  DCHECK_LT(var, ContextLocalCount());
704  return ContextLocalName(var);
705}
706
707
708int ScopeInfo::ParameterIndex(String* name) {
709  DCHECK(name->IsInternalizedString());
710  if (length() > 0) {
711    // We must read parameters from the end since for
712    // multiply declared parameters the value of the
713    // last declaration of that parameter is used
714    // inside a function (and thus we need to look
715    // at the last index). Was bug# 1110337.
716    int start = ParameterNamesIndex();
717    int end = start + ParameterCount();
718    for (int i = end - 1; i >= start; --i) {
719      if (name == get(i)) {
720        return i - start;
721      }
722    }
723  }
724  return -1;
725}
726
727
728int ScopeInfo::ReceiverContextSlotIndex() {
729  if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT)
730    return Smi::cast(get(ReceiverInfoIndex()))->value();
731  return -1;
732}
733
734int ScopeInfo::FunctionContextSlotIndex(String* name) {
735  DCHECK(name->IsInternalizedString());
736  if (length() > 0) {
737    if (FunctionVariableField::decode(Flags()) == CONTEXT &&
738        FunctionName() == name) {
739      return Smi::cast(get(FunctionNameInfoIndex() + 1))->value();
740    }
741  }
742  return -1;
743}
744
745
746FunctionKind ScopeInfo::function_kind() {
747  return FunctionKindField::decode(Flags());
748}
749
750int ScopeInfo::ParameterNamesIndex() {
751  DCHECK_LT(0, length());
752  return kVariablePartIndex;
753}
754
755
756int ScopeInfo::StackLocalFirstSlotIndex() {
757  return ParameterNamesIndex() + ParameterCount();
758}
759
760int ScopeInfo::StackLocalNamesIndex() { return StackLocalFirstSlotIndex() + 1; }
761
762int ScopeInfo::ContextLocalNamesIndex() {
763  return StackLocalNamesIndex() + StackLocalCount();
764}
765
766int ScopeInfo::ContextLocalInfosIndex() {
767  return ContextLocalNamesIndex() + ContextLocalCount();
768}
769
770int ScopeInfo::ReceiverInfoIndex() {
771  return ContextLocalInfosIndex() + ContextLocalCount();
772}
773
774int ScopeInfo::FunctionNameInfoIndex() {
775  return ReceiverInfoIndex() + (HasAllocatedReceiver() ? 1 : 0);
776}
777
778int ScopeInfo::OuterScopeInfoIndex() {
779  return FunctionNameInfoIndex() + (HasFunctionName() ? 2 : 0);
780}
781
782int ScopeInfo::ModuleInfoIndex() {
783  return OuterScopeInfoIndex() + (HasOuterScopeInfo() ? 1 : 0);
784}
785
786int ScopeInfo::ModuleVariableCountIndex() { return ModuleInfoIndex() + 1; }
787
788int ScopeInfo::ModuleVariablesIndex() { return ModuleVariableCountIndex() + 1; }
789
790void ScopeInfo::ModuleVariable(int i, String** name, int* index,
791                               VariableMode* mode,
792                               InitializationFlag* init_flag,
793                               MaybeAssignedFlag* maybe_assigned_flag) {
794  DCHECK_LE(0, i);
795  DCHECK_LT(i, Smi::cast(get(ModuleVariableCountIndex()))->value());
796
797  int entry = ModuleVariablesIndex() + i * kModuleVariableEntryLength;
798  int properties =
799      Smi::cast(get(entry + kModuleVariablePropertiesOffset))->value();
800
801  if (name != nullptr) {
802    *name = String::cast(get(entry + kModuleVariableNameOffset));
803  }
804  if (index != nullptr) {
805    *index = Smi::cast(get(entry + kModuleVariableIndexOffset))->value();
806    DCHECK_NE(*index, 0);
807  }
808  if (mode != nullptr) {
809    *mode = VariableModeField::decode(properties);
810  }
811  if (init_flag != nullptr) {
812    *init_flag = InitFlagField::decode(properties);
813  }
814  if (maybe_assigned_flag != nullptr) {
815    *maybe_assigned_flag = MaybeAssignedFlagField::decode(properties);
816  }
817}
818
819#ifdef DEBUG
820
821static void PrintList(const char* list_name,
822                      int nof_internal_slots,
823                      int start,
824                      int end,
825                      ScopeInfo* scope_info) {
826  if (start < end) {
827    PrintF("\n  // %s\n", list_name);
828    if (nof_internal_slots > 0) {
829      PrintF("  %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
830    }
831    for (int i = nof_internal_slots; start < end; ++i, ++start) {
832      PrintF("  %2d ", i);
833      String::cast(scope_info->get(start))->ShortPrint();
834      PrintF("\n");
835    }
836  }
837}
838
839
840void ScopeInfo::Print() {
841  PrintF("ScopeInfo ");
842  if (HasFunctionName()) {
843    FunctionName()->ShortPrint();
844  } else {
845    PrintF("/* no function name */");
846  }
847  PrintF("{");
848
849  if (length() > 0) {
850    PrintList("parameters", 0, ParameterNamesIndex(),
851              ParameterNamesIndex() + ParameterCount(), this);
852    PrintList("stack slots", 0, StackLocalNamesIndex(),
853              StackLocalNamesIndex() + StackLocalCount(), this);
854    PrintList("context slots", Context::MIN_CONTEXT_SLOTS,
855              ContextLocalNamesIndex(),
856              ContextLocalNamesIndex() + ContextLocalCount(), this);
857    // TODO(neis): Print module stuff if present.
858  }
859
860  PrintF("}\n");
861}
862#endif  // DEBUG
863
864Handle<ModuleInfoEntry> ModuleInfoEntry::New(Isolate* isolate,
865                                             Handle<Object> export_name,
866                                             Handle<Object> local_name,
867                                             Handle<Object> import_name,
868                                             int module_request, int cell_index,
869                                             int beg_pos, int end_pos) {
870  Handle<ModuleInfoEntry> result = Handle<ModuleInfoEntry>::cast(
871      isolate->factory()->NewStruct(MODULE_INFO_ENTRY_TYPE));
872  result->set_export_name(*export_name);
873  result->set_local_name(*local_name);
874  result->set_import_name(*import_name);
875  result->set_module_request(module_request);
876  result->set_cell_index(cell_index);
877  result->set_beg_pos(beg_pos);
878  result->set_end_pos(end_pos);
879  return result;
880}
881
882Handle<ModuleInfo> ModuleInfo::New(Isolate* isolate, Zone* zone,
883                                   ModuleDescriptor* descr) {
884  // Serialize module requests.
885  Handle<FixedArray> module_requests = isolate->factory()->NewFixedArray(
886      static_cast<int>(descr->module_requests().size()));
887  for (const auto& elem : descr->module_requests()) {
888    module_requests->set(elem.second, *elem.first->string());
889  }
890
891  // Serialize special exports.
892  Handle<FixedArray> special_exports =
893      isolate->factory()->NewFixedArray(descr->special_exports().length());
894  {
895    int i = 0;
896    for (auto entry : descr->special_exports()) {
897      Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate);
898      special_exports->set(i++, *serialized_entry);
899    }
900  }
901
902  // Serialize namespace imports.
903  Handle<FixedArray> namespace_imports =
904      isolate->factory()->NewFixedArray(descr->namespace_imports().length());
905  {
906    int i = 0;
907    for (auto entry : descr->namespace_imports()) {
908      Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate);
909      namespace_imports->set(i++, *serialized_entry);
910    }
911  }
912
913  // Serialize regular exports.
914  Handle<FixedArray> regular_exports =
915      descr->SerializeRegularExports(isolate, zone);
916
917  // Serialize regular imports.
918  Handle<FixedArray> regular_imports = isolate->factory()->NewFixedArray(
919      static_cast<int>(descr->regular_imports().size()));
920  {
921    int i = 0;
922    for (const auto& elem : descr->regular_imports()) {
923      Handle<ModuleInfoEntry> serialized_entry =
924          elem.second->Serialize(isolate);
925      regular_imports->set(i++, *serialized_entry);
926    }
927  }
928
929  Handle<ModuleInfo> result = isolate->factory()->NewModuleInfo();
930  result->set(kModuleRequestsIndex, *module_requests);
931  result->set(kSpecialExportsIndex, *special_exports);
932  result->set(kRegularExportsIndex, *regular_exports);
933  result->set(kNamespaceImportsIndex, *namespace_imports);
934  result->set(kRegularImportsIndex, *regular_imports);
935  return result;
936}
937
938int ModuleInfo::RegularExportCount() const {
939  DCHECK_EQ(regular_exports()->length() % kRegularExportLength, 0);
940  return regular_exports()->length() / kRegularExportLength;
941}
942
943String* ModuleInfo::RegularExportLocalName(int i) const {
944  return String::cast(regular_exports()->get(i * kRegularExportLength +
945                                             kRegularExportLocalNameOffset));
946}
947
948int ModuleInfo::RegularExportCellIndex(int i) const {
949  return Smi::cast(regular_exports()->get(i * kRegularExportLength +
950                                          kRegularExportCellIndexOffset))
951      ->value();
952}
953
954FixedArray* ModuleInfo::RegularExportExportNames(int i) const {
955  return FixedArray::cast(regular_exports()->get(
956      i * kRegularExportLength + kRegularExportExportNamesOffset));
957}
958
959Handle<ModuleInfoEntry> ModuleInfo::LookupRegularImport(
960    Handle<ModuleInfo> info, Handle<String> local_name) {
961  Isolate* isolate = info->GetIsolate();
962  Handle<FixedArray> regular_imports(info->regular_imports(), isolate);
963  for (int i = 0, n = regular_imports->length(); i < n; ++i) {
964    Handle<ModuleInfoEntry> entry(
965        ModuleInfoEntry::cast(regular_imports->get(i)), isolate);
966    if (String::cast(entry->local_name())->Equals(*local_name)) {
967      return entry;
968    }
969  }
970  UNREACHABLE();
971  return Handle<ModuleInfoEntry>();
972}
973
974}  // namespace internal
975}  // namespace v8
976