Waldek Hebisch wrote:
Peter N Lewis wrote:
Who calls InvalidObjectError and why (other than the obvious!).
I searched the code but couldn't find any enlightening references as to who actually detects an invalid object and calls this...?
BTW, it's called from compiler-generated code (not from RTS routines). The relevant line is in objects.c:
convert (TREE_TYPE (fun), build_predef_call (p_InvalidObjectError, NULL_TREE)), fun));
It is done before virtual method calls.
AFAIK InvalidObjectError is only called when you give `-fobject-checking' option. In this case the compiler emits inline code to check that virtual method table looks sane (exists and does not correspond to an abstract object).
Where "VMT exists" means that its VMT pointer is not nil, and in the structure it points to, the "NegatedSize" field contains the negative value of its "Size" field -- as a check against unintialized VMT pointers etc., not 100% foolproof, of course, and the same that BP does, BTW.
It doesn't actually check for abstract object types, but now that you mention it, I think it should. Though it's not easy to get an object with a VMT pointer to an abstract type (the compiler will normally prevent it), it is possible with some tricks (and of course, due to dangling pointers, memory corruption etc., which such runtime checks are meant to catch).
There are several ways to achieve it. One is to check for Size = 0. Since all object types in GPC have at least the VMT pointer, their size can never be 0, and GPC explicitly sets the Size field to 0 for abstract types. Another way is to produce an intentional mismatch of the NegatedSize field for abstract type VMTs. The following patch does the latter, as it avoids one more runtime check, and only changes the initialization of abstract VMTs.
Frank