Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/hx/Scriptable.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ class CppiaLoadedModule_obj : public ::hx::Object
virtual void run() = 0;
virtual void boot() = 0;
virtual ::hx::Class resolveClass( ::String inName) = 0;
virtual void unload() { }
};
typedef ::hx::ObjectPtr<CppiaLoadedModule_obj> CppiaLoadedModule;

Expand Down
26 changes: 26 additions & 0 deletions src/hx/cppia/Cppia.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ typedef std::map<int,CppiaStackVar *> CppiaStackVarMap;

extern String sInvalidArgCount;

void _hx_cppia_track_expr(void *inExpr);
void _hx_cppia_untrack_expr(void *inExpr);

struct CppiaExpr
{
int line;
Expand All @@ -161,6 +164,18 @@ struct CppiaExpr
const char *functionName;
int haxeTypeId;

void *operator new(size_t inSize)
{
void *result = ::operator new(inSize);
_hx_cppia_track_expr(result);
return result;
}

void operator delete(void *inPtr)
{
_hx_cppia_untrack_expr(inPtr);
::operator delete(inPtr);
}

CppiaExpr() : line(0), filename(0), className(0), functionName(0)
{
Expand Down Expand Up @@ -283,6 +298,8 @@ struct ScriptCallable : public CppiaDynamicExpr
int captureSize;


void deactivate();

ScriptCallable(CppiaStream &stream);
ScriptCallable(CppiaExpr *inBody);
ScriptCallable(CppiaModule &inModule,ScriptNamedFunction *inFunction);
Expand Down Expand Up @@ -372,7 +389,10 @@ class CppiaModule
std::vector< TypeData * > types;
std::vector< CppiaClassInfo * > classes;
std::vector< CppiaExpr * > markable;

hx::UnorderedSet< CppiaExpr * > allExprs;
hx::UnorderedSet<int> allFileIds;

typedef std::map< std::string, int > InterfaceSlots;
InterfaceSlots interfaceSlots;

Expand All @@ -384,9 +404,12 @@ class CppiaModule

ScriptCallable *main;

bool unloaded;

CppiaModule();
~CppiaModule();

void unload();
void link();
void compile();
void setDebug(CppiaExpr *outExpr, int inFileId, int inLine);
Expand Down Expand Up @@ -650,6 +673,8 @@ class CppiaClassInfo
bool containsPointers;
int dynamicMapOffset;
int interfaceSlotSize;
int vtableSlotCount;
bool unloaded;
void **vtable;
std::string name;
std::map<int, void *> interfaceScriptTables;
Expand Down Expand Up @@ -704,6 +729,7 @@ class CppiaClassInfo

void link();
void linkTypes();
void deactivate();


inline bool isNativeProperty(const String &inString);
Expand Down
76 changes: 71 additions & 5 deletions src/hx/cppia/CppiaClasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ struct CppiaEnumConstructor
int nameId;
int typeId;
};

std::vector<Arg> args;
CppiaClassInfo *classInfo;
int nameId;
Expand All @@ -49,7 +49,7 @@ struct CppiaEnumConstructor
int typeId = inStream.getInt();
args.push_back( Arg(nameId,typeId) );
}

}
hx::Object *create( Array<Dynamic> inArgs )
{
Expand Down Expand Up @@ -173,7 +173,7 @@ void SLJIT_CALL createEnum(hx::Class_obj *inClass, String *inName, int inArgs)
for(int i=0;i<inArgs;i++)
args[i] = Dynamic(base[i]);
base[0] = inClass->ConstructEnum(*inName, args).mPtr;

CATCH_NATIVE
ctx->pointer = oldPointer;
}
Expand Down Expand Up @@ -345,6 +345,8 @@ CppiaClassInfo::CppiaClassInfo(CppiaModule &inCppia) : cppia(inCppia)
enumMeta = 0;
isInterface = false;
interfaceSlotSize = 0;
vtableSlotCount = 0;
unloaded = false;
superType = 0;
typeId = 0;
vtable = 0;
Expand All @@ -363,6 +365,9 @@ class CppiaClass *getCppiaClass()

