1414#include " script/cc_instance.h"
1515#include < cstdio>
1616#include < deque>
17+ #include < vector>
1718#include < string.h>
1819#include " ac/common.h"
1920#include " ac/sys_events.h"
@@ -168,30 +169,43 @@ String cc_get_callstack(int max_lines)
168169}
169170
170171
171- // Function call stack is used to temporarily store
172- // values before passing them to script function
173- #define MAX_FUNC_PARAMS 20
174- // An inverted parameter stack
172+ // An inverted parameter stack, internally implemented as a vector,
173+ // to let us pass a pointer to the parameter sequence.
174+ // TODO: reorganize this as a generic container in utils.
175175struct FunctionCallStack
176176{
177- FunctionCallStack ()
177+ FunctionCallStack (size_t initial_count = 16 )
178178 {
179- Head = MAX_FUNC_PARAMS - 1 ;
180- Count = 0 ;
179+ initial_count = std::max (1u , initial_count);
180+ _entries.resize (initial_count);
181+ _head = _entries.data () + initial_count;
181182 }
182183
183- inline RuntimeScriptValue *GetHead ()
184+ inline RuntimeScriptValue *GetHead () { return _head; }
185+ inline const RuntimeScriptValue *GetHead () const { return _head; }
186+ inline size_t GetSize () const { return _entries.data () + _entries.size () - _head; }
187+
188+ inline void Push (const RuntimeScriptValue &value)
184189 {
185- return &Entries[Head];
190+ if (_head == _entries.data ())
191+ {
192+ std::vector<RuntimeScriptValue> expansion (_entries.size () * 2 );
193+ std::copy (_entries.begin (), _entries.begin () + _entries.size (), expansion.begin () + _entries.size ());
194+ _entries = std::move (expansion);
195+ _head = _entries.data () + _entries.size () / 2 ;
196+ }
197+ *(--_head) = value;
186198 }
187- inline RuntimeScriptValue *GetTail ()
199+
200+ inline void PopCount (size_t count)
188201 {
189- return &Entries[Head + Count];
202+ count = std::min (count, static_cast <size_t >(_entries.data () + _entries.size () - _head));
203+ _head += count;
190204 }
191205
192- RuntimeScriptValue Entries[MAX_FUNC_PARAMS + 1 ];
193- int Head ;
194- int Count ;
206+ private:
207+ std::vector<RuntimeScriptValue> _entries ;
208+ RuntimeScriptValue *_head = nullptr ;
195209};
196210
197211
@@ -595,7 +609,7 @@ ccInstError ccInstance::Run(int32_t curpc)
595609 funcstart[0 ] = _pc;
596610 ccInstance *codeInst = _runningInst;
597611 ScriptOperation codeOp;
598- FunctionCallStack func_callstack;
612+ FunctionCallStack func_callstack ( 16 ) ;
599613#if DEBUG_CC_EXEC
600614 const bool dump_opcodes = ccGetOption (SCOPT_DEBUGRUN) != 0 ;
601615#endif
@@ -1252,14 +1266,14 @@ ccInstError ccInstance::Run(int32_t curpc)
12521266
12531267 // If there are nested CALLAS calls, the stack might
12541268 // contain 2 calls worth of parameters, so only
1255- // push args for this call
1269+ // push args for this call (??? - CHECKME)
12561270 if (num_args_to_func < 0 )
12571271 {
1258- num_args_to_func = func_callstack.Count ;
1272+ num_args_to_func = func_callstack.GetSize () ;
12591273 }
12601274 ASSERT_STACK_SPACE_VALS (num_args_to_func + 1 /* return address */ );
12611275 for (const RuntimeScriptValue *prval = func_callstack.GetHead () + num_args_to_func;
1262- prval > func_callstack.GetHead (); --prval )
1276+ -- prval >= func_callstack.GetHead ();)
12631277 {
12641278 PushValueToStack (*prval);
12651279 }
@@ -1295,7 +1309,7 @@ ccInstError ccInstance::Run(int32_t curpc)
12951309 next_call_needs_object = 0 ;
12961310
12971311 _pc = oldpc;
1298- was_just_callas = func_callstack.Count ;
1312+ was_just_callas = func_callstack.GetSize () ;
12991313 num_args_to_func = -1 ;
13001314 POP_CALL_STACK ();
13011315 break ;
@@ -1308,12 +1322,12 @@ ccInstError ccInstance::Run(int32_t curpc)
13081322 was_just_callas = -1 ;
13091323 if (num_args_to_func < 0 )
13101324 {
1311- num_args_to_func = func_callstack.Count ;
1325+ num_args_to_func = func_callstack.GetSize () ;
13121326 }
13131327
13141328 // Convert pointer arguments to simple types
13151329 for (RuntimeScriptValue *prval = func_callstack.GetHead () + num_args_to_func;
1316- prval > func_callstack.GetHead (); --prval )
1330+ -- prval >= func_callstack.GetHead ();)
13171331 {
13181332 prval->DirectPtr ();
13191333 }
@@ -1326,11 +1340,11 @@ ccInstError ccInstance::Run(int32_t curpc)
13261340 {
13271341 RuntimeScriptValue obj_rval = _registers[SREG_OP];
13281342 obj_rval.DirectPtrObj ();
1329- return_value = CallPluginFunction (reg1.Ptr , &obj_rval, func_callstack.GetHead () + 1 , num_args_to_func);
1343+ return_value = CallPluginFunction (reg1.Ptr , &obj_rval, func_callstack.GetHead (), num_args_to_func);
13301344 }
13311345 else
13321346 {
1333- return_value = CallPluginFunction (reg1.Ptr , nullptr , func_callstack.GetHead () + 1 , num_args_to_func);
1347+ return_value = CallPluginFunction (reg1.Ptr , nullptr , func_callstack.GetHead (), num_args_to_func);
13341348 }
13351349 }
13361350 else if (next_call_needs_object)
@@ -1340,7 +1354,7 @@ ccInstError ccInstance::Run(int32_t curpc)
13401354 {
13411355 RuntimeScriptValue obj_rval = _registers[SREG_OP];
13421356 obj_rval.DirectPtrObj ();
1343- return_value = reg1.ObjPfn (obj_rval.Ptr , func_callstack.GetHead () + 1 , num_args_to_func);
1357+ return_value = reg1.ObjPfn (obj_rval.Ptr , func_callstack.GetHead (), num_args_to_func);
13441358 }
13451359 else
13461360 {
@@ -1349,7 +1363,7 @@ ccInstError ccInstance::Run(int32_t curpc)
13491363 }
13501364 else if (reg1.Type == kScValStaticFunction )
13511365 {
1352- return_value = reg1.SPfn (func_callstack.GetHead () + 1 , num_args_to_func);
1366+ return_value = reg1.SPfn (func_callstack.GetHead (), num_args_to_func);
13531367 }
13541368 else if (reg1.Type == kScValObjectFunction )
13551369 {
@@ -1373,13 +1387,22 @@ ccInstError ccInstance::Run(int32_t curpc)
13731387 case SCMD_PUSHREAL:
13741388 {
13751389 const auto ®1 = _registers[codeOp.Arg1i ()];
1376- PushToFuncCallStack ( func_callstack, reg1);
1390+ func_callstack. Push ( reg1);
13771391 break ;
13781392 }
13791393 case SCMD_SUBREALSTACK:
13801394 {
1395+ // Drop arg_lit entries from the func_callstack
1396+ // TODO: cannot we just clear the func_callstack right after using it in call op?
1397+ // it does not seem like these values are needed for anything else.
13811398 const auto arg_lit = codeOp.Arg1i ();
1382- PopFromFuncCallStack (func_callstack, arg_lit);
1399+ if (func_callstack.GetSize () < static_cast <uint32_t >(arg_lit))
1400+ {
1401+ cc_error (" function callstack underflow" );
1402+ return kInstErr_Generic ;
1403+ }
1404+ func_callstack.PopCount (arg_lit);
1405+
13831406 if (was_just_callas >= 0 )
13841407 {
13851408 ASSERT_STACK_SIZE (arg_lit);
@@ -2137,7 +2160,8 @@ void ccInstance::CopyGlobalData(const std::vector<uint8_t> &data)
21372160 std::copy (data.begin (), data.begin () + copy_sz, _scriptData->globaldata .begin ());
21382161}
21392162
2140- RuntimeScriptValue ccInstance::CallPluginFunction (void *fn_addr, const RuntimeScriptValue *object, const RuntimeScriptValue *params, int param_count)
2163+ RuntimeScriptValue ccInstance::CallPluginFunction (void *fn_addr, const RuntimeScriptValue *object,
2164+ const RuntimeScriptValue *params, int param_count)
21412165{
21422166 assert (fn_addr);
21432167 assert (param_count == 0 || params);
@@ -2330,31 +2354,6 @@ RuntimeScriptValue ccInstance::GetStackPtrOffsetRw(const int32_t rw_offset)
23302354 return stack_ptr;
23312355}
23322356
2333- void ccInstance::PushToFuncCallStack (FunctionCallStack &func_callstack, const RuntimeScriptValue &rval)
2334- {
2335- if (func_callstack.Count >= MAX_FUNC_PARAMS)
2336- {
2337- cc_error (" function callstack overflow" );
2338- return ;
2339- }
2340-
2341- func_callstack.Entries [func_callstack.Head ] = rval;
2342- func_callstack.Head --;
2343- func_callstack.Count ++;
2344- }
2345-
2346- void ccInstance::PopFromFuncCallStack (FunctionCallStack &func_callstack, int32_t num_entries)
2347- {
2348- if (func_callstack.Count == 0 )
2349- {
2350- cc_error (" function callstack underflow" );
2351- return ;
2352- }
2353-
2354- func_callstack.Head += num_entries;
2355- func_callstack.Count -= num_entries;
2356- }
2357-
23582357// -----------------------------------------------------------------------------
23592358//
23602359// Script execution debug log.
0 commit comments