+ struct TryData {
+ RefPtr<Label> target;
+ unsigned targetScopeDepth;
+ };
+
+ struct TryContext {
+ RefPtr<Label> start;
+ TryData* tryData;
+ };
+
+ struct TryRange {
+ RefPtr<Label> start;
+ RefPtr<Label> end;
+ TryData* tryData;
+ };
+
+ class ResolveResult {
+ public:
+ enum Flags {
+ // The property is locally bound, in a register.
+ RegisterFlag = 0x1,
+ // We need to traverse the scope chain at runtime, checking for
+ // non-strict eval and/or `with' nodes.
+ DynamicFlag = 0x2,
+ // The resolved binding is immutable.
+ ReadOnlyFlag = 0x4,
+ // The property has a static location
+ StaticFlag = 0x8,
+ // Entry at scope distance "m_depth" and located at "m_index"
+ ScopedFlag = 0x10
+ };
+
+ enum Type {
+ // The property is local, and stored in a register.
+ Register = RegisterFlag | StaticFlag,
+ // A read-only local, created by "const".
+ ReadOnlyRegister = RegisterFlag | ReadOnlyFlag | StaticFlag,
+ // Lexically fixed location in the scope chain
+ Lexical = ScopedFlag | StaticFlag,
+ // A read-only Lexical, created by "const".
+ ReadOnlyLexical = ScopedFlag | ReadOnlyFlag | StaticFlag,
+ // Any other form of lookup
+ Dynamic = DynamicFlag,
+ };
+
+ static ResolveResult registerResolve(RegisterID *local, unsigned flags)
+ {
+ return ResolveResult(Register | flags, local);
+ }
+ static ResolveResult dynamicResolve()
+ {
+ return ResolveResult(Dynamic, 0);
+ }
+ static ResolveResult lexicalResolve(int index, size_t depth, unsigned flags)
+ {
+ if (flags & DynamicFlag)
+ return dynamicResolve();
+ return ResolveResult(Lexical | flags, index, depth);
+ }
+ unsigned type() const { return m_type; }
+
+ // Returns the register corresponding to a local variable, or 0 if no
+ // such register exists. Registers returned by ResolveResult::local() do
+ // not require explicit reference counting.
+ RegisterID* local() const { return m_local; }
+
+ bool isRegister() const { return m_type & RegisterFlag; }
+ bool isStatic() const { return (m_type & StaticFlag) && !isDynamic(); }
+ bool isDynamic() const { return m_type & DynamicFlag; }
+ bool isReadOnly() const { return (m_type & ReadOnlyFlag) && !isDynamic(); }
+
+ unsigned depth() const { ASSERT(isStatic()); return m_depth; }
+ int32_t index() const { ASSERT(isStatic()); return m_index; }
+
+ private:
+ ResolveResult(unsigned type, RegisterID* local)
+ : m_type(type)
+ , m_local(local)
+ , m_index(0)
+ , m_depth(0)
+ {
+#ifndef NDEBUG
+ checkValidity();
+#endif
+ }
+
+ ResolveResult(unsigned type, int index, unsigned depth)
+ : m_type(type)
+ , m_local(0)
+ , m_index(index)
+ , m_depth(depth)
+ {
+#ifndef NDEBUG
+ checkValidity();
+#endif
+ }
+
+#ifndef NDEBUG
+ void checkValidity();
+#endif
+
+ unsigned m_type;
+ RegisterID* m_local; // Local register, if RegisterFlag is set
+ int m_index;
+ unsigned m_depth;
+ };
+
+ struct NonlocalResolveInfo {
+ friend class BytecodeGenerator;
+ NonlocalResolveInfo()
+ : m_state(Unused)
+ {
+ }
+ ~NonlocalResolveInfo()
+ {
+ ASSERT(m_state == Put);
+ }
+ private:
+ void resolved(uint32_t putToBaseIndex)
+ {
+ ASSERT(putToBaseIndex);
+ ASSERT(m_state == Unused);
+ m_state = Resolved;
+ m_putToBaseIndex = putToBaseIndex;
+ }
+ uint32_t put()
+ {
+ ASSERT(m_state == Resolved);
+ m_state = Put;
+ return m_putToBaseIndex;
+ }
+ enum State { Unused, Resolved, Put };
+ State m_state;
+ uint32_t m_putToBaseIndex;
+ };
+
+ class BytecodeGenerator {
+ WTF_MAKE_FAST_ALLOCATED;