sqvm.h 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /* see copyright notice in squirrel.h */
  2. #ifndef _SQVM_H_
  3. #define _SQVM_H_
  4. #ifdef PROFILE_SQVM
  5. #include "HighResolutionTimer.h"
  6. #endif
  7. #include "sqopcodes.h"
  8. #include "sqobject.h"
  9. #define MAX_NATIVE_CALLS 100
  10. #define MIN_STACK_OVERHEAD 15
  11. #define SQ_SUSPEND_FLAG -666
  12. #define SQ_TAILCALL_FLAG -777
  13. #define DONT_FALL_BACK 666
  14. //#define EXISTS_FALL_BACK -1
  15. #define GET_FLAG_RAW 0x00000001
  16. #define GET_FLAG_DO_NOT_RAISE_ERROR 0x00000002
  17. //base lib
  18. void sq_base_register(HSQUIRRELVM v);
  19. struct SQExceptionTrap{
  20. SQExceptionTrap() {}
  21. SQExceptionTrap(SQInteger ss, SQInteger stackbase,SQInstruction *ip, SQInteger ex_target):
  22. _stackbase(stackbase),_stacksize(ss),_ip(ip),_extarget(ex_target)
  23. {}
  24. SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et; }
  25. SQInteger _stackbase;
  26. SQInteger _stacksize;
  27. SQInstruction *_ip;
  28. SQInteger _extarget;
  29. };
  30. #define _INLINE
  31. typedef sqvector<SQExceptionTrap> ExceptionsTraps;
  32. struct SQVM : public CHAINABLE_OBJ
  33. {
  34. struct CallInfo{
  35. //CallInfo() { _generator = NULL;}
  36. SQInstruction *_ip;
  37. SQObjectPtr *_literals;
  38. SQObjectPtr _closure;
  39. SQGenerator *_generator;
  40. SQInt32 _etraps;
  41. SQInt32 _prevstkbase;
  42. SQInt32 _prevtop;
  43. SQInt32 _target;
  44. SQInt32 _ncalls;
  45. SQBool _root;
  46. };
  47. typedef sqvector<CallInfo> CallInfoVec;
  48. #ifdef PROFILE_SQVM
  49. struct OpProfile {SQInteger op, count; SQFloat total_time;};
  50. typedef sqvector<OpProfile> OpProfileVec;
  51. #endif
  52. public:
  53. void DebugHookProxy(SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname);
  54. static void _DebugHookProxy(HSQUIRRELVM v, SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname);
  55. enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM,ET_RESUME_THROW_VM };
  56. SQVM(SQSharedState *ss);
  57. ~SQVM();
  58. bool Init(SQVM *friendvm, SQInteger stacksize);
  59. bool Execute(SQObjectPtr &func, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL);
  60. //starts a native call return when the NATIVE closure returns
  61. bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval, SQInt32 target, bool &suspend,bool &tailcall);
  62. bool TailCall(SQClosure *closure, SQInteger firstparam, SQInteger nparams);
  63. //starts a SQUIRREL call in the same "Execution loop"
  64. bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall);
  65. bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor);
  66. //call a generic closure pure SQUIRREL or NATIVE
  67. bool Call(SQObjectPtr &closure, SQInteger nparams, SQInteger stackbase, SQObjectPtr &outres,SQBool raiseerror);
  68. SQRESULT Suspend();
  69. void CallDebugHook(SQInteger type,SQInteger forcedline=0);
  70. void CallErrorHandler(SQObjectPtr &e);
  71. void CallAtExitHandler();
  72. bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, bool raw, SQInteger selfidx);
  73. SQInteger FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest);
  74. bool InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest);
  75. bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, SQInteger selfidx);
  76. SQInteger FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val);
  77. bool NewSlot(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val,bool bstatic);
  78. bool NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw);
  79. bool DeleteSlot(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &res);
  80. bool Clone(const SQObjectPtr &self, SQObjectPtr &target);
  81. bool ObjCmp(const SQObjectPtr &o1, const SQObjectPtr &o2,SQInteger &res);
  82. bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest);
  83. bool IsEqualDeep(const SQObjectPtr &o1,const SQObjectPtr &o2);
  84. static bool IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2);
  85. static bool IsEqualIdentity(const SQObjectPtr &o1,const SQObjectPtr &o2);
  86. bool ToString(const SQObjectPtr &o,SQObjectPtr &res);
  87. SQString *PrintObjVal(const SQObjectPtr &o);
  88. void Raise_Error(const SQChar *s, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
  89. void Raise_Error(const SQObjectPtr &desc);
  90. void Raise_IdxError(const SQObjectPtr &o);
  91. void Raise_CompareError(const SQObject &o1, const SQObject &o2);
  92. void Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type);
  93. void FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex);
  94. void RelocateOuters();
  95. void CloseOuters(SQObjectPtr *stackindex);
  96. bool TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest);
  97. bool CallMetaMethod(SQObjectPtr &closure, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres);
  98. bool ArithMetaMethod(SQInteger op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);
  99. bool Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval);
  100. //new stuff
  101. _INLINE bool ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
  102. _INLINE bool BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
  103. _INLINE bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1);
  104. _INLINE bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res);
  105. bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func);
  106. bool CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs);
  107. //return true if the loop is finished
  108. bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump);
  109. //_INLINE bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
  110. _INLINE bool PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
  111. _INLINE bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix,SQInteger arg0);
  112. #ifdef _DEBUG_DUMP
  113. void dumpstack(SQInteger stackbase=-1, bool dumpall = false);
  114. #endif
  115. #ifndef NO_GARBAGE_COLLECTOR
  116. void Mark(SQCollectable **chain);
  117. SQObjectType GetType() {return OT_THREAD;}
  118. #endif
  119. void Finalize();
  120. void GrowCallStack() {
  121. SQInteger newsize = _alloccallsstacksize*2;
  122. _callstackdata.resize(newsize);
  123. _callsstack = &_callstackdata[0];
  124. _alloccallsstacksize = newsize;
  125. }
  126. bool EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall);
  127. void LeaveFrame();
  128. void Release(){ sq_delete(this,SQVM); }
  129. ////////////////////////////////////////////////////////////////////////////
  130. //stack functions for the api
  131. void Remove(SQInteger n);
  132. void Replace(SQInteger n);
  133. void ReplaceAbs(SQInteger n);
  134. void Insert(SQInteger n);
  135. static bool IsFalse(const SQObjectPtr &o);
  136. void Pop();
  137. void Pop(SQInteger n);
  138. void Push(const SQObjectPtr &o);
  139. void PushNull();
  140. SQObjectPtr &Top();
  141. SQObjectPtr &PopGet();
  142. SQObjectPtr &GetUp(SQInteger n);
  143. SQObjectPtr &GetAt(SQInteger n);
  144. void SetIncludePath(const SQChar *s);
  145. const SQChar *GetIncludePath();
  146. bool AddDefined(const SQChar *s);
  147. void RemoveDefined(const SQChar *s);
  148. bool IsDefined(const SQChar *s);
  149. SQObjectPtrVec _stack;
  150. SQInteger _top;
  151. SQInteger _stackbase;
  152. SQOuter *_openouters;
  153. SQObjectPtr _roottable;
  154. SQObjectPtr _lasterror;
  155. SQInteger _lasterror_line, _lasterror_column;
  156. SQStackInfos _lasterror_stackinfo;
  157. SQObjectPtr _errorhandler;
  158. SQObjectPtr _atexithandler;
  159. SQObjectPtr temp_reg;
  160. CallInfo* _callsstack;
  161. SQInteger _callsstacksize;
  162. SQInteger _alloccallsstacksize;
  163. sqvector<CallInfo> _callstackdata;
  164. ExceptionsTraps _etraps;
  165. CallInfo *ci;
  166. SQUserPointer _foreignptr;
  167. //VMs sharing the same state
  168. SQInteger _nnativecalls;
  169. SQInteger _nmetamethodscall;
  170. SQRELEASEHOOK _releasehook;
  171. SQObjectPtr _include_path;
  172. //suspend infos
  173. SQBool _suspended;
  174. SQBool _suspended_root;
  175. SQInteger _suspended_target;
  176. SQInteger _suspended_traps;
  177. #ifdef SQ_WITH_DELAYED_RELEASE_HOOKS
  178. SQBool _check_delayed_relase_hooks;
  179. #endif
  180. #ifdef PROFILE_SQVM
  181. OpProfileVec _op_profile;
  182. HighResolutionTimer _op_profile_timer;
  183. #endif
  184. SQDEBUGHOOK _debughook_native;
  185. SQObjectPtr _debughook_closure;
  186. bool _debughook;
  187. SQBool _closing;
  188. };
  189. struct AutoDec{
  190. AutoDec(SQInteger *n) { _n = n; }
  191. ~AutoDec() { (*_n)--; }
  192. SQInteger *_n;
  193. };
  194. inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));}
  195. #define _ss(_vm_) (_vm_)->_sharedstate
  196. #ifndef NO_GARBAGE_COLLECTOR
  197. #define _opt_ss(_vm_) (_vm_)->_sharedstate
  198. #else
  199. #define _opt_ss(_vm_) NULL
  200. #endif
  201. #define PUSH_CALLINFO(v,nci){ \
  202. SQInteger css = v->_callsstacksize; \
  203. if(css == v->_alloccallsstacksize) { \
  204. v->GrowCallStack(); \
  205. } \
  206. v->ci = &v->_callsstack[css]; \
  207. *(v->ci) = nci; \
  208. v->_callsstacksize++; \
  209. }
  210. #define POP_CALLINFO(v){ \
  211. SQInteger css = --v->_callsstacksize; \
  212. v->ci->_closure.Null(); \
  213. v->ci = css?&v->_callsstack[css-1]:NULL; \
  214. }
  215. #endif //_SQVM_H_