- 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:
Christoph Oelckers 2017-03-22 01:44:56 +01:00
commit 4417afd548
9 changed files with 55 additions and 93 deletions

View file

@ -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