0001
0002 #ifndef _PSVM_H_
0003 #define _PSVM_H_
0004
0005 #include "psopcodes.h"
0006 #include "psobject.h"
0007 #define MAX_NATIVE_CALLS 100
0008 #define MIN_STACK_OVERHEAD 15
0009
0010 #define PS_SUSPEND_FLAG -666
0011 #define DONT_FALL_BACK 666
0012
0013
0014 #define GET_FLAG_RAW 0x00000001
0015 #define GET_FLAG_DO_NOT_RAISE_ERROR 0x00000002
0016
0017 void ps_base_register(HPSCRIPTVM v);
0018
0019 struct PSExceptionTrap{
0020 PSExceptionTrap() {}
0021 PSExceptionTrap(PSInteger ss, PSInteger stackbase,PSInstruction *ip, PSInteger ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;}
0022 PSExceptionTrap(const PSExceptionTrap &et) { (*this) = et; }
0023 PSInteger _stackbase;
0024 PSInteger _stacksize;
0025 PSInstruction *_ip;
0026 PSInteger _extarget;
0027 };
0028
0029 #define _INLINE
0030
0031 #define STK(a) _stack._vals[_stackbase+(a)]
0032 #define TARGET _stack._vals[_stackbase+arg0]
0033
0034 typedef psvector<PSExceptionTrap> ExceptionsTraps;
0035
0036 struct PSVM : public CHAINABLE_OBJ
0037 {
0038 struct CallInfo{
0039
0040 PSInstruction *_ip;
0041 PSObjectPtr *_literals;
0042 PSObjectPtr _closure;
0043 PSGenerator *_generator;
0044 PSInt32 _etraps;
0045 PSInt32 _prevstkbase;
0046 PSInt32 _prevtop;
0047 PSInt32 _target;
0048 PSInt32 _ncalls;
0049 PSBool _root;
0050 };
0051
0052 typedef psvector<CallInfo> CallInfoVec;
0053 public:
0054 void DebugHookProxy(PSInteger type, const PSChar * sourcename, PSInteger line, const PSChar * funcname);
0055 static void _DebugHookProxy(HPSCRIPTVM v, PSInteger type, const PSChar * sourcename, PSInteger line, const PSChar * funcname);
0056 enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM,ET_RESUME_THROW_VM };
0057 PSVM(PSSharedState *ss);
0058 ~PSVM();
0059 bool Init(PSVM *friendvm, PSInteger stacksize);
0060 bool Execute(PSObjectPtr &func, PSInteger nargs, PSInteger stackbase, PSObjectPtr &outres, PSBool raiseerror, ExecutionType et = ET_CALL);
0061
0062 bool CallNative(PSNativeClosure *nclosure, PSInteger nargs, PSInteger newbase, PSObjectPtr &retval,bool &suspend);
0063
0064 bool StartCall(PSClosure *closure, PSInteger target, PSInteger nargs, PSInteger stackbase, bool tailcall);
0065 bool CreateClassInstance(PSClass *theclass, PSObjectPtr &inst, PSObjectPtr &constructor);
0066
0067 bool Call(PSObjectPtr &closure, PSInteger nparams, PSInteger stackbase, PSObjectPtr &outres,PSBool raiseerror);
0068 PSRESULT Suspend();
0069
0070 void CallDebugHook(PSInteger type,PSInteger forcedline=0);
0071 void CallErrorHandler(PSObjectPtr &e);
0072 bool Get(const PSObjectPtr &self, const PSObjectPtr &key, PSObjectPtr &dest, PSUnsignedInteger getflags, PSInteger selfidx);
0073 PSInteger FallBackGet(const PSObjectPtr &self,const PSObjectPtr &key,PSObjectPtr &dest);
0074 bool InvokeDefaultDelegate(const PSObjectPtr &self,const PSObjectPtr &key,PSObjectPtr &dest);
0075 bool Set(const PSObjectPtr &self, const PSObjectPtr &key, const PSObjectPtr &val, PSInteger selfidx);
0076 PSInteger FallBackSet(const PSObjectPtr &self,const PSObjectPtr &key,const PSObjectPtr &val);
0077 bool NewSlot(const PSObjectPtr &self, const PSObjectPtr &key, const PSObjectPtr &val,bool bstatic);
0078 bool NewSlotA(const PSObjectPtr &self,const PSObjectPtr &key,const PSObjectPtr &val,const PSObjectPtr &attrs,bool bstatic,bool raw);
0079 bool DeleteSlot(const PSObjectPtr &self, const PSObjectPtr &key, PSObjectPtr &res);
0080 bool Clone(const PSObjectPtr &self, PSObjectPtr &target);
0081 bool ObjCmp(const PSObjectPtr &o1, const PSObjectPtr &o2,PSInteger &res);
0082 bool StringCat(const PSObjectPtr &str, const PSObjectPtr &obj, PSObjectPtr &dest);
0083 static bool IsEqual(const PSObjectPtr &o1,const PSObjectPtr &o2,bool &res);
0084 bool ToString(const PSObjectPtr &o,PSObjectPtr &res);
0085 PSString *PrintObjVal(const PSObjectPtr &o);
0086
0087
0088 void Raise_Error(const PSChar *s, ...);
0089 void Raise_Error(const PSObjectPtr &desc);
0090 void Raise_IdxError(const PSObjectPtr &o);
0091 void Raise_CompareError(const PSObject &o1, const PSObject &o2);
0092 void Raise_ParamTypeError(PSInteger nparam,PSInteger typemask,PSInteger type);
0093
0094 void FindOuter(PSObjectPtr &target, PSObjectPtr *stackindex);
0095 void RelocateOuters();
0096 void CloseOuters(PSObjectPtr *stackindex);
0097
0098 bool TypeOf(const PSObjectPtr &obj1, PSObjectPtr &dest);
0099 bool CallMetaMethod(PSObjectPtr &closure, PSMetaMethod mm, PSInteger nparams, PSObjectPtr &outres);
0100 bool ArithMetaMethod(PSInteger op, const PSObjectPtr &o1, const PSObjectPtr &o2, PSObjectPtr &dest);
0101 bool Return(PSInteger _arg0, PSInteger _arg1, PSObjectPtr &retval);
0102
0103 _INLINE bool ARITH_OP(PSUnsignedInteger op,PSObjectPtr &trg,const PSObjectPtr &o1,const PSObjectPtr &o2);
0104 _INLINE bool BW_OP(PSUnsignedInteger op,PSObjectPtr &trg,const PSObjectPtr &o1,const PSObjectPtr &o2);
0105 _INLINE bool NEG_OP(PSObjectPtr &trg,const PSObjectPtr &o1);
0106 _INLINE bool CMP_OP(CmpOP op, const PSObjectPtr &o1,const PSObjectPtr &o2,PSObjectPtr &res);
0107 bool CLOSURE_OP(PSObjectPtr &target, PSFunctionProto *func);
0108 bool CLASS_OP(PSObjectPtr &target,PSInteger base,PSInteger attrs);
0109
0110 bool FOREACH_OP(PSObjectPtr &o1,PSObjectPtr &o2,PSObjectPtr &o3,PSObjectPtr &o4,PSInteger arg_2,int exitpos,int &jump);
0111
0112 _INLINE bool PLOCAL_INC(PSInteger op,PSObjectPtr &target, PSObjectPtr &a, PSObjectPtr &incr);
0113 _INLINE bool DerefInc(PSInteger op,PSObjectPtr &target, PSObjectPtr &self, PSObjectPtr &key, PSObjectPtr &incr, bool postfix,PSInteger arg0);
0114 #ifdef _DEBUG_DUMP
0115 void dumpstack(PSInteger stackbase=-1, bool dumpall = false);
0116 #endif
0117
0118 #ifndef NO_GARBAGE_COLLECTOR
0119 void Mark(PSCollectable **chain);
0120 PSObjectType GetType() {return OT_THREAD;}
0121 #endif
0122 void Finalize();
0123 void GrowCallStack() {
0124 PSInteger newsize = _alloccallsstacksize*2;
0125 _callstackdata.resize(newsize);
0126 _callsstack = &_callstackdata[0];
0127 _alloccallsstacksize = newsize;
0128 }
0129 bool EnterFrame(PSInteger newbase, PSInteger newtop, bool tailcall);
0130 void LeaveFrame();
0131 void Release(){ ps_delete(this,PSVM); }
0132
0133
0134 void Remove(PSInteger n);
0135
0136 static bool IsFalse(PSObjectPtr &o);
0137
0138 void Pop();
0139 void Pop(PSInteger n);
0140 void Push(const PSObjectPtr &o);
0141 void PushNull();
0142 PSObjectPtr &Top();
0143 PSObjectPtr &PopGet();
0144 PSObjectPtr &GetUp(PSInteger n);
0145 PSObjectPtr &GetAt(PSInteger n);
0146
0147 PSObjectPtrVec _stack;
0148
0149 PSInteger _top;
0150 PSInteger _stackbase;
0151 PSOuter *_openouters;
0152 PSObjectPtr _roottable;
0153 PSObjectPtr _lasterror;
0154 PSObjectPtr _errorhandler;
0155
0156 bool _debughook;
0157 PSDEBUGHOOK _debughook_native;
0158 PSObjectPtr _debughook_closure;
0159
0160 PSObjectPtr temp_reg;
0161
0162
0163 CallInfo* _callsstack;
0164 PSInteger _callsstacksize;
0165 PSInteger _alloccallsstacksize;
0166 psvector<CallInfo> _callstackdata;
0167
0168 ExceptionsTraps _etraps;
0169 CallInfo *ci;
0170 PSUserPointer _foreignptr;
0171
0172 PSSharedState *_sharedstate;
0173 PSInteger _nnativecalls;
0174 PSInteger _nmetamethodscall;
0175 PSRELEASEHOOK _releasehook;
0176
0177 PSBool _suspended;
0178 PSBool _suspended_root;
0179 PSInteger _suspended_target;
0180 PSInteger _suspended_traps;
0181 };
0182
0183 struct AutoDec{
0184 AutoDec(PSInteger *n) { _n = n; }
0185 ~AutoDec() { (*_n)--; }
0186 PSInteger *_n;
0187 };
0188
0189 inline PSObjectPtr &stack_get(HPSCRIPTVM v,PSInteger idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));}
0190
0191 #define _ss(_vm_) (_vm_)->_sharedstate
0192
0193 #ifndef NO_GARBAGE_COLLECTOR
0194 #define _opt_ss(_vm_) (_vm_)->_sharedstate
0195 #else
0196 #define _opt_ss(_vm_) NULL
0197 #endif
0198
0199 #define PUSH_CALLINFO(v,nci){ \
0200 PSInteger css = v->_callsstacksize; \
0201 if(css == v->_alloccallsstacksize) { \
0202 v->GrowCallStack(); \
0203 } \
0204 v->ci = &v->_callsstack[css]; \
0205 *(v->ci) = nci; \
0206 v->_callsstacksize++; \
0207 }
0208
0209 #define POP_CALLINFO(v){ \
0210 PSInteger css = --v->_callsstacksize; \
0211 v->ci->_closure.Null(); \
0212 v->ci = css?&v->_callsstack[css-1]:NULL; \
0213 }
0214 #endif