1 /*	see copyright notice in squirrel.h */
2 #ifndef _SQVM_H_
3 #define _SQVM_H_
4 
5 #include "sqopcodes.h"
6 #include "sqobject.h"
7 #define MAX_NATIVE_CALLS 100
8 #define MIN_STACK_OVERHEAD 10
9 
10 #define SQ_SUSPEND_FLAG -666
11 //base lib
12 void sq_base_register(HSQUIRRELVM v);
13 
14 struct SQExceptionTrap{
SQExceptionTrapSQExceptionTrap15 	SQExceptionTrap() {}
SQExceptionTrapSQExceptionTrap16 	SQExceptionTrap(SQInteger ss, SQInteger stackbase,SQInstruction *ip, SQInteger ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;}
SQExceptionTrapSQExceptionTrap17 	SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et;	}
18 	SQInteger _stackbase;
19 	SQInteger _stacksize;
20 	SQInstruction *_ip;
21 	SQInteger _extarget;
22 };
23 
24 
25 #define STK(a) _stack._vals[_stackbase+(a)]
26 #define TARGET _stack._vals[_stackbase+arg0]
27 
28 typedef sqvector<SQExceptionTrap> ExceptionsTraps;
29 
30 struct SQVM : public CHAINABLE_OBJ
31 {
32 	struct VarArgs {
VarArgsSQVM::VarArgs33 		VarArgs() { size = 0; base = 0; }
34 		SQInteger size;
35 		SQInteger base;
36 	};
37 
38 	struct CallInfo{
CallInfoSQVM::CallInfo39 		CallInfo() { _generator._type = OT_NULL;}
40 		//CallInfo(const CallInfo& ci) {  }
41 		SQInstructionVec *_iv;
42 		SQObjectPtrVec *_literals;
43 		SQObject _closure;
44 		SQObject _generator;
45 		SQInteger _etraps;
46 		SQInteger _prevstkbase;
47 		SQInteger _prevtop;
48 		SQInteger _target;
49 		SQInstruction *_ip;
50 		SQInteger _ncalls;
51 		SQBool _root;
52 		VarArgs _vargs;
53 	};
54 
55 typedef sqvector<CallInfo> CallInfoVec;
56 public:
57 	enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM };
58 	SQVM(SQSharedState *ss);
59 	virtual ~SQVM();
60 	bool Init(SQVM *friendvm, SQInteger stacksize);
61 	bool Execute(SQObjectPtr &func, SQInteger target, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, ExecutionType et = ET_CALL);
62 	//start a native call return when the NATIVE closure returns(returns true if the vm has been suspended)
63 	bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger stackbase, bool tailcall, SQObjectPtr &retval,bool &suspend);
64 	//start a SQUIRREL call in the same "Execution loop"
65 	bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall);
66 	bool CreateClassInstance(SQClass *theclass, SQInteger nargs, SQInteger stackbase, SQObjectPtr &retval);
67 	//call a generic closure pure SQUIRREL or NATIVE
68 	bool Call(SQObjectPtr &closure, SQInteger nparams, SQInteger stackbase, SQObjectPtr &outres);
69 	SQRESULT Suspend();
70 
71 	void CallDebugHook(SQInteger type,SQInteger forcedline=0);
72 	void CallErrorHandler(SQObjectPtr &e);
73 	bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, bool raw, bool fetchroot);
74 	bool FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw);
75 	bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, bool fetchroot);
76 	bool NewSlot(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val);
77 	bool DeleteSlot(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &res);
78 	bool Clone(const SQObjectPtr &self, SQObjectPtr &target);
79 	bool ObjCmp(const SQObjectPtr &o1, const SQObjectPtr &o2,SQInteger &res);
80 	bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest);
81 	bool IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res);
82 	void ToString(const SQObjectPtr &o,SQObjectPtr &res);
83 	SQString *PrintObjVal(const SQObject &o);
84 
85 
86 	void Raise_Error(const SQChar *s, ...);
87 	void Raise_Error(SQObjectPtr &desc);
88 	void Raise_IdxError(SQObject &o);
89 	void Raise_CompareError(const SQObject &o1, const SQObject &o2);
90 	void Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type);
91 
92 	void TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest);
93 	bool CallMetaMethod(SQDelegable *del, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres);
94 	bool ArithMetaMethod(SQInteger op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);
95 	bool Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval);
96 	//new stuff
97 	inline bool ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
98 	inline bool BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
99 	inline bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1);
100 	inline bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res);
101 	bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func);
102 	bool GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &idx,CallInfo *ci);
103 	bool CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs);
104 	//return true if the loop is finished
105 	bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,bool &finished);
106 	bool DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2);
107 	inline bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
108 	inline bool PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
109 	inline bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix);
110 	void PopVarArgs(VarArgs &vargs);
111 #ifdef _DEBUG_DUMP
112 	void dumpstack(SQInteger stackbase=-1, bool dumpall = false);
113 #endif
114 
115 #ifndef NO_GARBAGE_COLLECTOR
116 	void Mark(SQCollectable **chain);
117 #endif
118 	void Finalize();
119 
ReleaseSQVM120 	void Release(){ sq_delete(this,SQVM); } //does nothing
121 ////////////////////////////////////////////////////////////////////////////
122 	//stack functions for the api
123 	void Remove(SQInteger n);
124 
IsFalseSQVM125 	inline bool IsFalse(SQObjectPtr &o)
126 	{
127 		if((squirrel_type(o) & SQOBJECT_CANBEFALSE) && ( (squirrel_type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0)) )
128 			|| (_integer(o) == 0) ) { //OT_NULL|OT_INTEGER|OT_BOOL
129 			return true;
130 		}
131 		return false;
132 	}
PopSQVM133 	inline void Pop() {
134 		_stack[--_top] = _null_;
135 	}
136 
PopSQVM137 	inline void Pop(SQInteger n) {
138 		for(SQInteger i = 0; i < n; i++){
139 			_stack[--_top] = _null_;
140 		}
141 	}
142 
PushSQVM143 	inline void Push(const SQObjectPtr &o) { _stack[_top++] = o; }
TopSQVM144 	inline SQObjectPtr &Top() { return _stack[_top-1]; }
PopGetSQVM145 	inline SQObjectPtr &PopGet() { return _stack[--_top]; }
GetUpSQVM146 	inline SQObjectPtr &GetUp(SQInteger n) { return _stack[_top+n]; }
GetAtSQVM147 	inline SQObjectPtr &GetAt(SQInteger n) { return _stack[n]; }
148 
149 	SQObjectPtrVec _stack;
150 	SQObjectPtrVec _vargsstack;
151 	SQInteger _top;
152 	SQInteger _stackbase;
153 	SQObjectPtr _roottable;
154 	//SQObjectPtr _thrownerror;
155 	SQObjectPtr _lasterror;
156 	SQObjectPtr _errorhandler;
157 	SQObjectPtr _debughook;
158 
159 	SQObjectPtr temp_reg;
160 	CallInfoVec _callsstack;
161 	ExceptionsTraps _etraps;
162 	CallInfo *ci;
163 	void *_foreignptr;
164 	//VMs sharing the same state
165 	SQSharedState *_sharedstate;
166 	SQInteger _nnativecalls;
167 	//suspend infos
168 	SQBool _suspended;
169 	SQBool _suspended_root;
170 	SQInteger _suspended_target;
171 	SQInteger _suspended_traps;
172 };
173 
174 struct AutoDec{
AutoDecAutoDec175 	AutoDec(SQInteger *n) { _n = n; }
~AutoDecAutoDec176 	~AutoDec() { (*_n)--; }
177 	SQInteger *_n;
178 };
179 
stack_get(HSQUIRRELVM v,SQInteger idx)180 inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));}
181 const SQChar *GetTypeName(const SQObjectPtr &obj1);
182 const SQChar *IdType2Name(SQObjectType type);
183 
184 #define _ss(_vm_) (_vm_)->_sharedstate
185 
186 #ifndef NO_GARBAGE_COLLECTOR
187 #define _opt_ss(_vm_) (_vm_)->_sharedstate
188 #else
189 #define _opt_ss(_vm_) NULL
190 #endif
191 
192 #define PUSH_CALLINFO(v,nci){ \
193 	v->ci = &v->_callsstack.push_back(nci); \
194 }
195 
196 #define POP_CALLINFO(v){ \
197 	v->_callsstack.pop_back(); \
198 	if(v->_callsstack.size())	\
199 		v->ci = &v->_callsstack.back() ; \
200 	else	\
201 		v->ci = NULL; \
202 }
203 #endif //_SQVM_H_
204