# sqvm.h

    00001 /*  see copyright notice in squirrel.h */
    00002 #ifndef _SQVM_H_
    00003 #define _SQVM_H_
    00004
    00005 #include "sqopcodes.h"
    00006 #include "sqobject.h"
    00007 #define MAX_NATIVE_CALLS 100
    00008 #define MIN_STACK_OVERHEAD 10
    00009
    00010 #define SQ_SUSPEND_FLAG -666
    00011 //base lib
    00012 void sq_base_register(HSQUIRRELVM v);
    00013
    00014 struct SQExceptionTrap{
    00015   SQExceptionTrap() {}
    00016   SQExceptionTrap(SQInteger ss, SQInteger stackbase,SQInstruction *ip, SQInteger ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;}
    00017   SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et;  }
    00018   SQInteger _stackbase;
    00019   SQInteger _stacksize;
    00020   SQInstruction *_ip;
    00021   SQInteger _extarget;
    00022 };
    00023
    00024 #define _INLINE
    00025
    00026 #define STK(a) _stack._vals[_stackbase+(a)]
    00027 #define TARGET _stack._vals[_stackbase+arg0]
    00028
    00029 typedef sqvector<SQExceptionTrap> ExceptionsTraps;
    00030
    00031 struct SQVM : public CHAINABLE_OBJ
    00032 {
    00033   struct VarArgs {
    00034     VarArgs() { size = 0; base = 0; }
    00035     unsigned short size;
    00036     unsigned short base;
    00037   };
    00038
    00039   struct CallInfo{
    00040     //CallInfo() { _generator._type = OT_NULL;}
    00041     SQInstruction *_ip;
    00042     SQObjectPtr *_literals;
    00043     SQObjectPtr _closure;
    00044     SQGenerator *_generator;
    00045     SQInt32 _etraps;
    00046     SQInt32 _prevstkbase;
    00047     SQInt32 _prevtop;
    00048     SQInt32 _target;
    00049     SQInt32 _ncalls;
    00050     SQBool _root;
    00051     VarArgs _vargs;
    00052   };
    00053
    00054 typedef sqvector<CallInfo> CallInfoVec;
    00055 public:
    00056   enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM, ET_RESUME_THROW_VM, ET_RESUME_OPENTTD };
    00057   SQVM(SQSharedState *ss);
    00058   ~SQVM();
    00059   bool Init(SQVM *friendvm, SQInteger stacksize);
    00060   bool Execute(SQObjectPtr &func, SQInteger target, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL);
    00061   //starts a native call return when the NATIVE closure returns
    00062   bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger stackbase, SQObjectPtr &retval,bool &suspend);
    00063   //starts a SQUIRREL call in the same "Execution loop"
    00064   bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall);
    00065   bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor);
    00066   //call a generic closure pure SQUIRREL or NATIVE
    00067   bool Call(SQObjectPtr &closure, SQInteger nparams, SQInteger stackbase, SQObjectPtr &outres,SQBool raiseerror,SQBool can_suspend);
    00068   SQRESULT Suspend();
    00069
    00070   void CallDebugHook(SQInteger type,SQInteger forcedline=0);
    00071   void CallErrorHandler(SQObjectPtr &e);
    00072   bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, bool raw, bool fetchroot);
    00073   bool FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw);
    00074   bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, bool fetchroot);
    00075   bool NewSlot(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val,bool bstatic);
    00076   bool DeleteSlot(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &res);
    00077   bool Clone(const SQObjectPtr &self, SQObjectPtr &target);
    00078   bool ObjCmp(const SQObjectPtr &o1, const SQObjectPtr &o2,SQInteger &res);
    00079   bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest);
    00080   bool IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res);
    00081   void ToString(const SQObjectPtr &o,SQObjectPtr &res);
    00082   SQString *PrintObjVal(const SQObject &o);
    00083
    00084
    00085   void Raise_Error(const SQChar *s, ...);
    00086   void Raise_Error(SQObjectPtr &desc);
    00087   void Raise_IdxError(SQObject &o);
    00088   void Raise_CompareError(const SQObject &o1, const SQObject &o2);
    00089   void Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type);
    00090
    00091   void TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest);
    00092   bool CallMetaMethod(SQDelegable *del, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres);
    00093   bool ArithMetaMethod(SQInteger op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);
    00094   bool Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval);
    00095   //new stuff
    00096   _INLINE bool ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
    00097   _INLINE bool BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
    00098   _INLINE bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1);
    00099   _INLINE bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res);
    00100   bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func);
    00101   bool GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &idx,CallInfo *ci);
    00102   bool CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs);
    00103   bool GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target);
    00104   //return true if the loop is finished
    00105   bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump);
    00106   bool DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2);
    00107   _INLINE bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
    00108   _INLINE bool PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
    00109   _INLINE bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix);
    00110   void PopVarArgs(VarArgs &vargs);
    00111 #ifdef _DEBUG_DUMP
    00112   void dumpstack(SQInteger stackbase=-1, bool dumpall = false);
    00113 #endif
    00114
    00115 #ifndef NO_GARBAGE_COLLECTOR
    00116   void Mark(SQCollectable **chain);
    00117 #endif
    00118   void Finalize();
    00119   void GrowCallStack() {
    00120     SQInteger newsize = _alloccallsstacksize*2;
    00121     _callstackdata.resize(newsize);
    00122     _callsstack = &_callstackdata[0];
    00123     _alloccallsstacksize = newsize;
    00124   }
    00125   void Release(){ sq_delete(this,SQVM); } //does nothing
    00127   //stack functions for the api
    00128   void Remove(SQInteger n);
    00129
    00130   bool IsFalse(SQObjectPtr &o);
    00131
    00132   void Pop();
    00133   void Pop(SQInteger n);
    00134   void Push(const SQObjectPtr &o);
    00135   SQObjectPtr &Top();
    00136   SQObjectPtr &PopGet();
    00137   SQObjectPtr &GetUp(SQInteger n);
    00138   SQObjectPtr &GetAt(SQInteger n);
    00139
    00140   SQObjectPtrVec _stack;
    00141   SQObjectPtrVec _vargsstack;
    00142   SQInteger _top;
    00143   SQInteger _stackbase;
    00144   SQObjectPtr _roottable;
    00145   SQObjectPtr _lasterror;
    00146   SQObjectPtr _errorhandler;
    00147   SQObjectPtr _debughook;
    00148
    00149   SQObjectPtr temp_reg;
    00150
    00151
    00152   CallInfo* _callsstack;
    00153   SQInteger _callsstacksize;
    00154   SQInteger _alloccallsstacksize;
    00155   sqvector<CallInfo>  _callstackdata;
    00156
    00157   ExceptionsTraps _etraps;
    00158   CallInfo *ci;
    00159   void *_foreignptr;
    00160   //VMs sharing the same state
    00161   SQSharedState *_sharedstate;
    00162   SQInteger _nnativecalls;
    00163   //suspend infos
    00164   SQBool _suspended;
    00165   SQBool _suspended_root;
    00166   SQInteger _suspended_target;
    00167   SQInteger _suspended_traps;
    00168   VarArgs _suspend_varargs;
    00169
    00170   SQBool _can_suspend;
    00171   SQInteger _ops_till_suspend;
    00172
    00173   bool ShouldSuspend()
    00174   {
    00175     return _can_suspend && _ops_till_suspend <= 0;
    00176   }
    00177
    00178   void DecreaseOps(SQInteger amount)
    00179   {
    00180     if (_ops_till_suspend - amount < _ops_till_suspend) _ops_till_suspend -= amount;
    00181   }
    00182 };
    00183
    00184 struct AutoDec{
    00185   AutoDec(SQInteger *n) { _n = n; }
    00186   ~AutoDec() { (*_n)--; }
    00187   SQInteger *_n;
    00188 };
    00189
    00190 inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));}
    00191
    00192 #define _ss(_vm_) (_vm_)->_sharedstate
    00193
    00194 #ifndef NO_GARBAGE_COLLECTOR
    00195 #define _opt_ss(_vm_) (_vm_)->_sharedstate
    00196 #else
    00197 #define _opt_ss(_vm_) NULL
    00198 #endif
    00199
    00200 #define PUSH_CALLINFO(v,nci){ \
    00201   if(v->_callsstacksize == v->_alloccallsstacksize) { \
    00202     v->GrowCallStack(); \
    00203   } \
    00204   v->ci = &v->_callsstack[v->_callsstacksize]; \
    00205   *(v->ci) = nci; \
    00206   v->_callsstacksize++; \
    00207 }
    00208
    00209 #define POP_CALLINFO(v){ \
    00210   v->_callsstacksize--; \
    00211   v->ci->_closure.Null(); \
    00212   if(v->_callsstacksize)  \
    00213     v->ci = &v->_callsstack[v->_callsstacksize-1] ; \
    00214   else  \
    00215     v->ci = NULL; \
    00216 }
    00217 #endif //_SQVM_H_