[webkit-dev] Question about javascriptcore garbage collection
Krzysztof Kowalczyk
kkowalczyk at gmail.com
Sat Sep 3 12:56:51 PDT 2005
To answer my own question: the problem is that ValueImp has no virtual
functions (=> no virtual table) and AllocatedValueImp does. That means
that cast between ValueImp* and AllocatedValueImp* involve
adding/substracting 4 bytes to the pointer of the object, since, at
least in visual c, pointer to vtable is the first member of the
object. AllocatedValueImp * is allocated at CollectorCell boundary,
but when casted to ValueImp * it is no longer recognized by GC.
Here's a small test program that shows this. See the last 3 addresses
in the output for how the address changes depending on the type of
pointer.
So I devised another way of fixing the problem: simply marking
ValueImp::~ValueImp as virtual also fixes crashes for me.
So the remaining question is: what is the behaviour on Mac/gcc ? I
would aprecciate if a mac person would run this and posted the
results. On my win machine it says:
C:\kjk\src\ext\libs\webcore-apple\JavaScriptCore>inh-test.exe
justVal : 0x322bc0
num : 0x322bd0
numCasted : 0x322bd4
numDowncasted : 0x322bd0
jsNumber num : 0x320f60
jsNumberAsVI : 0x320f64
jsNumberAsAVI : 0x320f60
On a separate note: I don't see why ValueImp couldn't be eliminated
alltogether and its functionality folded in AllocatedValueImp (which
would also solve the problem).
Test program:
#include <stdio.h>
class ValueImp {
friend class AllocatedValueImp; // so it can derive from this class
public:
ValueImp() {};
~ValueImp() {};
void mark();
bool marked() const;
AllocatedValueImp *downcast();
const AllocatedValueImp *downcast() const;
};
class SimpleNumber {
public:
static inline bool is(const ValueImp *imp) { return false; }
};
class AllocatedValueImp : public ValueImp {
friend class NumberImp;
private:
AllocatedValueImp() {};
virtual ~AllocatedValueImp() {};
public:
virtual void mark();
bool marked() const;
private:
bool m_marked;
};
class NumberImp : public AllocatedValueImp {
public:
NumberImp(double v) : val(v) { }
private:
virtual ~NumberImp() {};
NumberImp() { }
double val;
};
inline void ValueImp::mark()
{
if (!SimpleNumber::is(this))
downcast()->mark();
}
inline bool ValueImp::marked() const
{
return SimpleNumber::is(this) || downcast()->marked();
}
inline AllocatedValueImp *ValueImp::downcast()
{
return static_cast<AllocatedValueImp *>(this);
}
inline const AllocatedValueImp *ValueImp::downcast() const
{
return static_cast<const AllocatedValueImp *>(this);
}
inline bool AllocatedValueImp::marked() const
{
return m_marked;
}
inline void AllocatedValueImp::mark()
{
m_marked = true;
}
ValueImp *jsNumber(double d)
{
NumberImp *num = new NumberImp(d);
printf("jsNumber num : 0x%x\n", num);
return num;
}
int main(int argc, char **argv)
{
ValueImp *justVal = new ValueImp();
AllocatedValueImp *num = new NumberImp(15.0);
ValueImp *numCasted = static_cast<ValueImp*>(num);
AllocatedValueImp *numDowncasted = numCasted->downcast();
printf("justVal : 0x%x\n", justVal);
printf("num : 0x%x\n", num);
printf("numCasted : 0x%x\n", numCasted);
printf("numDowncasted : 0x%x\n", numDowncasted);
ValueImp *jsNumberAsValueImp = jsNumber(5.0);
printf("jsNumberAsVI : 0x%x\n", jsNumberAsValueImp);
AllocatedValueImp *asAllocatedValueImp = jsNumberAsValueImp->downcast();
printf("jsNumberAsAVI : 0x%x\n", asAllocatedValueImp);
return 0;
}
More information about the webkit-dev
mailing list