00001
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
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
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
00062 bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger stackbase, SQObjectPtr &retval,bool &suspend);
00063
00064 bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall);
00065 bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor);
00066
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
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
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); }
00127
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
00161 SQSharedState *_sharedstate;
00162 SQInteger _nnativecalls;
00163
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_