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