Skip to content

Commit 10fb3ca

Browse files
Fix suspended Squirrel thread and generator save/restore
1 parent ece9232 commit 10fb3ca

File tree

1 file changed

+102
-66
lines changed

1 file changed

+102
-66
lines changed

sp/src/vscript/vscript_squirrel.cpp

Lines changed: 102 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,14 @@ class SquirrelVM : public IScriptVM
284284
WriteObject( (const SQObjectPtr&)obj, pBuffer, writeState );
285285
}
286286

287+
void WriteObject( SQGenerator *pObj, CUtlBuffer* pBuffer, WriteStateMap& writeState )
288+
{
289+
SQObject obj;
290+
obj._type = OT_GENERATOR;
291+
obj._unVal.pUserPointer = pObj;
292+
WriteObject( (const SQObjectPtr&)obj, pBuffer, writeState );
293+
}
294+
287295
void ReadObject( SQObjectPtr &obj, CUtlBuffer* pBuffer, ReadStateMap& readState );
288296

289297
// Do not implicity add/remove ref
@@ -3671,23 +3679,25 @@ void SquirrelVM::WriteObject( const SQObjectPtr &obj, CUtlBuffer* pBuffer, Write
36713679

36723680
if ( pThis->_callsstacksize )
36733681
{
3674-
int stackidx = -1;
3675-
36763682
for ( int i = pThis->_callsstacksize; i--; )
36773683
{
36783684
const SQVM::CallInfo *ci = &pThis->_callsstack[i];
36793685

3680-
if ( pThis->ci == ci )
3681-
stackidx = i;
3682-
3683-
Assert( !ci->_generator );
3684-
Assert( ci->_ip && ci->_ip >= ci->_closure._unVal.pClosure->_function->_instructions );
3686+
Assert( ci->_ip >= ci->_closure._unVal.pClosure->_function->_instructions &&
3687+
ci->_ip < ci->_closure._unVal.pClosure->_function->_instructions +
3688+
ci->_closure._unVal.pClosure->_function->_ninstructions );
36853689
Assert( pThis->_etraps.size() >= (SQUnsignedInteger)ci->_etraps );
36863690
Assert( ci->_closure._type == OT_CLOSURE && ci->_closure._unVal.pClosure );
36873691

36883692
WriteObject( ci->_closure, pBuffer, writeState );
36893693

3690-
int offset = (int)ci->_ip - (int)ci->_closure._unVal.pClosure->_function->_instructions;
3694+
Assert( ci->_ip - ci->_closure._unVal.pClosure->_function->_instructions <= INT_MAX );
3695+
3696+
pBuffer->PutChar( ci->_generator != 0 );
3697+
if ( ci->_generator )
3698+
WriteObject( ci->_generator, pBuffer, writeState );
3699+
3700+
int offset = ci->_ip - ci->_closure._unVal.pClosure->_function->_instructions;
36913701
pBuffer->PutInt( offset );
36923702
pBuffer->PutInt( ci->_etraps );
36933703
pBuffer->PutInt( ci->_prevstkbase );
@@ -3699,13 +3709,15 @@ void SquirrelVM::WriteObject( const SQObjectPtr &obj, CUtlBuffer* pBuffer, Write
36993709
for ( int j = ci->_etraps; j--; )
37003710
{
37013711
const SQExceptionTrap &et = pThis->_etraps[j];
3702-
pBuffer->PutInt( et._extarget );
3703-
pBuffer->PutInt( et._stackbase );
37043712
pBuffer->PutInt( et._stacksize );
3705-
Assert( et._ip == ci->_ip );
3713+
pBuffer->PutInt( et._stackbase );
3714+
Assert( et._ip - ci->_ip <= INT_MAX );
3715+
pBuffer->PutInt( et._ip - ci->_ip );
3716+
pBuffer->PutInt( et._extarget );
37063717
}
37073718
}
37083719

3720+
int stackidx = pThis->ci - pThis->_callsstack;
37093721
Assert( stackidx >= 0 && stackidx < pThis->_callsstacksize );
37103722
pBuffer->PutInt( stackidx );
37113723
}
@@ -3736,29 +3748,37 @@ void SquirrelVM::WriteObject( const SQObjectPtr &obj, CUtlBuffer* pBuffer, Write
37363748

37373749
WriteObject( pThis->_closure, pBuffer, writeState );
37383750

3739-
const SQVM::CallInfo &ci = pThis->_ci;
3751+
const SQVM::CallInfo *ci = &pThis->_ci;
3752+
3753+
Assert( pThis->_closure._unVal.pClosure == ci->_closure._unVal.pClosure );
3754+
Assert( ci->_ip >= ci->_closure._unVal.pClosure->_function->_instructions &&
3755+
ci->_ip < ci->_closure._unVal.pClosure->_function->_instructions +
3756+
ci->_closure._unVal.pClosure->_function->_ninstructions );
3757+
Assert( pThis->_etraps.size() >= (SQUnsignedInteger)ci->_etraps );
37403758

3741-
Assert( !ci._generator );
3742-
Assert( pThis->_closure._unVal.pClosure == ci._closure._unVal.pClosure );
3743-
Assert( ci._ip && ci._ip >= ci._closure._unVal.pClosure->_function->_instructions );
3744-
Assert( pThis->_etraps.size() >= (SQUnsignedInteger)ci._etraps );
3759+
Assert( ci->_ip - ci->_closure._unVal.pClosure->_function->_instructions <= INT_MAX );
37453760

3746-
int offset = (int)ci._ip - (int)ci._closure._unVal.pClosure->_function->_instructions;
3761+
pBuffer->PutChar( ci->_generator != 0 );
3762+
if ( ci->_generator )
3763+
WriteObject( ci->_generator, pBuffer, writeState );
3764+
3765+
int offset = ci->_ip - ci->_closure._unVal.pClosure->_function->_instructions;
37473766
pBuffer->PutInt( offset );
3748-
pBuffer->PutInt( ci._etraps );
3749-
pBuffer->PutInt( ci._prevstkbase );
3750-
pBuffer->PutInt( ci._prevtop );
3751-
pBuffer->PutInt( ci._target );
3752-
pBuffer->PutInt( ci._ncalls );
3753-
pBuffer->PutChar( ci._root );
3767+
pBuffer->PutInt( ci->_etraps );
3768+
pBuffer->PutInt( ci->_prevstkbase );
3769+
pBuffer->PutInt( ci->_prevtop );
3770+
pBuffer->PutInt( ci->_target );
3771+
pBuffer->PutInt( ci->_ncalls );
3772+
pBuffer->PutChar( ci->_root );
37543773

3755-
for ( int j = ci._etraps; j--; )
3774+
for ( int j = ci->_etraps; j--; )
37563775
{
37573776
const SQExceptionTrap &et = pThis->_etraps[j];
3758-
pBuffer->PutInt( et._extarget );
3759-
pBuffer->PutInt( et._stackbase );
37603777
pBuffer->PutInt( et._stacksize );
3761-
Assert( et._ip == ci._ip );
3778+
pBuffer->PutInt( et._stackbase );
3779+
Assert( et._ip - ci->_ip <= INT_MAX );
3780+
pBuffer->PutInt( et._ip - ci->_ip );
3781+
pBuffer->PutInt( et._extarget );
37623782
}
37633783

37643784
int stacksize = pThis->_stack.size();
@@ -4331,23 +4351,31 @@ void SquirrelVM::ReadObject( SQObjectPtr &pObj, CUtlBuffer* pBuffer, ReadStateMa
43314351
ReadObject( closure, pBuffer, readState );
43324352
Assert( closure._type == OT_CLOSURE && closure._unVal.pClosure );
43334353

4354+
if ( pBuffer->GetChar() )
4355+
{
4356+
SQObject generator;
4357+
ReadObject( generator, pBuffer, readState );
4358+
Assert( generator._type == OT_GENERATOR && generator._unVal.pGenerator );
4359+
ci->_generator = generator._unVal.pGenerator;
4360+
}
4361+
else
4362+
{
4363+
ci->_generator = NULL;
4364+
}
4365+
43344366
int offset = pBuffer->GetInt();
4335-
int funcsize = sizeof(SQInstruction) * closure._unVal.pClosure->_function->_ninstructions;
4336-
int start = (int)(closure._unVal.pClosure->_function->_instructions);
4337-
int pos = start + offset;
4338-
ci->_ip = (SQInstruction*)pos;
4367+
SQInstruction *start = closure._unVal.pClosure->_function->_instructions;
4368+
SQInstruction *end = start + closure._unVal.pClosure->_function->_ninstructions;
4369+
SQInstruction *pos = start + offset;
43394370

4340-
Assert( pos < (start + funcsize) );
4371+
Assert( pos >= start && pos < end );
43414372

4342-
// don't read past boundary
4343-
if ( pos >= (start + funcsize) )
4344-
{
4345-
ci->_ip = (SQInstruction*)start;
4346-
}
4373+
if ( pos < start || pos >= end )
4374+
pos = start;
43474375

4376+
ci->_ip = pos;
43484377
ci->_literals = closure._unVal.pClosure->_function->_literals;
43494378
ci->_closure = closure;
4350-
ci->_generator = NULL;
43514379
ci->_etraps = pBuffer->GetInt();
43524380
ci->_prevstkbase = pBuffer->GetInt();
43534381
ci->_prevtop = pBuffer->GetInt();
@@ -4360,10 +4388,10 @@ void SquirrelVM::ReadObject( SQObjectPtr &pObj, CUtlBuffer* pBuffer, ReadStateMa
43604388
for ( int j = ci->_etraps; j--; )
43614389
{
43624390
SQExceptionTrap &et = pThis->_etraps[j];
4363-
et._extarget = pBuffer->GetInt();
4364-
et._stackbase = pBuffer->GetInt();
43654391
et._stacksize = pBuffer->GetInt();
4366-
et._ip = ci->_ip;
4392+
et._stackbase = pBuffer->GetInt();
4393+
et._ip = ci->_ip + pBuffer->GetInt();
4394+
et._extarget = pBuffer->GetInt();
43674395
}
43684396
}
43694397

@@ -4410,41 +4438,49 @@ void SquirrelVM::ReadObject( SQObjectPtr &pObj, CUtlBuffer* pBuffer, ReadStateMa
44104438

44114439
pThis->_state = (SQGenerator::SQGeneratorState)state;
44124440

4413-
SQVM::CallInfo &ci = pThis->_ci;
4441+
SQVM::CallInfo *ci = &pThis->_ci;
4442+
4443+
if ( pBuffer->GetChar() )
4444+
{
4445+
SQObject generator;
4446+
ReadObject( generator, pBuffer, readState );
4447+
Assert( generator._type == OT_GENERATOR && generator._unVal.pGenerator );
4448+
ci->_generator = generator._unVal.pGenerator;
4449+
}
4450+
else
4451+
{
4452+
ci->_generator = NULL;
4453+
}
44144454

44154455
int offset = pBuffer->GetInt();
4416-
int funcsize = sizeof(SQInstruction) * closure._unVal.pClosure->_function->_ninstructions;
4417-
int start = (int)(closure._unVal.pClosure->_function->_instructions);
4418-
int pos = start + offset;
4419-
ci._ip = (SQInstruction*)pos;
4456+
SQInstruction *start = closure._unVal.pClosure->_function->_instructions;
4457+
SQInstruction *end = start + closure._unVal.pClosure->_function->_ninstructions;
4458+
SQInstruction *pos = start + offset;
44204459

4421-
Assert( pos < (start + funcsize) );
4460+
Assert( pos >= start && pos < end );
44224461

4423-
// don't read past boundary
4424-
if ( pos >= (start + funcsize) )
4425-
{
4426-
ci._ip = (SQInstruction*)start;
4427-
}
4462+
if ( pos < start || pos >= end )
4463+
pos = start;
44284464

4429-
ci._literals = closure._unVal.pClosure->_function->_literals;
4430-
ci._closure = closure;
4431-
ci._generator = NULL;
4432-
ci._etraps = pBuffer->GetInt();
4433-
ci._prevstkbase = pBuffer->GetInt();
4434-
ci._prevtop = pBuffer->GetInt();
4435-
ci._target = pBuffer->GetInt();
4436-
ci._ncalls = pBuffer->GetInt();
4437-
ci._root = pBuffer->GetChar();
4465+
ci->_ip = pos;
4466+
ci->_literals = closure._unVal.pClosure->_function->_literals;
4467+
ci->_closure = closure;
4468+
ci->_etraps = pBuffer->GetInt();
4469+
ci->_prevstkbase = pBuffer->GetInt();
4470+
ci->_prevtop = pBuffer->GetInt();
4471+
ci->_target = pBuffer->GetInt();
4472+
ci->_ncalls = pBuffer->GetInt();
4473+
ci->_root = pBuffer->GetChar();
44384474

4439-
pThis->_etraps.resize( ci._etraps );
4475+
pThis->_etraps.resize( ci->_etraps );
44404476

4441-
for ( int j = ci._etraps; j--; )
4477+
for ( int j = ci->_etraps; j--; )
44424478
{
44434479
SQExceptionTrap &et = pThis->_etraps[j];
4444-
et._extarget = pBuffer->GetInt();
4445-
et._stackbase = pBuffer->GetInt();
44464480
et._stacksize = pBuffer->GetInt();
4447-
et._ip = ci._ip;
4481+
et._stackbase = pBuffer->GetInt();
4482+
et._ip = ci->_ip + pBuffer->GetInt();
4483+
et._extarget = pBuffer->GetInt();
44484484
}
44494485

44504486
int stacksize = pBuffer->GetInt();

0 commit comments

Comments
 (0)