hx::Object *CppiaClassInfo::createInstance(CppiaCtx *ctx,Expressions &inArgs, bool inCallNew)
{
if (unloaded)
hx::Throw( HX_CSTRING("Cannot construct ") + String(name.c_str()) + HX_CSTRING(", its class was unloaded") );

hx::Object *obj = haxeBase->factory(vtable,extraData);

createDynamicFunctions(obj);
Expand All @@ -375,6 +380,9 @@ hx::Object *CppiaClassInfo::createInstance(CppiaCtx *ctx,Expressions &inArgs, bo

hx::Object *CppiaClassInfo::createInstance(CppiaCtx *ctx,Array<Dynamic> &inArgs)
{
if (unloaded)
hx::Throw( HX_CSTRING("Cannot construct ") + String(name.c_str()) + HX_CSTRING(", its class was unloaded") );

hx::Object *obj = haxeBase->factory(vtable,extraData);

createDynamicFunctions(obj);
Expand Down Expand Up @@ -678,6 +686,52 @@ CppiaEnumConstructor *CppiaClassInfo::findEnum(int inFieldId)
return 0;
}

// Drops the class back to its host base without freeing anything that a raw pointer still reaches.
void CppiaClassInfo::deactivate()
{
if (unloaded)
return;
unloaded = true;

if (vtable)
{
void **base = vtable - interfaceSlotSize - 1;
int count = vtableSlotCount + 2 + interfaceSlotSize;
memset(base, 0, sizeof(void *)*count);
vtable[-1] = this;
}

// These all hold ScriptCallable pointers into the expression graph that is about to be freed.
memberFunctions.clear();
staticFunctions.clear();
memberGetters.clear();
memberSetters.clear();
staticGetters.clear();
staticSetters.clear();
newFunc = 0;
initExpr = 0;
enumMeta = 0;

// Var initialisers are expressions, and nothing runs them again after this point.
for(int i=0;i<memberVars.size();i++)
memberVars[i]->init = 0;
for(int i=0;i<staticVars.size();i++)
staticVars[i]->init = 0;

// Statics are still marked through the module, so clearing them is what actually releases the memory.
for(int i=0;i<staticVars.size();i++)
{
staticVars[i]->objVal = null();
staticVars[i]->stringVal = String();
}
for(int i=0;i<staticDynamicFunctions.size();i++)
{
staticDynamicFunctions[i]->objVal = null();
staticDynamicFunctions[i]->stringVal = String();
}
}


void CppiaClassInfo::mark(hx::MarkContext *__inCtx)
{
HX_MARK_MEMBER(mClass);
Expand Down Expand Up @@ -1056,7 +1110,7 @@ void CppiaClassInfo::linkTypes()


DBGLOG(" script member vars size = %d\n", extraData);

for(int i=0;i<staticVars.size();i++)
{
DBGLOG(" link static var %s\n", cppia.identStr(staticVars[i]->nameId));
Expand Down Expand Up @@ -1162,6 +1216,7 @@ void CppiaClassInfo::linkTypes()
if (interfaceSlotSize)
interfaceSlotSize++;

vtableSlotCount = vtableSlot;
vtable = new void*[vtableSlot + 2 + interfaceSlotSize];
memset(vtable, 0, sizeof(void *)*(vtableSlot+2+interfaceSlotSize));
vtable += interfaceSlotSize;
Expand Down Expand Up @@ -1352,7 +1407,7 @@ void CppiaClassInfo::init(CppiaCtx *ctx, int inPhase)
unsigned char *pointer = ctx->pointer;
ctx->push( (hx::Object *) 0 ); // this
AutoStack save(ctx,pointer);

if (inPhase==0)
{
for(int i=0;i<staticVars.size();i++)
Expand Down Expand Up @@ -1382,6 +1437,10 @@ void CppiaClassInfo::init(CppiaCtx *ctx, int inPhase)

Dynamic CppiaClassInfo::getStaticValue(const String &inName,hx::PropertyAccess inCallProp)
{
if (unloaded)
hx::Throw( HX_CSTRING("Cannot read ") + String(name.c_str()) + HX_CSTRING(".") + inName +
HX_CSTRING(", its class was unloaded") );

if (inCallProp==paccDynamic)
inCallProp = isNativeProperty(inName) ? paccAlways : paccNever;
if (inCallProp)
Expand Down Expand Up @@ -1423,6 +1482,9 @@ Dynamic CppiaClassInfo::getStaticValue(const String &inName,hx::PropertyAccess

bool CppiaClassInfo::hasStaticValue(const String &inName)
{
if (unloaded)
return false;

if (findStaticGetter(inName))
return true;

Expand All @@ -1448,6 +1510,10 @@ bool CppiaClassInfo::hasStaticValue(const String &inName)

Dynamic CppiaClassInfo::setStaticValue(const String &inName,const Dynamic &inValue ,hx::PropertyAccess inCallProp)
{
if (unloaded)
hx::Throw( HX_CSTRING("Cannot write ") + String(name.c_str()) + HX_CSTRING(".") + inName +
HX_CSTRING(", its class was unloaded") );

if (inCallProp==paccDynamic)
inCallProp = isNativeProperty(inName) ? paccAlways : paccNever;
if (inCallProp)
Expand Down
21 changes: 21 additions & 0 deletions src/hx/cppia/CppiaFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,27 @@ void ScriptCallable::compile()
}
#endif

struct UnloadedBody : public CppiaExpr
{
const char *getName() HXCPP_OVERRIDE { return "UnloadedBody"; }

void runVoid(CppiaCtx *ctx) HXCPP_OVERRIDE
{
hx::Throw( HX_CSTRING("Called a function from a cppia class that has been unloaded") );
}
};

static UnloadedBody sUnloadedBody;

void ScriptCallable::deactivate()
{
body = &sUnloadedBody;
#ifdef CPPIA_JIT
compiled = 0;
#endif
}


// --- CppiaClosure ----


Expand Down
Loading
Loading