+ Variable(const Identifier& ident, VarOffset offset, RegisterID* local, unsigned attributes, VariableKind kind)
+ : m_ident(ident)
+ , m_offset(offset)
+ , m_local(local)
+ , m_attributes(attributes)
+ , m_kind(kind)
+ {
+ }
+
+ // If it's unset, then it is a non-locally-scoped variable. If it is set, then it could be
+ // a stack variable, a scoped variable in the local scope, or a variable captured in the
+ // direct arguments object.
+ bool isResolved() const { return !!m_offset; }
+
+ const Identifier& ident() const { return m_ident; }
+
+ VarOffset offset() const { return m_offset; }
+ bool isLocal() const { return m_offset.isStack(); }
+ RegisterID* local() const { return m_local; }
+
+ bool isReadOnly() const { return m_attributes & ReadOnly; }
+ bool isSpecial() const { return m_kind != NormalVariable; }
+
+ private:
+ Identifier m_ident;
+ VarOffset m_offset;
+ RegisterID* m_local;
+ unsigned m_attributes;
+ VariableKind m_kind;
+ };
+
+ struct TryRange {
+ RefPtr<Label> start;
+ RefPtr<Label> end;
+ TryData* tryData;
+ };
+
+ enum ProfileTypeBytecodeFlag {
+ ProfileTypeBytecodePutToScope,
+ ProfileTypeBytecodeGetFromScope,
+ ProfileTypeBytecodePutToLocalScope,
+ ProfileTypeBytecodeGetFromLocalScope,
+ ProfileTypeBytecodeHasGlobalID,
+ ProfileTypeBytecodeDoesNotHaveGlobalID,
+ ProfileTypeBytecodeFunctionArgument,
+ ProfileTypeBytecodeFunctionReturnStatement
+ };
+
+ class BytecodeGenerator {
+ WTF_MAKE_FAST_ALLOCATED;
+ WTF_MAKE_NONCOPYABLE(BytecodeGenerator);
+ public:
+ typedef DeclarationStacks::VarStack VarStack;
+ typedef DeclarationStacks::FunctionStack FunctionStack;
+
+ BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, DebuggerMode, ProfilerMode);
+ BytecodeGenerator(VM&, FunctionNode*, UnlinkedFunctionCodeBlock*, DebuggerMode, ProfilerMode);
+ BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, DebuggerMode, ProfilerMode);
+
+ ~BytecodeGenerator();
+
+ VM* vm() const { return m_vm; }
+ ParserArena& parserArena() const { return m_scopeNode->parserArena(); }
+ const CommonIdentifiers& propertyNames() const { return *m_vm->propertyNames; }
+
+ bool isConstructor() const { return m_codeBlock->isConstructor(); }
+#if ENABLE(ES6_CLASS_SYNTAX)
+ ConstructorKind constructorKind() const { return m_codeBlock->constructorKind(); }
+#else
+ ConstructorKind constructorKind() const { return ConstructorKind::None; }
+#endif
+
+ ParserError generate();
+
+ bool isArgumentNumber(const Identifier&, int);
+
+ Variable variable(const Identifier&);
+
+ // Ignores the possibility of intervening scopes.
+ Variable variablePerSymbolTable(const Identifier&);
+
+ enum ExistingVariableMode { VerifyExisting, IgnoreExisting };
+ void createVariable(const Identifier&, VarKind, ConstantMode, ExistingVariableMode = VerifyExisting); // Creates the variable, or asserts that the already-created variable is sufficiently compatible.
+