OpenClonk
C4AulExec.h
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2001, 2006-2007, Sven Eberhardt
5  * Copyright (c) 2006, Peter Wortmann
6  * Copyright (c) 2007, Günther Brammer
7  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
8  *
9  * Distributed under the terms of the ISC license; see accompanying file
10  * "COPYING" for details.
11  *
12  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
13  * See accompanying file "TRADEMARK" for details.
14  *
15  * To redistribute this file separately, substitute the full license texts
16  * for the above references.
17  */
18 
19 #ifndef C4AULEXEC_H
20 #define C4AULEXEC_H
21 
23 #include "script/C4Aul.h"
24 #include "script/C4AulScriptFunc.h"
25 
26 const int MAX_CONTEXT_STACK = 512;
27 const int MAX_VALUE_STACK = 1024;
28 
29 /*
30  The Stack layout is as follows:
31  first parameter
32  ...
33  last parameter
34  first named var
35  ...
36  last named var
37  temporary values
38  */
39 
40 // execution context
42 {
48  C4TimeMilliseconds tTime; // initialized only by profiler if active
49 
50  void dump(StdStrBuf Dump = StdStrBuf(""));
52 };
53 
54 class C4AulExec
55 {
56 
57 public:
59  : pCurCtx(Contexts - 1), pCurVal(Values - 1)
60  { }
61 
62 private:
63  C4AulScriptContext *pCurCtx;
64  C4Value *pCurVal;
65 
66  int iTraceStart{-1};
67  bool fProfiling;
68  C4TimeMilliseconds tDirectExecStart;
69  uint32_t tDirectExecTotal; // profiler time for DirectExec
70  C4ScriptHost *pProfiledScript;
71 
73  C4Value Values[MAX_VALUE_STACK];
74 
75  void StartProfiling(C4ScriptHost *pScript); // starts recording the times
76  bool IsProfiling() { return fProfiling; }
77  void StopProfiling() { fProfiling=false; }
78  friend class C4AulProfiler;
79 public:
80  C4Value Exec(C4AulScriptFunc *pSFunc, C4PropList * p, C4Value pPars[], bool fPassErrors);
81  C4Value DirectExec(C4PropList *p, const char *szScript, const char *szContext, bool fPassErrors = false, C4AulScriptContext* context = nullptr, bool parse_function = false);
82 
83  void StartTrace();
84  inline void StartDirectExec() { if (fProfiling) tDirectExecStart = C4TimeMilliseconds::Now(); }
85  inline void StopDirectExec() { if (fProfiling) tDirectExecTotal += C4TimeMilliseconds::Now() - tDirectExecStart; }
86 
87  int GetContextDepth() const { return pCurCtx - Contexts + 1; }
88  C4AulScriptContext *GetContext(int iLevel) { return iLevel >= 0 && iLevel < GetContextDepth() ? Contexts + iLevel : nullptr; }
89  void LogCallStack();
90  static C4String *FnTranslate(C4PropList * _this, C4String *text);
91  static bool FnLogCallStack(C4PropList * _this);
92  void ClearPointers(C4Object *);
93 
94 private:
95  C4Value Exec(C4AulBCC *pCPos);
96  void PushContext(const C4AulScriptContext &rContext);
97  void PopContext();
98 
99  void CheckOverflow(int iCnt)
100  {
101  if (pCurVal - Values >= MAX_VALUE_STACK - iCnt)
102  throw C4AulExecError("value stack overflow, probably due to too deep recursion");
103  }
104 
105  void PushInt(int32_t i)
106  {
107  CheckOverflow(1);
108  (++pCurVal)->SetInt(i);
109  }
110 
111  void PushBool(bool b)
112  {
113  CheckOverflow(1);
114  (++pCurVal)->SetBool(b);
115  }
116 
117  void PushString(C4String * Str)
118  {
119  CheckOverflow(1);
120  (++pCurVal)->SetString(Str);
121  }
122 
123  void PushArray(C4ValueArray * Array)
124  {
125  CheckOverflow(1);
126  (++pCurVal)->SetArray(Array);
127  }
128 
129  void PushFunction(C4AulFunc * Fn)
130  {
131  CheckOverflow(1);
132  (++pCurVal)->SetFunction(Fn);
133  }
134 
135  void PushPropList(C4PropList * PropList)
136  {
137  CheckOverflow(1);
138  (++pCurVal)->SetPropList(PropList);
139  }
140 
141  void PushValue(const C4Value &rVal)
142  {
143  CheckOverflow(1);
144  (++pCurVal)->Set(rVal);
145  }
146 
147  void PushNullVals(int iCnt)
148  {
149  CheckOverflow(iCnt);
150  pCurVal += iCnt;
151  }
152 
153  bool PopValue()
154  {
155  assert (LocalValueStackSize() >= 1);
156  (pCurVal--)->Set0();
157  return true;
158  }
159 
160  void PopValues(int n)
161  {
162  assert (LocalValueStackSize() >= n);
163  while (n--)
164  (pCurVal--)->Set0();
165  }
166 
167  void PopValuesUntil(C4Value *pUntilVal)
168  {
169  assert (pUntilVal >= Values - 1);
170  while (pCurVal > pUntilVal)
171  (pCurVal--)->Set0();
172  }
173 
174  int ContextStackSize() const
175  {
176  return pCurCtx - Contexts + 1;
177  }
178 
179  int ValueStackSize() const
180  {
181  return pCurVal - Values + 1;
182  }
183 
184  int LocalValueStackSize() const
185  {
186  return ContextStackSize()
187  ? pCurVal - pCurCtx->Pars - pCurCtx->Func->GetParCount() - pCurCtx->Func->VarNamed.iSize + 1
188  : pCurVal - Values + 1;
189  }
190 
191  ALWAYS_INLINE void CheckOpPars(C4V_Type Type1, C4V_Type Type2, const char * opname)
192  {
193  // Get parameters
194  C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
195 
196  // Typecheck parameters
197  if (!pPar1->CheckParConversion(Type1))
198  throw C4AulExecError(FormatString(R"(operator "%s" left side got %s, but expected %s)",
199  opname, pPar1->GetTypeName(), GetC4VName(Type1)).getData());
200  if (!pPar2->CheckParConversion(Type2))
201  throw C4AulExecError(FormatString(R"(operator "%s" right side got %s, but expected %s)",
202  opname, pPar2->GetTypeName(), GetC4VName(Type2)).getData());
203  }
204  ALWAYS_INLINE void CheckOpPar(C4V_Type Type1, const char * opname)
205  {
206  // Typecheck parameter
207  if (!pCurVal->CheckParConversion(Type1))
208  throw C4AulExecError(FormatString(R"(operator "%s": got %s, but expected %s)",
209  opname, pCurVal->GetTypeName(), GetC4VName(Type1)).getData());
210  }
211 
212  C4V_Type CheckArrayAccess(C4Value *pStructure, C4Value *pIndex)
213  {
214  if (pStructure->CheckConversion(C4V_Array))
215  {
216  if (!pIndex->CheckConversion(C4V_Int))
217  throw C4AulExecError(FormatString("array access: index of type %s, but expected int", pIndex->GetTypeName()).getData());
218  return C4V_Array;
219  }
220  else if (pStructure->CheckConversion(C4V_PropList))
221  {
222  if (!pIndex->CheckConversion(C4V_String))
223  throw C4AulExecError(FormatString("proplist access: index of type %s, but expected string", pIndex->GetTypeName()).getData());
224  return C4V_PropList;
225  }
226  else
227  throw C4AulExecError(FormatString("can't access %s as array or proplist", pStructure->GetTypeName()).getData());
228  }
229  C4AulBCC *Call(C4AulFunc *pFunc, C4Value *pReturn, C4Value *pPars, C4PropList * pContext = nullptr);
230 };
231 
232 extern C4AulExec AulExec;
233 
234 // script profiler entry
236 {
237 private:
238  // map entry
239  struct Entry
240  {
241  C4AulScriptFunc *pFunc;
242  uint32_t tProfileTime;
243 
244  bool operator < (const Entry &e2) const { return tProfileTime < e2.tProfileTime ; }
245  };
246 
247  // items
248  std::vector<Entry> Times;
249 
250  void CollectEntry(C4AulScriptFunc *pFunc, uint32_t tProfileTime);
251  void CollectTimes(C4PropListStatic * p);
252  void CollectTimes();
253  static void ResetTimes(C4PropListStatic * p);
254  static void ResetTimes();
255  void Show();
256 public:
257  static void Abort() { AulExec.StopProfiling(); }
258  static void StartProfiling(C4ScriptHost *pScript); // reset times and start collecting new ones
259  static void StopProfiling(); // stop the profiler and displays results
260 };
261 
262 #endif // C4AULEXEC_H
C4AulExec AulExec
Definition: C4AulExec.cpp:29
const int MAX_CONTEXT_STACK
Definition: C4AulExec.h:26
const int MAX_VALUE_STACK
Definition: C4AulExec.h:27
#define b
bool operator<(const C4TimeMilliseconds &lhs, const C4TimeMilliseconds &rhs)
const char * GetC4VName(const C4V_Type Type)
Definition: C4Value.cpp:32
C4V_Type
Definition: C4Value.h:24
@ C4V_Int
Definition: C4Value.h:26
@ C4V_PropList
Definition: C4Value.h:28
@ C4V_Array
Definition: C4Value.h:30
@ C4V_String
Definition: C4Value.h:29
#define ALWAYS_INLINE
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:270
int iCnt
Definition: TstC4NetIO.cpp:32
C4AulExec()
Definition: C4AulExec.h:58
void LogCallStack()
Definition: C4AulExec.cpp:94
void ClearPointers(C4Object *)
Definition: C4AulExec.cpp:136
static bool FnLogCallStack(C4PropList *_this)
Definition: C4AulExec.cpp:130
void StartTrace()
Definition: C4AulExec.cpp:905
C4AulScriptContext * GetContext(int iLevel)
Definition: C4AulExec.h:88
C4Value DirectExec(C4PropList *p, const char *szScript, const char *szContext, bool fPassErrors=false, C4AulScriptContext *context=nullptr, bool parse_function=false)
Definition: C4AulExec.cpp:1012
C4Value Exec(C4AulScriptFunc *pSFunc, C4PropList *p, C4Value pPars[], bool fPassErrors)
void StopDirectExec()
Definition: C4AulExec.h:85
static C4String * FnTranslate(C4PropList *_this, C4String *text)
Definition: C4AulExec.cpp:100
int GetContextDepth() const
Definition: C4AulExec.h:87
void StartDirectExec()
Definition: C4AulExec.h:84
static void StopProfiling()
Definition: C4AulExec.cpp:972
static void Abort()
Definition: C4AulExec.h:257
static void StartProfiling(C4ScriptHost *pScript)
Definition: C4AulExec.cpp:963
C4ValueMapNames VarNamed
int GetParCount() const override
static C4TimeMilliseconds Now()
ALWAYS_INLINE bool CheckConversion(C4V_Type vtToType) const
Definition: C4Value.h:189
ALWAYS_INLINE bool CheckParConversion(C4V_Type vtToType) const
Definition: C4Value.h:171
const char * GetTypeName() const
Definition: C4Value.h:164
const char * getData() const
Definition: StdBuf.h:442
void dump(StdStrBuf Dump=StdStrBuf(""))
Definition: C4AulExec.cpp:88
C4TimeMilliseconds tTime
Definition: C4AulExec.h:48
C4Value * Return
Definition: C4AulExec.h:44
C4AulBCC * CPos
Definition: C4AulExec.h:47
C4PropList * Obj
Definition: C4AulExec.h:43
StdStrBuf ReturnDump(StdStrBuf Dump=StdStrBuf(""))
Definition: C4AulExec.cpp:38
C4AulScriptFunc * Func
Definition: C4AulExec.h:46
C4Value * Pars
Definition: C4AulExec.h:45