blob: 23c3949895845a16946b83aad5004e2cae3e47f5 [file] [log] [blame]
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_OBJECTS_SCOPE_INFO_H_
#define V8_OBJECTS_SCOPE_INFO_H_
#include "src/common/globals.h"
#include "src/objects/fixed-array.h"
#include "src/objects/function-kind.h"
#include "src/objects/objects.h"
#include "src/utils/utils.h"
#include "testing/gtest/include/gtest/gtest_prod.h" // nogncheck
#include "torque-generated/bit-fields.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
template <typename T>
class Handle;
class Isolate;
template <typename T>
class MaybeHandle;
class SourceTextModuleInfo;
class Scope;
class StringSet;
class Zone;
// ScopeInfo represents information about different scopes of a source
// program and the allocation of the scope's variables. Scope information
// is stored in a compressed form in ScopeInfo objects and is used
// at runtime (stack dumps, deoptimization, etc.).
// This object provides quick access to scope info details for runtime
// routines.
class ScopeInfo : public FixedArray {
public:
DEFINE_TORQUE_GENERATED_SCOPE_FLAGS()
DECL_CAST(ScopeInfo)
DECL_PRINTER(ScopeInfo)
// Return the type of this scope.
ScopeType scope_type() const;
// Return the language mode of this scope.
LanguageMode language_mode() const;
// True if this scope is a (var) declaration scope.
bool is_declaration_scope() const;
// True if this scope is a class scope.
bool is_class_scope() const;
// Does this scope make a sloppy eval call?
bool SloppyEvalCanExtendVars() const;
// Return the number of context slots for code if a context is allocated. This
// number consists of three parts:
// 1. Size of header for every context.
// 2. One context slot per context allocated local.
// 3. One context slot for the function name if it is context allocated.
// Parameters allocated in the context count as context allocated locals. If
// no contexts are allocated for this scope ContextLength returns 0.
int ContextLength() const;
int ContextHeaderLength() const;
bool HasContextExtensionSlot() const;
// Does this scope declare a "this" binding?
bool HasReceiver() const;
// Does this scope declare a "this" binding, and the "this" binding is stack-
// or context-allocated?
bool HasAllocatedReceiver() const;
// Does this scope has class brand (for private methods)?
bool HasClassBrand() const;
// Does this scope contains a saved class variable context local slot index
// for checking receivers of static private methods?
bool HasSavedClassVariableIndex() const;
// Does this scope declare a "new.target" binding?
bool HasNewTarget() const;
// Is this scope the scope of a named function expression?
V8_EXPORT_PRIVATE bool HasFunctionName() const;
// See SharedFunctionInfo::HasSharedName.
V8_EXPORT_PRIVATE bool HasSharedFunctionName() const;
V8_EXPORT_PRIVATE bool HasInferredFunctionName() const;
void SetFunctionName(Object name);
void SetInferredFunctionName(String name);
// Does this scope belong to a function?
bool HasPositionInfo() const;
// Return if contexts are allocated for this scope.
bool HasContext() const;
// Return if this is a function scope with "use asm".
inline bool IsAsmModule() const;
inline bool HasSimpleParameters() const;
// Return the function_name if present.
V8_EXPORT_PRIVATE Object FunctionName() const;
// The function's name if it is non-empty, otherwise the inferred name or an
// empty string.
String FunctionDebugName() const;
// Return the function's inferred name if present.
// See SharedFunctionInfo::function_identifier.
V8_EXPORT_PRIVATE Object InferredFunctionName() const;
// Position information accessors.
int StartPosition() const;
int EndPosition() const;
void SetPositionInfo(int start, int end);
SourceTextModuleInfo ModuleDescriptorInfo() const;
// Return the name of the given context local.
String ContextLocalName(int var) const;
// Return the mode of the given context local.
VariableMode ContextLocalMode(int var) const;
// Return whether the given context local variable is static.
IsStaticFlag ContextLocalIsStaticFlag(int var) const;
// Return the initialization flag of the given context local.
InitializationFlag ContextLocalInitFlag(int var) const;
bool ContextLocalIsParameter(int var) const;
uint32_t ContextLocalParameterNumber(int var) const;
// Return the initialization flag of the given context local.
MaybeAssignedFlag ContextLocalMaybeAssignedFlag(int var) const;
// Return true if this local was introduced by the compiler, and should not be
// exposed to the user in a debugger.
static bool VariableIsSynthetic(String name);
// Lookup support for serialized scope info. Returns the local context slot
// index for a given slot name if the slot is present; otherwise
// returns a value < 0. The name must be an internalized string.
// If the slot is present and mode != nullptr, sets *mode to the corresponding
// mode for that variable.
static int ContextSlotIndex(ScopeInfo scope_info, String name,
VariableMode* mode, InitializationFlag* init_flag,
MaybeAssignedFlag* maybe_assigned_flag,
IsStaticFlag* is_static_flag);
// Lookup metadata of a MODULE-allocated variable. Return 0 if there is no
// module variable with the given name (the index value of a MODULE variable
// is never 0).
int ModuleIndex(String name, VariableMode* mode,
InitializationFlag* init_flag,
MaybeAssignedFlag* maybe_assigned_flag);
// Lookup support for serialized scope info. Returns the function context
// slot index if the function name is present and context-allocated (named
// function expressions, only), otherwise returns a value < 0. The name
// must be an internalized string.
int FunctionContextSlotIndex(String name) const;
// Lookup support for serialized scope info. Returns the receiver context
// slot index if scope has a "this" binding, and the binding is
// context-allocated. Otherwise returns a value < 0.
int ReceiverContextSlotIndex() const;
// Lookup support for serialized scope info. Returns the index of the
// saved class variable in context local slots if scope is a class scope
// and it contains static private methods that may be accessed.
// Otherwise returns a value < 0.
int SavedClassVariableContextLocalIndex() const;
FunctionKind function_kind() const;
// Returns true if this ScopeInfo is linked to a outer ScopeInfo.
bool HasOuterScopeInfo() const;
// Returns true if this ScopeInfo was created for a debug-evaluate scope.
bool IsDebugEvaluateScope() const;
// Can be used to mark a ScopeInfo that looks like a with-scope as actually
// being a debug-evaluate scope.
void SetIsDebugEvaluateScope();
// Return the outer ScopeInfo if present.
ScopeInfo OuterScopeInfo() const;
bool is_script_scope() const;
// Returns true if this ScopeInfo has a blocklist attached containing stack
// allocated local variables.
V8_EXPORT_PRIVATE bool HasLocalsBlockList() const;
// Returns a list of stack-allocated locals of parent scopes.
// Used during local debug-evalute to decide whether a context lookup
// can continue upwards after checking this scope.
V8_EXPORT_PRIVATE StringSet LocalsBlockList() const;
// Returns true if this ScopeInfo was created for a scope that skips the
// closest outer class when resolving private names.
bool PrivateNameLookupSkipsOuterClass() const;
// REPL mode scopes allow re-declaraction of let variables. They come from
// debug evaluate but are different to IsDebugEvaluateScope().
bool IsReplModeScope() const;
#ifdef DEBUG
bool Equals(ScopeInfo other) const;
#endif
template <typename LocalIsolate>
static Handle<ScopeInfo> Create(LocalIsolate* isolate, Zone* zone,
Scope* scope,
MaybeHandle<ScopeInfo> outer_scope);
static Handle<ScopeInfo> CreateForWithScope(
Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope);
V8_EXPORT_PRIVATE static Handle<ScopeInfo> CreateForEmptyFunction(
Isolate* isolate);
static Handle<ScopeInfo> CreateForNativeContext(Isolate* isolate);
static Handle<ScopeInfo> CreateGlobalThisBinding(Isolate* isolate);
// Creates a copy of a {ScopeInfo} but with the provided locals blocklist
// attached. Does nothing if the original {ScopeInfo} already has a field
// for a blocklist reserved.
V8_EXPORT_PRIVATE static Handle<ScopeInfo> RecreateWithBlockList(
Isolate* isolate, Handle<ScopeInfo> original,
Handle<StringSet> blocklist);
// Serializes empty scope info.
V8_EXPORT_PRIVATE static ScopeInfo Empty(Isolate* isolate);
// The layout of the static part of a ScopeInfo is as follows. Each entry is
// numeric and occupies one array slot.
// 1. A set of properties of the scope.
// 2. The number of parameters. For non-function scopes this is 0.
// 3. The number of non-parameter and parameter variables allocated in the
// context.
#define FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(V) \
V(Flags) \
V(ParameterCount) \
V(ContextLocalCount)
#define FIELD_ACCESSORS(name) \
inline void Set##name(int value); \
inline int name() const;
FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)
#undef FIELD_ACCESSORS
enum Fields {
#define DECL_INDEX(name) k##name,
FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(DECL_INDEX)
#undef DECL_INDEX
kVariablePartIndex
};
static const int kFlagsOffset = OffsetOfElementAt(Fields::kFlags);
STATIC_ASSERT(LanguageModeSize == 1 << LanguageModeBit::kSize);
STATIC_ASSERT(kLastFunctionKind <= FunctionKindBits::kMax);
private:
// The layout of the variable part of a ScopeInfo is as follows:
// 1. ContextLocalNames:
// Contains the names of local variables and parameters that are allocated
// in the context. They are stored in increasing order of the context slot
// index starting with Context::MIN_CONTEXT_SLOTS. One slot is used per
// context local, so in total this part occupies ContextLocalCount() slots
// in the array.
// 2. ContextLocalInfos:
// Contains the variable modes and initialization flags corresponding to
// the context locals in ContextLocalNames. One slot is used per
// context local, so in total this part occupies ContextLocalCount()
// slots in the array.
// 3. SavedClassVariableInfo:
// If the scope is a class scope and it has static private methods that
// may be accessed directly or through eval, one slot is reserved to hold
// the context slot index for the class variable.
// 4. ReceiverInfo:
// If the scope binds a "this" value, one slot is reserved to hold the
// context or stack slot index for the variable.
// 5. FunctionNameInfo:
// If the scope belongs to a named function expression this part contains
// information about the function variable. It always occupies two array
// slots: a. The name of the function variable.
// b. The context or stack slot index for the variable.
// 6. InferredFunctionName:
// Contains the function's inferred name.
// 7. SourcePosition:
// Contains two slots with a) the startPosition and b) the endPosition if
// the scope belongs to a function or script.
// 8. OuterScopeInfoIndex:
// The outer scope's ScopeInfo or the hole if there's none.
// 9. LocalsBlockList: List of stack allocated local variables. Used by
// debug evaluate to properly abort variable lookup when a name clashes
// with a stack allocated local that can't be materialized.
// 10. SourceTextModuleInfo, ModuleVariableCount, and ModuleVariables:
// For a module scope, this part contains the SourceTextModuleInfo, the
// number of MODULE-allocated variables, and the metadata of those
// variables. For non-module scopes it is empty.
int ContextLocalNamesIndex() const;
int ContextLocalInfosIndex() const;
int SavedClassVariableInfoIndex() const;
int ReceiverInfoIndex() const;
int FunctionNameInfoIndex() const;
int InferredFunctionNameIndex() const;
int PositionInfoIndex() const;
int OuterScopeInfoIndex() const;
V8_EXPORT_PRIVATE int LocalsBlockListIndex() const;
int ModuleInfoIndex() const;
int ModuleVariableCountIndex() const;
int ModuleVariablesIndex() const;
static bool NeedsPositionInfo(ScopeType type);
enum class BootstrappingType { kScript, kFunction, kNative };
static Handle<ScopeInfo> CreateForBootstrapping(Isolate* isolate,
BootstrappingType type);
int Lookup(Handle<String> name, int start, int end, VariableMode* mode,
VariableLocation* location, InitializationFlag* init_flag,
MaybeAssignedFlag* maybe_assigned_flag);
// Get metadata of i-th MODULE-allocated variable, where 0 <= i <
// ModuleVariableCount. The metadata is returned via out-arguments, which may
// be nullptr if the corresponding information is not requested
void ModuleVariable(int i, String* name, int* index,
VariableMode* mode = nullptr,
InitializationFlag* init_flag = nullptr,
MaybeAssignedFlag* maybe_assigned_flag = nullptr);
static const int kFunctionNameEntries = 2;
static const int kPositionInfoEntries = 2;
// Properties of variables.
using VariableModeField = base::BitField<VariableMode, 0, 4>;
using InitFlagField = VariableModeField::Next<InitializationFlag, 1>;
using MaybeAssignedFlagField = InitFlagField::Next<MaybeAssignedFlag, 1>;
using ParameterNumberField = MaybeAssignedFlagField::Next<uint32_t, 16>;
using IsStaticFlagField = ParameterNumberField::Next<IsStaticFlag, 1>;
friend class ScopeIterator;
friend std::ostream& operator<<(std::ostream& os, VariableAllocationInfo var);
OBJECT_CONSTRUCTORS(ScopeInfo, FixedArray);
FRIEND_TEST(TestWithNativeContext, RecreateScopeInfoWithLocalsBlocklistWorks);
};
std::ostream& operator<<(std::ostream& os, VariableAllocationInfo var);
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_SCOPE_INFO_H_