text: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
   * vim: set ts=8 sts=4 et sw=4 tw=99:
   * This Source Code Form is subject to the terms of the Mozilla Public
   * License, v. 2.0. If a copy of the MPL was not distributed with this
   * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  
  #ifndef jit_BaselineCompiler_h
  #define jit_BaselineCompiler_h
  
  #include "jit/FixedList.h"
  #if defined(JS_CODEGEN_X86)
  # include "jit/x86/BaselineCompiler-x86.h"
  #elif defined(JS_CODEGEN_X64)
  # include "jit/x64/BaselineCompiler-x64.h"
  #elif defined(JS_CODEGEN_ARM)
  # include "jit/arm/BaselineCompiler-arm.h"
  #elif defined(JS_CODEGEN_ARM64)
  # include "jit/arm64/BaselineCompiler-arm64.h"
  #elif defined(JS_CODEGEN_MIPS32)
  # include "jit/mips32/BaselineCompiler-mips32.h"
  #elif defined(JS_CODEGEN_MIPS64)
  # include "jit/mips64/BaselineCompiler-mips64.h"
  #elif defined(JS_CODEGEN_NONE)
  # include "jit/none/BaselineCompiler-none.h"
  #else
  # error "Unknown architecture!"
  #endif
  
  namespace js {
  namespace jit {
  
  #define OPCODE_LIST(_)         \
      _(JSOP_NOP)                \
      _(JSOP_LABEL)              \
      _(JSOP_POP)                \
      _(JSOP_POPN)               \
      _(JSOP_DUPAT)              \
      _(JSOP_ENTERWITH)          \
      _(JSOP_LEAVEWITH)          \
      _(JSOP_DUP)                \
      _(JSOP_DUP2)               \
      _(JSOP_SWAP)               \
      _(JSOP_PICK)               \
      _(JSOP_GOTO)               \
      _(JSOP_IFEQ)               \
      _(JSOP_IFNE)               \
      _(JSOP_AND)                \
      _(JSOP_OR)                 \
      _(JSOP_NOT)                \
      _(JSOP_POS)                \
      _(JSOP_LOOPHEAD)           \
      _(JSOP_LOOPENTRY)          \
      _(JSOP_VOID)               \
      _(JSOP_UNDEFINED)          \
      _(JSOP_HOLE)               \
      _(JSOP_NULL)               \
      _(JSOP_TRUE)               \
      _(JSOP_FALSE)              \
      _(JSOP_ZERO)               \
      _(JSOP_ONE)                \
      _(JSOP_INT8)               \
      _(JSOP_INT32)              \
      _(JSOP_UINT16)             \
      _(JSOP_UINT24)             \
      _(JSOP_DOUBLE)             \
      _(JSOP_STRING)             \
      _(JSOP_SYMBOL)             \
      _(JSOP_OBJECT)             \
      _(JSOP_CALLSITEOBJ)        \
      _(JSOP_REGEXP)             \
      _(JSOP_LAMBDA)             \
      _(JSOP_LAMBDA_ARROW)       \
      _(JSOP_BITOR)              \
      _(JSOP_BITXOR)             \
      _(JSOP_BITAND)             \
      _(JSOP_LSH)                \
      _(JSOP_RSH)                \
      _(JSOP_URSH)               \
      _(JSOP_ADD)                \
      _(JSOP_SUB)                \
      _(JSOP_MUL)                \
      _(JSOP_DIV)                \
      _(JSOP_MOD)                \
      _(JSOP_POW)                \
      _(JSOP_LT)                 \
      _(JSOP_LE)                 \
      _(JSOP_GT)                 \
      _(JSOP_GE)                 \
      _(JSOP_EQ)                 \
      _(JSOP_NE)                 \
      _(JSOP_STRICTEQ)           \
      _(JSOP_STRICTNE)           \
      _(JSOP_CONDSWITCH)         \
      _(JSOP_CASE)               \
      _(JSOP_DEFAULT)            \
      _(JSOP_LINENO)             \
      _(JSOP_BITNOT)             \
      _(JSOP_NEG)                \
      _(JSOP_NEWARRAY)           \
      _(JSOP_SPREADCALLARRAY)    \
      _(JSOP_NEWARRAY_COPYONWRITE) \
      _(JSOP_INITELEM_ARRAY)     \
      _(JSOP_NEWOBJECT)          \
      _(JSOP_NEWINIT)            \
      _(JSOP_INITELEM)           \
      _(JSOP_INITELEM_GETTER)    \
      _(JSOP_INITELEM_SETTER)    \
      _(JSOP_INITELEM_INC)       \
      _(JSOP_MUTATEPROTO)        \
      _(JSOP_INITPROP)           \
      _(JSOP_INITLOCKEDPROP)     \
      _(JSOP_INITHIDDENPROP)     \
      _(JSOP_INITPROP_GETTER)    \
      _(JSOP_INITPROP_SETTER)    \
      _(JSOP_ARRAYPUSH)          \
      _(JSOP_GETELEM)            \
      _(JSOP_SETELEM)            \
      _(JSOP_STRICTSETELEM)      \
      _(JSOP_CALLELEM)           \
      _(JSOP_DELELEM)            \
      _(JSOP_STRICTDELELEM)      \
      _(JSOP_IN)                 \
      _(JSOP_GETGNAME)           \
      _(JSOP_BINDGNAME)          \
      _(JSOP_SETGNAME)           \
      _(JSOP_STRICTSETGNAME)     \
      _(JSOP_SETNAME)            \
      _(JSOP_STRICTSETNAME)      \
      _(JSOP_GETPROP)            \
      _(JSOP_SETPROP)            \
      _(JSOP_STRICTSETPROP)      \
      _(JSOP_CALLPROP)           \
      _(JSOP_DELPROP)            \
      _(JSOP_STRICTDELPROP)      \
      _(JSOP_LENGTH)             \
      _(JSOP_GETXPROP)           \
      _(JSOP_GETALIASEDVAR)      \
      _(JSOP_SETALIASEDVAR)      \
      _(JSOP_GETNAME)            \
      _(JSOP_BINDNAME)           \
      _(JSOP_DELNAME)            \
      _(JSOP_GETIMPORT)          \
      _(JSOP_GETINTRINSIC)       \
      _(JSOP_DEFVAR)             \
      _(JSOP_DEFCONST)           \
      _(JSOP_DEFLET)             \
      _(JSOP_DEFFUN)             \
      _(JSOP_GETLOCAL)           \
      _(JSOP_SETLOCAL)           \
      _(JSOP_GETARG)             \
      _(JSOP_SETARG)             \
      _(JSOP_CHECKLEXICAL)       \
      _(JSOP_INITLEXICAL)        \
      _(JSOP_INITGLEXICAL)       \
      _(JSOP_CHECKALIASEDLEXICAL) \
      _(JSOP_INITALIASEDLEXICAL) \
      _(JSOP_UNINITIALIZED)      \
      _(JSOP_CALL)               \
      _(JSOP_CALLITER)           \
      _(JSOP_FUNCALL)            \
      _(JSOP_FUNAPPLY)           \
      _(JSOP_NEW)                \
      _(JSOP_EVAL)               \
      _(JSOP_STRICTEVAL)         \
      _(JSOP_SPREADCALL)         \
      _(JSOP_SPREADNEW)          \
      _(JSOP_SPREADEVAL)         \
      _(JSOP_STRICTSPREADEVAL)   \
      _(JSOP_IMPLICITTHIS)       \
      _(JSOP_GIMPLICITTHIS)      \
      _(JSOP_INSTANCEOF)         \
      _(JSOP_TYPEOF)             \
      _(JSOP_TYPEOFEXPR)         \
      _(JSOP_THROWMSG)           \
      _(JSOP_THROW)              \
      _(JSOP_THROWING)           \
      _(JSOP_TRY)                \
      _(JSOP_FINALLY)            \
      _(JSOP_GOSUB)              \
      _(JSOP_RETSUB)             \
      _(JSOP_PUSHBLOCKSCOPE)     \
      _(JSOP_POPBLOCKSCOPE)      \
      _(JSOP_FRESHENBLOCKSCOPE)  \
      _(JSOP_DEBUGLEAVEBLOCK)    \
      _(JSOP_EXCEPTION)          \
      _(JSOP_DEBUGGER)           \
      _(JSOP_ARGUMENTS)          \
      _(JSOP_RUNONCE)            \
      _(JSOP_REST)               \
      _(JSOP_TOID)               \
      _(JSOP_TOSTRING)           \
      _(JSOP_TABLESWITCH)        \
      _(JSOP_ITER)               \
      _(JSOP_MOREITER)           \
      _(JSOP_ISNOITER)           \
      _(JSOP_ENDITER)            \
      _(JSOP_GENERATOR)          \
      _(JSOP_INITIALYIELD)       \
      _(JSOP_YIELD)              \
      _(JSOP_DEBUGAFTERYIELD)    \
      _(JSOP_FINALYIELDRVAL)     \
      _(JSOP_RESUME)             \
      _(JSOP_CALLEE)             \
      _(JSOP_GETRVAL)            \
      _(JSOP_SETRVAL)            \
      _(JSOP_RETRVAL)            \
      _(JSOP_RETURN)             \
      _(JSOP_FUNCTIONTHIS)       \
      _(JSOP_GLOBALTHIS)         \
      _(JSOP_CHECKTHIS)          \
      _(JSOP_CHECKRETURN)        \
      _(JSOP_NEWTARGET)          \
      _(JSOP_SUPERCALL)          \
      _(JSOP_SPREADSUPERCALL)    \
      _(JSOP_THROWSETCONST)      \
      _(JSOP_THROWSETALIASEDCONST) \
      _(JSOP_INITHIDDENPROP_GETTER) \
      _(JSOP_INITHIDDENPROP_SETTER) \
      _(JSOP_INITHIDDENELEM)     \
      _(JSOP_INITHIDDENELEM_GETTER) \
      _(JSOP_INITHIDDENELEM_SETTER) \
      _(JSOP_CHECKOBJCOERCIBLE)
  
  class BaselineCompiler : public BaselineCompilerSpecific
  {
      FixedList<Label>            labels_;
      NonAssertingLabel           return_;
      NonAssertingLabel           postBarrierSlot_;
  
      // Native code offset right before the scope chain is initialized.
      CodeOffset prologueOffset_;
  
      // Native code offset right before the frame is popped and the method
      // returned from.
      CodeOffset epilogueOffset_;
  
      // Native code offset right after debug prologue and epilogue, or
      // equivalent positions when debug mode is off.
      CodeOffset postDebugPrologueOffset_;
  
      // For each INITIALYIELD or YIELD op, this Vector maps the yield index
      // to the bytecode offset of the next op.
      Vector<uint32_t>            yieldOffsets_;
  
      // Whether any on stack arguments are modified.
      bool modifiesArguments_;
  
      Label* labelOf(jsbytecode* pc) {
          return &labels_[script->pcToOffset(pc)];
      }
  
      // If a script has more |nslots| than this, then emit code to do an
      // early stack check.
      static const unsigned EARLY_STACK_CHECK_SLOT_COUNT = 128;
      bool needsEarlyStackCheck() const {
          return script->nslots() > EARLY_STACK_CHECK_SLOT_COUNT;
      }
  
    public:
      BaselineCompiler(JSContext* cx, TempAllocator& alloc, JSScript* script);
      bool init();
  
      MethodStatus compile();
  
    private:
      MethodStatus emitBody();
  
      bool emitCheckThis(ValueOperand val);
      void emitLoadReturnValue(ValueOperand val);
  
      void emitInitializeLocals(size_t n, const Value& v);
      bool emitPrologue();
      bool emitEpilogue();
      bool emitOutOfLinePostBarrierSlot();
      bool emitIC(ICStub* stub, ICEntry::Kind kind);
      bool emitOpIC(ICStub* stub) {
          return emitIC(stub, ICEntry::Kind_Op);
      }
      bool emitNonOpIC(ICStub* stub) {
          return emitIC(stub, ICEntry::Kind_NonOp);
      }
  
      bool emitStackCheck(bool earlyCheck=false);
      bool emitInterruptCheck();
      bool emitWarmUpCounterIncrement(bool allowOsr=true);
      bool emitArgumentTypeChecks();
      void emitIsDebuggeeCheck();
      bool emitDebugPrologue();
      bool emitDebugTrap();
      void emitCoverage(jsbytecode* pc);
      bool emitTraceLoggerEnter();
      bool emitTraceLoggerExit();
  
      void emitProfilerEnterFrame();
      void emitProfilerExitFrame();
  
      bool initScopeChain();
  
      void storeValue(const StackValue* source, const Address& dest,
                      const ValueOperand& scratch);
  
  #define EMIT_OP(op) bool emit_##op();
      OPCODE_LIST(EMIT_OP)
  #undef EMIT_OP
  
      // JSOP_NEG, JSOP_BITNOT
      bool emitUnaryArith();
  
      // JSOP_BITXOR, JSOP_LSH, JSOP_ADD etc.
      bool emitBinaryArith();
  
      // Handles JSOP_LT, JSOP_GT, and friends
      bool emitCompare();
  
      bool emitReturn();
  
      bool emitToBoolean();
      bool emitTest(bool branchIfTrue);
      bool emitAndOr(bool branchIfTrue);
      bool emitCall();
      bool emitSpreadCall();
  
      bool emitInitPropGetterSetter();
      bool emitInitElemGetterSetter();
  
      bool emitFormalArgAccess(uint32_t arg, bool get);
  
      bool emitThrowConstAssignment();
      bool emitUninitializedLexicalCheck(const ValueOperand& val);
  
      bool addPCMappingEntry(bool addIndexEntry);
  
      bool addYieldOffset();
  
      void getScopeCoordinateObject(Register reg);
      Address getScopeCoordinateAddressFromObject(Register objReg, Register reg);
      Address getScopeCoordinateAddress(Register reg);
  };
  
  extern const VMFunction NewArrayCopyOnWriteInfo;
  
  } // namespace jit
  } // namespace js
  
  #endif /* jit_BaselineCompiler_h */
  