Skip to content

Commit cb7ea33

Browse files
committed
Engine: support (theoretically) unlimited script function parameters
1 parent e59c26a commit cb7ea33

File tree

2 files changed

+52
-59
lines changed

2 files changed

+52
-59
lines changed

Engine/script/cc_instance.cpp

Lines changed: 52 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
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.
175175
struct 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 &reg1 = _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.

Engine/script/cc_instance.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,6 @@ struct ScriptVariable
100100
RuntimeScriptValue RValue;
101101
};
102102

103-
struct FunctionCallStack;
104-
105103
struct ScriptPosition
106104
{
107105
ScriptPosition()
@@ -235,10 +233,6 @@ class ccInstance
235233
// Offset is in data bytes; program stack ptr is __not__ changed
236234
RuntimeScriptValue GetStackPtrOffsetRw(int32_t rw_offset);
237235

238-
// Function call stack processing
239-
void PushToFuncCallStack(FunctionCallStack &func_callstack, const RuntimeScriptValue &rval);
240-
void PopFromFuncCallStack(FunctionCallStack &func_callstack, int32_t num_entries);
241-
242236
// Script execution debug log.
243237
#if (DEBUG_CC_EXEC)
244238
// Opens log for dumping execution steps

0 commit comments

Comments
 (0)