- changed VMValue to handle strings by reference.
This makes VMValue a real POD type with no hacky overloads and eliminates a lot of destructor code in all places that call a VM function. Due to the way this had to be handled, none of these destructors could be skipped because any value could have been a string. This required some minor changes in functions that passed a temporary FString into the VM to ensure that the temporary object lives long enough to be handled. The code generator had already been changed to deal with this in a previous commit. This is easily offset by the code savings and reduced maintenance needs elsewhere.
This commit is contained in:
parent
9bffe4ee50
commit
4417afd548
9 changed files with 55 additions and 93 deletions
|
|
@ -419,29 +419,21 @@ struct VMValue
|
|||
double f;
|
||||
struct { int pad[3]; VM_UBYTE Type; };
|
||||
struct { int foo[4]; } biggest;
|
||||
const FString *sp;
|
||||
};
|
||||
|
||||
// Unfortunately, FString cannot be used directly.
|
||||
// Fortunately, it is relatively simple.
|
||||
FString &s() { return *(FString *)&a; }
|
||||
const FString &s() const { return *(FString *)&a; }
|
||||
const FString &s() const { return *sp; }
|
||||
|
||||
VMValue()
|
||||
{
|
||||
a = NULL;
|
||||
Type = REGT_NIL;
|
||||
}
|
||||
~VMValue()
|
||||
{
|
||||
Kill();
|
||||
}
|
||||
VMValue(const VMValue &o)
|
||||
{
|
||||
biggest = o.biggest;
|
||||
if (Type == REGT_STRING)
|
||||
{
|
||||
::new(&s()) FString(o.s());
|
||||
}
|
||||
}
|
||||
VMValue(int v)
|
||||
{
|
||||
|
|
@ -453,14 +445,12 @@ struct VMValue
|
|||
f = v;
|
||||
Type = REGT_FLOAT;
|
||||
}
|
||||
VMValue(const char *s)
|
||||
VMValue(const char *s) = delete;
|
||||
VMValue(const FString &s) = delete;
|
||||
|
||||
VMValue(const FString *s)
|
||||
{
|
||||
::new(&a) FString(s);
|
||||
Type = REGT_STRING;
|
||||
}
|
||||
VMValue(const FString &s)
|
||||
{
|
||||
::new(&a) FString(s);
|
||||
sp = s;
|
||||
Type = REGT_STRING;
|
||||
}
|
||||
VMValue(DObject *v)
|
||||
|
|
@ -483,68 +473,31 @@ struct VMValue
|
|||
}
|
||||
VMValue &operator=(const VMValue &o)
|
||||
{
|
||||
if (o.Type == REGT_STRING)
|
||||
{
|
||||
if (Type == REGT_STRING)
|
||||
{
|
||||
s() = o.s();
|
||||
}
|
||||
else
|
||||
{
|
||||
new(&s()) FString(o.s());
|
||||
Type = REGT_STRING;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Kill();
|
||||
biggest = o.biggest;
|
||||
}
|
||||
biggest = o.biggest;
|
||||
return *this;
|
||||
}
|
||||
VMValue &operator=(int v)
|
||||
{
|
||||
Kill();
|
||||
i = v;
|
||||
Type = REGT_INT;
|
||||
return *this;
|
||||
}
|
||||
VMValue &operator=(double v)
|
||||
{
|
||||
Kill();
|
||||
f = v;
|
||||
Type = REGT_FLOAT;
|
||||
return *this;
|
||||
}
|
||||
VMValue &operator=(const FString &v)
|
||||
VMValue &operator=(const FString *v)
|
||||
{
|
||||
if (Type == REGT_STRING)
|
||||
{
|
||||
s() = v;
|
||||
}
|
||||
else
|
||||
{
|
||||
::new(&s()) FString(v);
|
||||
Type = REGT_STRING;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
VMValue &operator=(const char *v)
|
||||
{
|
||||
if (Type == REGT_STRING)
|
||||
{
|
||||
s() = v;
|
||||
}
|
||||
else
|
||||
{
|
||||
::new(&s()) FString(v);
|
||||
Type = REGT_STRING;
|
||||
}
|
||||
sp = v;
|
||||
Type = REGT_STRING;
|
||||
return *this;
|
||||
}
|
||||
VMValue &operator=(const FString &v) = delete;
|
||||
VMValue &operator=(const char *v) = delete;
|
||||
VMValue &operator=(DObject *v)
|
||||
{
|
||||
Kill();
|
||||
a = v;
|
||||
atag = ATAG_OBJECT;
|
||||
Type = REGT_POINTER;
|
||||
|
|
@ -584,13 +537,6 @@ struct VMValue
|
|||
// FIXME
|
||||
return 0;
|
||||
}
|
||||
void Kill()
|
||||
{
|
||||
if (Type == REGT_STRING)
|
||||
{
|
||||
s().~FString();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class VMFunction
|
||||
|
|
|
|||
|
|
@ -583,7 +583,7 @@ begin:
|
|||
break;
|
||||
case REGT_STRING:
|
||||
assert(C < f->NumRegS);
|
||||
::new(param) VMValue(reg.s[C]);
|
||||
::new(param) VMValue(®.s[C]);
|
||||
break;
|
||||
case REGT_STRING | REGT_ADDROF:
|
||||
assert(C < f->NumRegS);
|
||||
|
|
@ -591,7 +591,7 @@ begin:
|
|||
break;
|
||||
case REGT_STRING | REGT_KONST:
|
||||
assert(C < sfunc->NumKonstS);
|
||||
::new(param) VMValue(konsts[C]);
|
||||
::new(param) VMValue(&konsts[C]);
|
||||
break;
|
||||
case REGT_POINTER:
|
||||
assert(C < f->NumRegA);
|
||||
|
|
@ -707,10 +707,7 @@ begin:
|
|||
stack->PopFrame();
|
||||
}
|
||||
assert(numret == C && "Number of parameters returned differs from what was expected by the caller");
|
||||
for (b = B; b != 0; --b)
|
||||
{
|
||||
reg.param[--f->NumParam].~VMValue();
|
||||
}
|
||||
f->NumParam -= B;
|
||||
pc += C; // Skip RESULTs
|
||||
}
|
||||
NEXTOP;
|
||||
|
|
|
|||
|
|
@ -384,12 +384,6 @@ VMFrame *VMFrameStack::PopFrame()
|
|||
{
|
||||
(regs++)->~FString();
|
||||
}
|
||||
// Free any parameters this frame left behind.
|
||||
VMValue *param = frame->GetParam();
|
||||
for (int i = frame->NumParam; i != 0; --i)
|
||||
{
|
||||
(param++)->~VMValue();
|
||||
}
|
||||
VMFrame *parent = frame->ParentFrame;
|
||||
if (parent == NULL)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@
|
|||
#include "gdtoa.h"
|
||||
#include "backend/vmbuilder.h"
|
||||
|
||||
FSharedStringArena VMStringConstants;
|
||||
|
||||
static int GetIntConst(FxExpression *ex, FCompileContext &ctx)
|
||||
{
|
||||
ex = new FxIntCast(ex, false);
|
||||
|
|
@ -2555,7 +2557,8 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
|||
break;
|
||||
|
||||
case REGT_STRING:
|
||||
vmval[0] = cnst->GetValue().GetString();
|
||||
// We need a reference to something permanently stored here.
|
||||
vmval[0] = VMStringConstants.Alloc(cnst->GetValue().GetString());
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue