Beispiel #1
0
//----------------------------------------------------------------//
int MOAILuaObject::_gc ( lua_State* L ) {

	MOAILuaState state ( L );
	MOAILuaObject* self = ( MOAILuaObject* )state.GetPtrUserData ( 1 );
	self->mCollected = true;
	
	if ( MOAILuaRuntime::IsValid ()) {
	
		if ( self->mFinalizer ) {
			self->mFinalizer.PushRef ( state );
			if ( state.IsType ( -1, LUA_TFUNCTION )) {
				state.DebugCall ( 0, 0 );
			}
			else if ( state.IsType ( -1, LUA_TSTRING )) {
				printf ( "%s\n", state.GetValue < cc8* >( -1, "" ));
			}
			else {
				state.Pop ( 1 );
			}
			self->mFinalizer.Clear ();
		}
		
		if ( MOAILuaRuntime::Get ().mReportGC ) {
			printf ( "GC %s <%p>\n", self->TypeName (), self );
		}
	}
	
	if ( self->GetRefCount () == 0 ) {
		delete ( self );
	}
	return 0;
}
//----------------------------------------------------------------//
int MOAILuaObject::_tostring ( lua_State* L ) {

	MOAILuaState state ( L );

	MOAILuaObject* data = ( MOAILuaObject* )state.GetPtrUserData ( 1 );
	if ( data ) {
		
		STLString str;
		
		lua_getfield ( state, 1, "getClassName" );
		if ( state.IsType ( -1, LUA_TFUNCTION )) {
		
			lua_pushvalue ( state, 1 );
			state.DebugCall ( 1, 1 );
			cc8* classname = state.GetValue < cc8* >( -1, "" );
			str.write ( "%p <%s>", data, classname );
			state.Push ( str );
			return 1;
		}
		
		str.write ( "%p <%s>", data, data->TypeName ());
		state.Push ( str );
		return 1;
	}
	return 0;
}
//----------------------------------------------------------------//
int MOAILuaObject::_getClassName ( lua_State* L ) {

	MOAILuaState state ( L );
	MOAILuaObject* object = ( MOAILuaObject* )state.GetPtrUserData ( 1 );

	if ( object ) {
		lua_pushstring ( L, object->TypeName ());
		return 1;
	}
	return 0;
}
//----------------------------------------------------------------//
int MOAILuaObject::_getClass ( lua_State* L ) {

	MOAILuaState state ( L );
	MOAILuaObject* object = ( MOAILuaObject* )state.GetPtrUserData ( 1 );

	if ( object ) {
		object->PushLuaClassTable ( state );
		return 1;
	}
	return 0;
}
//----------------------------------------------------------------//
int MOAILuaObject::_tostring ( lua_State* L ) {

	MOAILuaState state ( L );

	MOAILuaObject* data = ( MOAILuaObject* )state.GetPtrUserData ( 1 );
	if ( data ) {
	
		STLString str;
		str.write ( "0x%p <%s>", data, data->TypeName ()); // TODO: 64-bit
		state.Push ( str );
		return 1;
	}
	return 0;
}
//----------------------------------------------------------------//
int MOAILuaObject::_gc ( lua_State* L ) {

	MOAILuaState state ( L );
	
	MOAILuaObject* data = ( MOAILuaObject* )state.GetPtrUserData ( 1 );

	bool cleanup = ( data->GetRefCount () == 0 ); // ready to cleanup if no references

	// in any event, let's get rid of the userdata and lua refs we know about
	data->ClearLocal ( data->mContain );
	data->mUserdata.Clear ();
	data->mMemberTable.Clear ();
	
	// check to see if gc is being invoked during finalization
	if ( MOAILuaRuntime::IsValid ()) {
		MOAILuaRuntime::Get ().ClearObjectStackTrace ( data );
	}

	// delete if no references
	if ( cleanup ) {
		delete data;
	}
	return 0;
}
//----------------------------------------------------------------//
int MOAILuaObject::_index ( lua_State* L ) {

	MOAILuaState state ( L );
	MOAILuaObject* data = ( MOAILuaObject* )state.GetPtrUserData ( 1 );
	if ( data ) {
	
		//AJV for debugging
		//__android_log_print(ANDROID_LOG_INFO, "MoaiLog", "0x%p <%s>", data, data->TypeName ());
	}

	// push the instance table
	lua_getmetatable ( L, 1 );

	// push the member table
	lua_pushstring ( L, LUA_MEMBER_TABLE_NAME );
	lua_rawget ( L, -2 );
	
	// try to get the value
	lua_pushvalue ( L, 2 ); 
	lua_gettable ( L, -2 );
	
	// if nil...
	if ( lua_isnil ( L, -1 )) {
	
		// pop the nil and the member table
		lua_pop ( L, 2 );
		
		// get the instance table's metatable (the interface table)
		lua_getmetatable ( L, -1 );
		
		// and try to get the value from the interface table directly
		lua_pushvalue ( L, 2 );
		lua_rawget ( L, -2 );
	}
	return 1;
}
Beispiel #8
0
//----------------------------------------------------------------//
int MOAILuaClass::_extendSingleton ( lua_State* L ) {

	MOAILuaState state ( L );
	
	// upvalues:
	// 1: singleton userdata
	// 2: class table
	
	// set the userdata
	MOAILuaObject* luaData = ( MOAILuaObject* )state.GetPtrUserData ( lua_upvalueindex ( 1 ));
	state.PushPtrUserData ( luaData );
	
	// clone the class table
	state.CloneTable ( lua_upvalueindex ( 2 ));
	
	lua_pushvalue ( state, -1 );
	lua_setfield ( state, -2, "__index" );

	lua_pushvalue ( state, -1 );
	lua_setfield ( state, -2, "__newindex" );
	
	// add getClassName to class table
	lua_pushvalue ( L, 1 );
	lua_pushcclosure ( L, _getUpvalue, 1 );
	lua_setfield ( L, -2, "getClassName" );
	
	// copy the extended userdata
	lua_pushvalue ( L, -2 );
	
	// copy the extended table
	lua_pushvalue ( L, -2 );
	
	// push the 'extend' method with the singleton userdata and extended class table upvalues
	lua_pushcclosure ( L, _extendSingleton, 2 );
	
	// set the extended 'extend' method...
	lua_setfield ( L, -2, "extend" );

	// stack:
	// -1: extended class table
	// -2: extended userdata
	
	// call the extender
	if ( state.IsType ( 2, LUA_TFUNCTION )) {
		lua_pushvalue ( L, 2 );
		lua_pushvalue ( L, -2 );
		lua_pushvalue ( L, lua_upvalueindex ( 2 ));
		state.DebugCall ( 2, 0 );
	}
	
	// stack:
	// -1: extended class table
	// -2: extended userdata
	
	// set the table as a metatable on the userdata
	lua_setmetatable ( L, -2 );
	
	// and we're done
	cc8* classname = state.GetValue < cc8* >( 1, "" );
	lua_setglobal ( state, classname );
	return 0;
}
Beispiel #9
0
//----------------------------------------------------------------//
// This beast will walk through all tables and functions accessible in the
// current lua state and print a reference line for each one found to help
// track who is pointing to it.
void MOAILuaRuntime::FindAndPrintLuaRefs ( int idx, cc8* prefix, FILE *f, const LeakPtrList& objects ) {

	lua_State* L = this->mMainState;

	// Convert to absolute index
	if ( idx < 0 ) {
		idx = lua_gettop(L) + idx + 1;
	}
	
	// Check if the item at the top of the stack has been traversed yet.
	lua_pushvalue ( L, -1 );
	lua_gettable ( L, idx );
	if( lua_type ( L, -1 ) != LUA_TNIL ) {
		// It has, let's bail.
		lua_pop ( L, 1 ); // Clean our 'true'
		return;
	}
	lua_pop(L, 1); // Remove the nil
	
	int tt = lua_type ( L, -1 );
	if( tt == LUA_TTABLE ) {
//		printf("finding refs in: %s\n", prefix);
		// It hasn't been visited, so mark it in our traversal set
		lua_pushvalue ( L, -1 ); // Push table as key
		lua_pushboolean ( L, true );
		lua_settable ( L, idx );
		
		lua_pushnil ( L );  // first key
		while ( lua_next ( L, -2 ) != 0 ) {
			
			// use the 'key' (at index -2) and 'value' (at index -1)
			STLString key;
			
			if ( lua_type ( L, -2) == LUA_TSTRING ) {
				if ( MOAILuaRuntime::IsLuaIdentifier ( lua_tostring ( L, -2 ))) {
					key.write ( "%s.%s", prefix, lua_tostring ( L, -2 ));
				}
				else {
					// TODO: escape '\"'
					key.write ( "%s[\"%s\"]", prefix, lua_tostring ( L, -2 ));
				}
			}
			else {
				// stringify key
				lua_getglobal ( L, "tostring" );
				lua_pushvalue ( L, -3 );
				lua_call ( L, 1, 1 );
				
				key.write ( "%s[%s]", prefix, lua_tostring ( L, -1 ));
				// Pop stringified key
				lua_pop ( L, 1 );
			}
			
			this->FindAndPrintLuaRefs ( idx, key.c_str (), f, objects );

			// removes 'value'; keeps 'key' for next iteration
			lua_pop ( L, 1 );
		}
		
		// Check its metatable (if it has one)
		if ( lua_getmetatable ( L, -1 )) {
			STLString key;
			key.write ( "%s~mt", prefix );
			this->FindAndPrintLuaRefs ( idx, key.c_str(), f, objects );
			lua_pop ( L, 1 ); // Pop metatable
		}
	}
	else if ( tt == LUA_TFUNCTION ) {
//		printf("finding refs in: %s\n", prefix);
		// It hasn't been visited, so mark it in our tarversal set
		lua_pushvalue ( L, -1 ); // Push table as key
		lua_pushboolean ( L, true );
		lua_settable ( L, idx );
		
		const char *upname;
		for ( int i = 1; ( upname = lua_getupvalue ( L, -1, i )) != NULL; ++i ) {
			STLString key;
			key.write ( "%s(%s)", prefix, upname );
			this->FindAndPrintLuaRefs ( idx, key.c_str(), f, objects );
			// Pop the upvalue
			lua_pop ( L, 1 );
		}
	}
	else if ( tt == LUA_TUSERDATA ) {
		// It hasn't been visited, so mark it in our traversal set
		lua_pushvalue ( L, -1 ); // Push table as key
		lua_pushboolean ( L, true );
		lua_settable ( L, idx );

		MOAILuaState state ( L );
		void *ud = state.GetPtrUserData ( -1 );
		for ( LeakPtrList::const_iterator i = objects.begin (); i != objects.end (); ++i ) {
			if( *i == ud ) {
				fprintf ( f, "\tLua Ref: %s = %s <%p>\n", prefix, ( *i )->TypeName (), ud );
//				if ( strcmp((*i)->TypeName(), "MOAICoroutine") == 0 ) {
//					MOAICoroutine *t = (MOAICoroutine*)ud;
//				}
			}
		}
		
		// Check its metatable (if it has one)
		if ( lua_getmetatable ( L, -1 )) {
			STLString key;
			key.write ( "%s~mt", prefix );
			this->FindAndPrintLuaRefs ( idx, key.c_str (), f, objects );
			lua_pop ( L, 1 ); // Pop metatable
		}
	}
}