// 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/globals.h" #include "src/objects.h" #include "src/utils.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 Scope; 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: DECLARE_CAST(ScopeInfo) // Return the type of this scope. ScopeType scope_type(); // Does this scope call eval? bool CallsEval(); // Return the language mode of this scope. LanguageMode language_mode(); // True if this scope is a (var) declaration scope. bool is_declaration_scope(); // Does this scope make a sloppy eval call? bool CallsSloppyEval() { return CallsEval() && is_sloppy(language_mode()); } // Return the total number of locals allocated on the stack and in the // context. This includes the parameters that are allocated in the context. int LocalCount(); // Return the number of stack slots for code. This number consists of two // parts: // 1. One stack slot per stack allocated local. // 2. One stack slot for the function name if it is stack allocated. int StackSlotCount(); // Return the number of context slots for code if a context is allocated. This // number consists of three parts: // 1. Size of fixed header for every context: Context::MIN_CONTEXT_SLOTS // 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(); // Does this scope declare a "this" binding? bool HasReceiver(); // Does this scope declare a "this" binding, and the "this" binding is stack- // or context-allocated? bool HasAllocatedReceiver(); // Does this scope declare a "new.target" binding? bool HasNewTarget(); // Is this scope the scope of a named function expression? bool HasFunctionName(); // Return if this has context allocated locals. bool HasHeapAllocatedLocals(); // Return if contexts are allocated for this scope. bool HasContext(); // Return if this is a function scope with "use asm". inline bool IsAsmModule() { return AsmModuleField::decode(Flags()); } // Return if this is a nested function within an asm module scope. inline bool IsAsmFunction() { return AsmFunctionField::decode(Flags()); } inline bool HasSimpleParameters() { return HasSimpleParametersField::decode(Flags()); } // Return the function_name if present. String* FunctionName(); ModuleInfo* ModuleDescriptorInfo(); // Return the name of the given parameter. String* ParameterName(int var); // Return the name of the given local. String* LocalName(int var); // Return the name of the given stack local. String* StackLocalName(int var); // Return the name of the given stack local. int StackLocalIndex(int var); // Return the name of the given context local. String* ContextLocalName(int var); // Return the mode of the given context local. VariableMode ContextLocalMode(int var); // Return the initialization flag of the given context local. InitializationFlag ContextLocalInitFlag(int var); // Return the initialization flag of the given context local. MaybeAssignedFlag ContextLocalMaybeAssignedFlag(int var); // 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 // the stack slot index for a given slot name if the slot is // present; otherwise returns a value < 0. The name must be an internalized // string. int StackSlotIndex(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 != NULL, sets *mode to the corresponding // mode for that variable. static int ContextSlotIndex(Handle<ScopeInfo> scope_info, Handle<String> name, VariableMode* mode, InitializationFlag* init_flag, MaybeAssignedFlag* maybe_assigned_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(Handle<String> name, VariableMode* mode, InitializationFlag* init_flag, MaybeAssignedFlag* maybe_assigned_flag); // Lookup the name of a certain context slot by its index. String* ContextSlotName(int slot_index); // Lookup support for serialized scope info. Returns the // parameter index for a given parameter name if the parameter is present; // otherwise returns a value < 0. The name must be an internalized string. int ParameterIndex(String* name); // 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); // 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(); FunctionKind function_kind(); // Returns true if this ScopeInfo is linked to a outer ScopeInfo. bool HasOuterScopeInfo(); // Returns true if this ScopeInfo was created for a debug-evaluate scope. bool IsDebugEvaluateScope(); // 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(); #ifdef DEBUG bool Equals(ScopeInfo* other) const; #endif static Handle<ScopeInfo> Create(Isolate* isolate, Zone* zone, Scope* scope, MaybeHandle<ScopeInfo> outer_scope); static Handle<ScopeInfo> CreateForWithScope( Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope); static Handle<ScopeInfo> CreateGlobalThisBinding(Isolate* isolate); // Serializes empty scope info. V8_EXPORT_PRIVATE static ScopeInfo* Empty(Isolate* isolate); #ifdef DEBUG void Print(); #endif // 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 variables allocated on the stack. // 4. 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(StackLocalCount) \ V(ContextLocalCount) #define FIELD_ACCESSORS(name) \ inline void Set##name(int value) { set(k##name, Smi::FromInt(value)); } \ inline int name() { \ if (length() > 0) { \ return Smi::cast(get(k##name))->value(); \ } else { \ return 0; \ } \ } FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS) #undef FIELD_ACCESSORS enum { #define DECL_INDEX(name) k##name, FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(DECL_INDEX) #undef DECL_INDEX kVariablePartIndex }; private: // The layout of the variable part of a ScopeInfo is as follows: // 1. ParameterNames: // This part stores the names of the parameters for function scopes. One // slot is used per parameter, so in total this part occupies // ParameterCount() slots in the array. For other scopes than function // scopes ParameterCount() is 0. // 2. StackLocalFirstSlot: // Index of a first stack slot for stack local. Stack locals belonging to // this scope are located on a stack at slots starting from this index. // 3. StackLocalNames: // Contains the names of local variables that are allocated on the stack, // in increasing order of the stack slot index. First local variable has a // stack slot index defined in StackLocalFirstSlot (point 2 above). // One slot is used per stack local, so in total this part occupies // StackLocalCount() slots in the array. // 4. 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. // 5. 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. // 6. ReceiverInfo: // If the scope binds a "this" value, one slot is reserved to hold the // context or stack slot index for the variable. // 7. 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. // 8. OuterScopeInfoIndex: // The outer scope's ScopeInfo or the hole if there's none. // 9. ModuleInfo, ModuleVariableCount, and ModuleVariables: // For a module scope, this part contains the ModuleInfo, the number of // MODULE-allocated variables, and the metadata of those variables. For // non-module scopes it is empty. int ParameterNamesIndex(); int StackLocalFirstSlotIndex(); int StackLocalNamesIndex(); int ContextLocalNamesIndex(); int ContextLocalInfosIndex(); int ReceiverInfoIndex(); int FunctionNameInfoIndex(); int OuterScopeInfoIndex(); int ModuleInfoIndex(); int ModuleVariableCountIndex(); int ModuleVariablesIndex(); 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); // Used for the function name variable for named function expressions, and for // the receiver. enum VariableAllocationInfo { NONE, STACK, CONTEXT, UNUSED }; // Properties of scopes. class ScopeTypeField : public BitField<ScopeType, 0, 4> {}; class CallsEvalField : public BitField<bool, ScopeTypeField::kNext, 1> {}; STATIC_ASSERT(LANGUAGE_END == 2); class LanguageModeField : public BitField<LanguageMode, CallsEvalField::kNext, 1> {}; class DeclarationScopeField : public BitField<bool, LanguageModeField::kNext, 1> {}; class ReceiverVariableField : public BitField<VariableAllocationInfo, DeclarationScopeField::kNext, 2> {}; class HasNewTargetField : public BitField<bool, ReceiverVariableField::kNext, 1> {}; class FunctionVariableField : public BitField<VariableAllocationInfo, HasNewTargetField::kNext, 2> {}; class AsmModuleField : public BitField<bool, FunctionVariableField::kNext, 1> {}; class AsmFunctionField : public BitField<bool, AsmModuleField::kNext, 1> {}; class HasSimpleParametersField : public BitField<bool, AsmFunctionField::kNext, 1> {}; class FunctionKindField : public BitField<FunctionKind, HasSimpleParametersField::kNext, 10> {}; class HasOuterScopeInfoField : public BitField<bool, FunctionKindField::kNext, 1> {}; class IsDebugEvaluateScopeField : public BitField<bool, HasOuterScopeInfoField::kNext, 1> {}; // Properties of variables. class VariableModeField : public BitField<VariableMode, 0, 3> {}; class InitFlagField : public BitField<InitializationFlag, 3, 1> {}; class MaybeAssignedFlagField : public BitField<MaybeAssignedFlag, 4, 1> {}; friend class ScopeIterator; }; } // namespace internal } // namespace v8 #include "src/objects/object-macros-undef.h" #endif // V8_OBJECTS_SCOPE_INFO_H_