Browse Source

Merged default into minor

--HG--
branch : minor
Alex Szpakowski 11 years ago
parent
commit
9b1f7d7a6e

+ 0 - 1
src/common/Variant.cpp

@@ -226,7 +226,6 @@ void Variant::toLua(lua_State *L)
 		{
 		{
 			const char *name = NULL;
 			const char *name = NULL;
 			love::types.find(udatatype, name);
 			love::types.find(udatatype, name);
-			((love::Object *) data.userdata)->retain();
 			luax_pushtype(L, name, flags, (love::Object *) data.userdata);
 			luax_pushtype(L, name, flags, (love::Object *) data.userdata);
 		}
 		}
 		else
 		else

+ 16 - 44
src/common/runtime.cpp

@@ -36,8 +36,7 @@
 namespace love
 namespace love
 {
 {
 
 
-static thread::Mutex *gcmutex = 0;
-void *_gcmutex = 0;
+static thread::Mutex *gcmutex = nullptr;
 
 
 /**
 /**
  * Called when an object is collected. The object is released
  * Called when an object is collected. The object is released
@@ -46,25 +45,15 @@ void *_gcmutex = 0;
 static int w__gc(lua_State *L)
 static int w__gc(lua_State *L)
 {
 {
 	if (!gcmutex)
 	if (!gcmutex)
-	{
 		gcmutex = thread::newMutex();
 		gcmutex = thread::newMutex();
-		_gcmutex = (void *) gcmutex;
-	}
 
 
-	Proxy *p = (Proxy *)lua_touserdata(L, 1);
-	Object *t = (Object *)p->data;
+	Proxy *p = (Proxy *) lua_touserdata(L, 1);
+	Object *object = (Object *) p->data;
 
 
 	thread::Lock lock(gcmutex);
 	thread::Lock lock(gcmutex);
 
 
-	int numretains = p->retains;
-	if (numretains >= 0)
-		numretains = std::min(numretains, t->getReferenceCount());
-
-	for (int i = numretains; i > 0; i--)
-		t->release();
+	object->release();
 
 
-	// Signal that this Proxy is dead.
-	p->retains = -1;
 	return 0;
 	return 0;
 }
 }
 
 
@@ -228,7 +217,6 @@ int luax_register_module(lua_State *L, const WrappedModule &m)
 	luax_insistregistry(L, REGISTRY_MODULES);
 	luax_insistregistry(L, REGISTRY_MODULES);
 
 
 	Proxy *p = (Proxy *)lua_newuserdata(L, sizeof(Proxy));
 	Proxy *p = (Proxy *)lua_newuserdata(L, sizeof(Proxy));
-	p->retains = 1;
 	p->data = m.module;
 	p->data = m.module;
 	p->flags = m.flags;
 	p->flags = m.flags;
 
 
@@ -394,20 +382,24 @@ int luax_register_searcher(lua_State *L, lua_CFunction f, int pos)
 	return 0;
 	return 0;
 }
 }
 
 
-void luax_rawnewtype(lua_State *L, const char *name, bits flags, love::Object *data, bool own)
+void luax_rawnewtype(lua_State *L, const char *name, bits flags, love::Object *object)
 {
 {
 	Proxy *u = (Proxy *)lua_newuserdata(L, sizeof(Proxy));
 	Proxy *u = (Proxy *)lua_newuserdata(L, sizeof(Proxy));
 
 
-	u->data = (void *) data;
+	object->retain();
+
+	u->data = (void *) object;
 	u->flags = flags;
 	u->flags = flags;
-	u->retains = own ? 1 : 0;
 
 
 	luaL_newmetatable(L, name);
 	luaL_newmetatable(L, name);
 	lua_setmetatable(L, -2);
 	lua_setmetatable(L, -2);
 }
 }
 
 
-void luax_pushtype(lua_State *L, const char *name, bits flags, love::Object *data, bool own)
+void luax_pushtype(lua_State *L, const char *name, bits flags, love::Object *object)
 {
 {
+	if (object == nullptr)
+		lua_pushnil(L);
+
 	// Fetch the registry table of instantiated types.
 	// Fetch the registry table of instantiated types.
 	luax_getregistry(L, REGISTRY_TYPES);
 	luax_getregistry(L, REGISTRY_TYPES);
 
 
@@ -415,11 +407,11 @@ void luax_pushtype(lua_State *L, const char *name, bits flags, love::Object *dat
 	if (!lua_istable(L, -1))
 	if (!lua_istable(L, -1))
 	{
 	{
 		lua_pop(L, 1);
 		lua_pop(L, 1);
-		return luax_rawnewtype(L, name, flags, data, own);
+		return luax_rawnewtype(L, name, flags, object);
 	}
 	}
 
 
 	// Get the value of lovetypes[data] on the stack.
 	// Get the value of lovetypes[data] on the stack.
-	lua_pushlightuserdata(L, (void *) data);
+	lua_pushlightuserdata(L, (void *) object);
 	lua_gettable(L, -2);
 	lua_gettable(L, -2);
 
 
 	// If the Proxy userdata isn't in the instantiated types table yet, add it.
 	// If the Proxy userdata isn't in the instantiated types table yet, add it.
@@ -427,38 +419,18 @@ void luax_pushtype(lua_State *L, const char *name, bits flags, love::Object *dat
 	{
 	{
 		lua_pop(L, 1);
 		lua_pop(L, 1);
 
 
-		luax_rawnewtype(L, name, flags, data, own);
+		luax_rawnewtype(L, name, flags, object);
 
 
-		lua_pushlightuserdata(L, (void *) data);
+		lua_pushlightuserdata(L, (void *) object);
 		lua_pushvalue(L, -2);
 		lua_pushvalue(L, -2);
 
 
 		// lovetypes[data] = Proxy.
 		// lovetypes[data] = Proxy.
 		lua_settable(L, -4);
 		lua_settable(L, -4);
-
-		// Remove the lovetypes table from the stack.
-		lua_remove(L, -2);
-
-		// The Proxy userdata remains at the top of the stack.
-		return;
 	}
 	}
 
 
 	// Remove the lovetypes table from the stack.
 	// Remove the lovetypes table from the stack.
 	lua_remove(L, -2);
 	lua_remove(L, -2);
 
 
-	// If the object should be released on GC and we already have a stored
-	// Proxy, we should tell the Proxy that the object was retained again.
-	if (own)
-	{
-		Proxy *p = (Proxy *) lua_touserdata(L, -1);
-
-		thread::EmptyLock lock;
-		if (gcmutex)
-			lock.setLock(gcmutex);
-
-		if (p->retains >= 0)
-			++(p->retains);
-	}
-
 	// Keep the Proxy userdata on the stack.
 	// Keep the Proxy userdata on the stack.
 }
 }
 
 

+ 10 - 13
src/common/runtime.h

@@ -43,9 +43,6 @@ namespace love
 class Module;
 class Module;
 class Reference;
 class Reference;
 
 
-// Exposed mutex of the GC
-extern void *_gcmutex;
-
 /**
 /**
  * Registries represent special tables which can be accessed with
  * Registries represent special tables which can be accessed with
  * luax_insistregistry and luax_getregistry.
  * luax_insistregistry and luax_getregistry.
@@ -70,9 +67,6 @@ struct Proxy
 
 
 	// The light userdata (pointer to the love::Object).
 	// The light userdata (pointer to the love::Object).
 	void *data;
 	void *data;
-
-	// The number of times release() should be called on GC.
-	int retains;
 };
 };
 
 
 /**
 /**
@@ -231,6 +225,9 @@ void luax_setfuncs(lua_State *L, const luaL_Reg *l);
 
 
 /**
 /**
  * Register a module in the love table. The love table will be created if it does not exist.
  * Register a module in the love table. The love table will be created if it does not exist.
+ * NOTE: The module-object is expected to have a +1 reference count before calling
+ * this function, as it doesn't retain the object itself but Lua will release it
+ * upon garbage collection.
  * @param L The Lua state.
  * @param L The Lua state.
  **/
  **/
 int luax_register_module(lua_State *L, const WrappedModule &m);
 int luax_register_module(lua_State *L, const WrappedModule &m);
@@ -271,27 +268,27 @@ int luax_register_searcher(lua_State *L, lua_CFunction f, int pos = -1);
 /**
 /**
  * Pushes a Lua representation of the given object onto the stack, creating and
  * Pushes a Lua representation of the given object onto the stack, creating and
  * storing the Lua representation in a weak table if it doesn't exist yet.
  * storing the Lua representation in a weak table if it doesn't exist yet.
+ * NOTE: The object will be retained by Lua and released upon garbage collection.
  * @param L The Lua state.
  * @param L The Lua state.
  * @param name The name of the type. This must match the name used with luax_register_type.
  * @param name The name of the type. This must match the name used with luax_register_type.
  * @param flags The type information of the object.
  * @param flags The type information of the object.
- * @param data The pointer to the actual object.
- * @param own Set this to true (default) if the object should be released upon garbage collection.
+ * @param object The pointer to the actual object.
  **/
  **/
-void luax_pushtype(lua_State *L, const char *name, bits flags, love::Object *data, bool own = true);
+void luax_pushtype(lua_State *L, const char *name, bits flags, love::Object *object);
 
 
 /**
 /**
  * Creates a new Lua representation of the given object *without* checking if it
  * Creates a new Lua representation of the given object *without* checking if it
  * exists yet, and *without* storing it in a weak table.
  * exists yet, and *without* storing it in a weak table.
  * This should only be used when performance is an extreme concern and the
  * This should only be used when performance is an extreme concern and the
  * object is not ever expected to be pushed to Lua again, as it prevents the
  * object is not ever expected to be pushed to Lua again, as it prevents the
- * Lua-side objects from working in all cases when used as keys in tables.
+ * Lua-side objects from working in some cases when used as keys in tables.
+ * NOTE: The object will be retained by Lua and released upon garbage collection.
  * @param L The Lua state.
  * @param L The Lua state.
  * @param name The name of the type. This must match the name used with luax_register_type.
  * @param name The name of the type. This must match the name used with luax_register_type.
  * @param flags The type information of the object.
  * @param flags The type information of the object.
- * @param data The pointer to the actual object.
- * @param own Set this to true (default) if the object should be released upon garbage collection.
+ * @param object The pointer to the actual object.
  **/
  **/
-void luax_rawnewtype(lua_State *L, const char *name, bits flags, love::Object *data, bool own = true);
+void luax_rawnewtype(lua_State *L, const char *name, bits flags, love::Object *object);
 
 
 /**
 /**
  * Checks whether the value at idx is a certain type.
  * Checks whether the value at idx is a certain type.

+ 11 - 2
src/modules/audio/wrap_Audio.cpp

@@ -63,6 +63,7 @@ int w_newSource(lua_State *L)
 	if (t)
 	if (t)
 	{
 	{
 		luax_pushtype(L, "Source", AUDIO_SOURCE_T, t);
 		luax_pushtype(L, "Source", AUDIO_SOURCE_T, t);
+		t->release();
 		return 1;
 		return 1;
 	}
 	}
 	else
 	else
@@ -224,7 +225,10 @@ int w_getRecordedData(lua_State *L)
 	if (!sd)
 	if (!sd)
 		lua_pushnil(L);
 		lua_pushnil(L);
 	else
 	else
+	{
 		luax_pushtype(L, "SoundData", SOUND_SOUND_DATA_T, sd);
 		luax_pushtype(L, "SoundData", SOUND_SOUND_DATA_T, sd);
+		sd->release();
+	}
 	return 1;
 	return 1;
 }
 }
 
 
@@ -233,8 +237,13 @@ int w_stopRecording(lua_State *L)
 	if (luax_optboolean(L, 1, true))
 	if (luax_optboolean(L, 1, true))
 	{
 	{
 		love::sound::SoundData *sd = instance()->stopRecording(true);
 		love::sound::SoundData *sd = instance()->stopRecording(true);
-		if (!sd) lua_pushnil(L);
-		else luax_pushtype(L, "SoundData", SOUND_SOUND_DATA_T, sd);
+		if (!sd)
+			lua_pushnil(L);
+		else
+		{
+			luax_pushtype(L, "SoundData", SOUND_SOUND_DATA_T, sd);
+			sd->release();
+		}
 		return 1;
 		return 1;
 	}
 	}
 	instance()->stopRecording(false);
 	instance()->stopRecording(false);

+ 1 - 0
src/modules/audio/wrap_Source.cpp

@@ -38,6 +38,7 @@ int w_Source_clone(lua_State *L)
 	Source *clone = nullptr;
 	Source *clone = nullptr;
 	luax_catchexcept(L, [&](){ clone = t->clone(); });
 	luax_catchexcept(L, [&](){ clone = t->clone(); });
 	luax_pushtype(L, "Source", AUDIO_SOURCE_T, clone);
 	luax_pushtype(L, "Source", AUDIO_SOURCE_T, clone);
+	clone->release();
 	return 1;
 	return 1;
 }
 }
 
 

+ 8 - 1
src/modules/filesystem/wrap_Filesystem.cpp

@@ -145,6 +145,7 @@ int w_newFile(lua_State *L)
 	}
 	}
 
 
 	luax_pushtype(L, "File", FILESYSTEM_FILE_T, t);
 	luax_pushtype(L, "File", FILESYSTEM_FILE_T, t);
+	t->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -210,6 +211,7 @@ int w_newFileData(lua_State *L)
 				return luax_ioError(L, "%s", e.what());
 				return luax_ioError(L, "%s", e.what());
 			}
 			}
 			luax_pushtype(L, "FileData", FILESYSTEM_FILE_DATA_T, data);
 			luax_pushtype(L, "FileData", FILESYSTEM_FILE_DATA_T, data);
+			data->release();
 			return 1;
 			return 1;
 		}
 		}
 		else
 		else
@@ -241,6 +243,7 @@ int w_newFileData(lua_State *L)
 	}
 	}
 
 
 	luax_pushtype(L, "FileData", FILESYSTEM_FILE_DATA_T, t);
 	luax_pushtype(L, "FileData", FILESYSTEM_FILE_DATA_T, t);
+	t->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -396,9 +399,13 @@ int w_lines(lua_State *L)
 		luax_catchexcept(L, [&](){ success = file->open(File::READ); });
 		luax_catchexcept(L, [&](){ success = file->open(File::READ); });
 
 
 		if (!success)
 		if (!success)
+		{
+			file->release();
 			return luaL_error(L, "Could not open file.");
 			return luaL_error(L, "Could not open file.");
-		
+		}
+
 		luax_pushtype(L, "File", FILESYSTEM_FILE_T, file);
 		luax_pushtype(L, "File", FILESYSTEM_FILE_T, file);
+		file->release();
 	}
 	}
 	else
 	else
 		return luaL_argerror(L, 1, "expected filename.");
 		return luaL_argerror(L, 1, "expected filename.");

+ 4 - 0
src/modules/font/freetype/wrap_Font.cpp

@@ -58,8 +58,11 @@ int w_newRasterizer(lua_State *L)
 			[&]() { d->release(); }
 			[&]() { d->release(); }
 		);
 		);
 	}
 	}
+	else
+		return luaL_argerror(L, 1, "expected ImageData, filename, or FileData");
 
 
 	luax_pushtype(L, "Rasterizer", FONT_RASTERIZER_T, t);
 	luax_pushtype(L, "Rasterizer", FONT_RASTERIZER_T, t);
+	t->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -81,6 +84,7 @@ int w_newGlyphData(lua_State *L)
 	}
 	}
 
 
 	luax_pushtype(L, "GlyphData", FONT_GLYPH_DATA_T, t);
 	luax_pushtype(L, "GlyphData", FONT_GLYPH_DATA_T, t);
+	t->release();
 	return 1;
 	return 1;
 }
 }
 
 

+ 1 - 0
src/modules/font/wrap_Rasterizer.cpp

@@ -87,6 +87,7 @@ int w_Rasterizer_getGlyphData(lua_State *L)
 	});
 	});
 
 
 	luax_pushtype(L, "GlyphData", FONT_GLYPH_DATA_T, g);
 	luax_pushtype(L, "GlyphData", FONT_GLYPH_DATA_T, g);
+	g->release();
 	return 1;
 	return 1;
 }
 }
 
 

+ 2 - 2
src/modules/graphics/opengl/Graphics.cpp

@@ -167,7 +167,7 @@ void Graphics::setViewportSize(int width, int height)
 
 
 	// We want to affect the main screen, not any Canvas that's currently active
 	// We want to affect the main screen, not any Canvas that's currently active
 	// (not that any *should* be active when this is called.)
 	// (not that any *should* be active when this is called.)
-	std::vector<Canvas *> canvases = getCanvas();
+	std::vector<Object::StrongRef<Canvas>> canvases = states.back().canvases;
 	setCanvas();
 	setCanvas();
 
 
 	// Set the viewport to top-left corner.
 	// Set the viewport to top-left corner.
@@ -1061,7 +1061,7 @@ love::image::ImageData *Graphics::newScreenshot(love::image::Image *image, bool
 {
 {
 	// Temporarily unbind the currently active canvas (glReadPixels reads the
 	// Temporarily unbind the currently active canvas (glReadPixels reads the
 	// active framebuffer, not the main one.)
 	// active framebuffer, not the main one.)
-	std::vector<Canvas *> canvases = getCanvas();
+	std::vector<Object::StrongRef<Canvas>> canvases = states.back().canvases;
 	setCanvas();
 	setCanvas();
 
 
 	int w = getWidth();
 	int w = getWidth();

+ 1 - 0
src/modules/graphics/opengl/wrap_Canvas.cpp

@@ -68,6 +68,7 @@ int w_Canvas_getImageData(lua_State *L)
 	love::image::Image *image = luax_getmodule<love::image::Image>(L, "image", MODULE_IMAGE_T);
 	love::image::Image *image = luax_getmodule<love::image::Image>(L, "image", MODULE_IMAGE_T);
 	love::image::ImageData *img = canvas->getImageData(image);
 	love::image::ImageData *img = canvas->getImageData(image);
 	luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, img);
 	luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, img);
+	img->release();
 	return 1;
 	return 1;
 }
 }
 
 

+ 17 - 14
src/modules/graphics/opengl/wrap_Graphics.cpp

@@ -225,6 +225,7 @@ int w_newImage(lua_State *L)
 
 
 	// Push the type.
 	// Push the type.
 	luax_pushtype(L, "Image", GRAPHICS_IMAGE_T, image);
 	luax_pushtype(L, "Image", GRAPHICS_IMAGE_T, image);
+	image->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -241,6 +242,7 @@ int w_newQuad(lua_State *L)
 
 
 	Quad *quad = instance()->newQuad(v, sw, sh);
 	Quad *quad = instance()->newQuad(v, sw, sh);
 	luax_pushtype(L, "Quad", GRAPHICS_QUAD_T, quad);
 	luax_pushtype(L, "Quad", GRAPHICS_QUAD_T, quad);
+	quad->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -265,6 +267,7 @@ int w_newFont(lua_State *L)
 
 
 	// Push the type.
 	// Push the type.
 	luax_pushtype(L, "Font", GRAPHICS_FONT_T, font);
 	luax_pushtype(L, "Font", GRAPHICS_FONT_T, font);
+	font->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -282,8 +285,8 @@ int w_newImageFont(lua_State *L)
 		filter = i->getFilter();
 		filter = i->getFilter();
 		love::image::ImageData *id = i->getImageData();
 		love::image::ImageData *id = i->getImageData();
 		if (!id)
 		if (!id)
-			return luaL_argerror(L, 1, "Image cannot be compressed.");
-		luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, id, false);
+			return luaL_argerror(L, 1, "Image must not be compressed.");
+		luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, id);
 		lua_replace(L, 1);
 		lua_replace(L, 1);
 	}
 	}
 
 
@@ -305,6 +308,7 @@ int w_newImageFont(lua_State *L)
 
 
 	// Push the type.
 	// Push the type.
 	luax_pushtype(L, "Font", GRAPHICS_FONT_T, font);
 	luax_pushtype(L, "Font", GRAPHICS_FONT_T, font);
+	font->release();
 
 
 	return 1;
 	return 1;
 }
 }
@@ -327,6 +331,7 @@ int w_newSpriteBatch(lua_State *L)
 	);
 	);
 
 
 	luax_pushtype(L, "SpriteBatch", GRAPHICS_SPRITE_BATCH_T, t);
 	luax_pushtype(L, "SpriteBatch", GRAPHICS_SPRITE_BATCH_T, t);
+	t->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -343,6 +348,7 @@ int w_newParticleSystem(lua_State *L)
 	);
 	);
 
 
 	luax_pushtype(L, "ParticleSystem", GRAPHICS_PARTICLE_SYSTEM_T, t);
 	luax_pushtype(L, "ParticleSystem", GRAPHICS_PARTICLE_SYSTEM_T, t);
+	t->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -367,6 +373,7 @@ int w_newCanvas(lua_State *L)
 		return luaL_error(L, "Canvas not created, but no error thrown. I don't even...");
 		return luaL_error(L, "Canvas not created, but no error thrown. I don't even...");
 
 
 	luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, canvas);
 	luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, canvas);
+	canvas->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -450,6 +457,7 @@ int w_newShader(lua_State *L)
 	{
 	{
 		Shader *shader = instance()->newShader(sources);
 		Shader *shader = instance()->newShader(sources);
 		luax_pushtype(L, "Shader", GRAPHICS_SHADER_T, shader);
 		luax_pushtype(L, "Shader", GRAPHICS_SHADER_T, shader);
+		shader->release();
 	}
 	}
 	catch (love::Exception &e)
 	catch (love::Exception &e)
 	{
 	{
@@ -542,6 +550,7 @@ int w_newMesh(lua_State *L)
 		t->setTexture(tex);
 		t->setTexture(tex);
 
 
 	luax_pushtype(L, "Mesh", GRAPHICS_MESH_T, t);
 	luax_pushtype(L, "Mesh", GRAPHICS_MESH_T, t);
+	t->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -631,7 +640,6 @@ int w_getFont(lua_State *L)
 	if (f == 0)
 	if (f == 0)
 		return 0;
 		return 0;
 
 
-	f->retain();
 	luax_pushtype(L, "Font", GRAPHICS_FONT_T, f);
 	luax_pushtype(L, "Font", GRAPHICS_FONT_T, f);
 	return 1;
 	return 1;
 }
 }
@@ -855,6 +863,7 @@ int w_newScreenshot(lua_State *L)
 	luax_catchexcept(L, [&](){ i = instance()->newScreenshot(image, copyAlpha); });
 	luax_catchexcept(L, [&](){ i = instance()->newScreenshot(image, copyAlpha); });
 
 
 	luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, i);
 	luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, i);
+	i->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -903,16 +912,13 @@ int w_getCanvas(lua_State *L)
 	const std::vector<Canvas *> canvases = instance()->getCanvas();
 	const std::vector<Canvas *> canvases = instance()->getCanvas();
 	int n = 0;
 	int n = 0;
 
 
-	if (!canvases.empty())
+	for (Canvas *c : canvases)
 	{
 	{
-		for (Canvas *c : canvases)
-		{
-			c->retain();
-			luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, c);
-			n++;
-		}
+		luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, c);
+		n++;
 	}
 	}
-	else
+
+	if (n == 0)
 	{
 	{
 		lua_pushnil(L);
 		lua_pushnil(L);
 		n = 1;
 		n = 1;
@@ -938,10 +944,7 @@ int w_getShader(lua_State *L)
 {
 {
 	Shader *shader = instance()->getShader();
 	Shader *shader = instance()->getShader();
 	if (shader)
 	if (shader)
-	{
-		shader->retain();
 		luax_pushtype(L, "Shader", GRAPHICS_SHADER_T, shader);
 		luax_pushtype(L, "Shader", GRAPHICS_SHADER_T, shader);
-	}
 	else
 	else
 		lua_pushnil(L);
 		lua_pushnil(L);
 
 

+ 0 - 6
src/modules/graphics/opengl/wrap_Image.cpp

@@ -91,10 +91,7 @@ int w_Image_getData(lua_State *L)
 	{
 	{
 		love::image::CompressedData *t = i->getCompressedData();
 		love::image::CompressedData *t = i->getCompressedData();
 		if (t)
 		if (t)
-		{
-			t->retain();
 			luax_pushtype(L, "CompressedData", IMAGE_COMPRESSED_DATA_T, t);
 			luax_pushtype(L, "CompressedData", IMAGE_COMPRESSED_DATA_T, t);
-		}
 		else
 		else
 			lua_pushnil(L);
 			lua_pushnil(L);
 	}
 	}
@@ -102,10 +99,7 @@ int w_Image_getData(lua_State *L)
 	{
 	{
 		love::image::ImageData *t = i->getImageData();
 		love::image::ImageData *t = i->getImageData();
 		if (t)
 		if (t)
-		{
-			t->retain();
 			luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, t);
 			luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, t);
-		}
 		else
 		else
 			lua_pushnil(L);
 			lua_pushnil(L);
 	}
 	}

+ 0 - 5
src/modules/graphics/opengl/wrap_Mesh.cpp

@@ -263,18 +263,13 @@ int w_Mesh_getTexture(lua_State *L)
 	if (tex == nullptr)
 	if (tex == nullptr)
 		return 0;
 		return 0;
 
 
-	tex->retain();
-
 	// FIXME: big hack right here.
 	// FIXME: big hack right here.
 	if (typeid(*tex) == typeid(Image))
 	if (typeid(*tex) == typeid(Image))
 		luax_pushtype(L, "Image", GRAPHICS_IMAGE_T, tex);
 		luax_pushtype(L, "Image", GRAPHICS_IMAGE_T, tex);
 	else if (typeid(*tex) == typeid(Canvas))
 	else if (typeid(*tex) == typeid(Canvas))
 		luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, tex);
 		luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, tex);
 	else
 	else
-	{
-		tex->release();
 		return luaL_error(L, "Unable to determine texture type.");
 		return luaL_error(L, "Unable to determine texture type.");
-	}
 
 
 	return 1;
 	return 1;
 }
 }

+ 1 - 5
src/modules/graphics/opengl/wrap_ParticleSystem.cpp

@@ -52,6 +52,7 @@ int w_ParticleSystem_clone(lua_State *L)
 	luax_catchexcept(L, [&](){ clone = t->clone(); });
 	luax_catchexcept(L, [&](){ clone = t->clone(); });
 
 
 	luax_pushtype(L, "ParticleSystem", GRAPHICS_PARTICLE_SYSTEM_T, clone);
 	luax_pushtype(L, "ParticleSystem", GRAPHICS_PARTICLE_SYSTEM_T, clone);
+	clone->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -67,7 +68,6 @@ int w_ParticleSystem_getTexture(lua_State *L)
 {
 {
 	ParticleSystem *t = luax_checkparticlesystem(L, 1);
 	ParticleSystem *t = luax_checkparticlesystem(L, 1);
 	Texture *tex = t->getTexture();
 	Texture *tex = t->getTexture();
-	tex->retain();
 
 
 	// FIXME: big hack right here.
 	// FIXME: big hack right here.
 	if (typeid(*tex) == typeid(Image))
 	if (typeid(*tex) == typeid(Image))
@@ -75,10 +75,7 @@ int w_ParticleSystem_getTexture(lua_State *L)
 	else if (typeid(*tex) == typeid(Canvas))
 	else if (typeid(*tex) == typeid(Canvas))
 		luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, tex);
 		luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, tex);
 	else
 	else
-	{
-		tex->release();
 		return luaL_error(L, "Unable to determine texture type.");
 		return luaL_error(L, "Unable to determine texture type.");
-	}
 
 
 	return 1;
 	return 1;
 }
 }
@@ -608,7 +605,6 @@ int w_ParticleSystem_getQuads(lua_State *L)
 
 
 	for (size_t i = 0; i < quads.size(); i++)
 	for (size_t i = 0; i < quads.size(); i++)
 	{
 	{
-		quads[i]->retain();
 		luax_pushtype(L, "Quad", GRAPHICS_QUAD_T, quads[i]);
 		luax_pushtype(L, "Quad", GRAPHICS_QUAD_T, quads[i]);
 		lua_rawseti(L, -2, i + 1);
 		lua_rawseti(L, -2, i + 1);
 	}
 	}

+ 0 - 4
src/modules/graphics/opengl/wrap_SpriteBatch.cpp

@@ -137,7 +137,6 @@ int w_SpriteBatch_getTexture(lua_State *L)
 {
 {
 	SpriteBatch *t = luax_checkspritebatch(L, 1);
 	SpriteBatch *t = luax_checkspritebatch(L, 1);
 	Texture *tex = t->getTexture();
 	Texture *tex = t->getTexture();
-	tex->retain();
 
 
 	// FIXME: big hack right here.
 	// FIXME: big hack right here.
 	if (typeid(*tex) == typeid(Image))
 	if (typeid(*tex) == typeid(Image))
@@ -145,10 +144,7 @@ int w_SpriteBatch_getTexture(lua_State *L)
 	else if (typeid(*tex) == typeid(Canvas))
 	else if (typeid(*tex) == typeid(Canvas))
 		luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, tex);
 		luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, tex);
 	else
 	else
-	{
-		tex->release();
 		return luaL_error(L, "Unable to determine texture type.");
 		return luaL_error(L, "Unable to determine texture type.");
-	}
 
 
 	return 1;
 	return 1;
 }
 }

+ 3 - 0
src/modules/image/wrap_Image.cpp

@@ -48,6 +48,7 @@ int w_newImageData(lua_State *L)
 		luax_catchexcept(L, [&](){ t = instance()->newImageData(w, h); });
 		luax_catchexcept(L, [&](){ t = instance()->newImageData(w, h); });
 
 
 		luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, t);
 		luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, t);
+		t->release();
 		return 1;
 		return 1;
 	}
 	}
 
 
@@ -61,6 +62,7 @@ int w_newImageData(lua_State *L)
 	);
 	);
 
 
 	luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, t);
 	luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, t);
+	t->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -75,6 +77,7 @@ int w_newCompressedData(lua_State *L)
 	);
 	);
 
 
 	luax_pushtype(L, "CompressedData", IMAGE_COMPRESSED_DATA_T, t);
 	luax_pushtype(L, "CompressedData", IMAGE_COMPRESSED_DATA_T, t);
+	t->release();
 	return 1;
 	return 1;
 }
 }
 
 

+ 0 - 1
src/modules/joystick/wrap_JoystickModule.cpp

@@ -40,7 +40,6 @@ int w_getJoysticks(lua_State *L)
 	for (int i = 0; i < stickcount; i++)
 	for (int i = 0; i < stickcount; i++)
 	{
 	{
 		Joystick *stick = instance()->getJoystick(i);
 		Joystick *stick = instance()->getJoystick(i);
-		stick->retain();
 		luax_pushtype(L, "Joystick", JOYSTICK_JOYSTICK_T, stick);
 		luax_pushtype(L, "Joystick", JOYSTICK_JOYSTICK_T, stick);
 		lua_rawseti(L, -2, i + 1);
 		lua_rawseti(L, -2, i + 1);
 	}
 	}

+ 1 - 0
src/modules/math/wrap_BezierCurve.cpp

@@ -45,6 +45,7 @@ int w_BezierCurve_getDerivative(lua_State *L)
 	BezierCurve *curve = luax_checkbeziercurve(L, 1);
 	BezierCurve *curve = luax_checkbeziercurve(L, 1);
 	BezierCurve *deriv = new BezierCurve(curve->getDerivative());
 	BezierCurve *deriv = new BezierCurve(curve->getDerivative());
 	luax_pushtype(L, "BezierCurve", MATH_BEZIER_CURVE_T, deriv);
 	luax_pushtype(L, "BezierCurve", MATH_BEZIER_CURVE_T, deriv);
+	deriv->release();
 	return 1;
 	return 1;
 }
 }
 
 

+ 2 - 0
src/modules/math/wrap_Math.cpp

@@ -101,6 +101,7 @@ int w_newRandomGenerator(lua_State *L)
 	}
 	}
 
 
 	luax_pushtype(L, "RandomGenerator", MATH_RANDOM_GENERATOR_T, t);
 	luax_pushtype(L, "RandomGenerator", MATH_RANDOM_GENERATOR_T, t);
+	t->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -139,6 +140,7 @@ int w_newBezierCurve(lua_State *L)
 
 
 	BezierCurve *curve = Math::instance.newBezierCurve(points);
 	BezierCurve *curve = Math::instance.newBezierCurve(points);
 	luax_pushtype(L, "BezierCurve", MATH_BEZIER_CURVE_T, curve);
 	luax_pushtype(L, "BezierCurve", MATH_BEZIER_CURVE_T, curve);
+	curve->release();
 	return 1;
 	return 1;
 }
 }
 
 

+ 1 - 4
src/modules/mouse/wrap_Mouse.cpp

@@ -46,6 +46,7 @@ int w_newCursor(lua_State *L)
 	luax_catchexcept(L, [&](){ cursor = instance()->newCursor(data, hotx, hoty); });
 	luax_catchexcept(L, [&](){ cursor = instance()->newCursor(data, hotx, hoty); });
 
 
 	luax_pushtype(L, "Cursor", MOUSE_CURSOR_T, cursor);
 	luax_pushtype(L, "Cursor", MOUSE_CURSOR_T, cursor);
+	cursor->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -60,7 +61,6 @@ int w_getSystemCursor(lua_State *L)
 	Cursor *cursor = 0;
 	Cursor *cursor = 0;
 	luax_catchexcept(L, [&](){ cursor = instance()->getSystemCursor(systemCursor); });
 	luax_catchexcept(L, [&](){ cursor = instance()->getSystemCursor(systemCursor); });
 
 
-	cursor->retain();
 	luax_pushtype(L, "Cursor", MOUSE_CURSOR_T, cursor);
 	luax_pushtype(L, "Cursor", MOUSE_CURSOR_T, cursor);
 	return 1;
 	return 1;
 }
 }
@@ -84,10 +84,7 @@ int w_getCursor(lua_State *L)
 	Cursor *cursor = instance()->getCursor();
 	Cursor *cursor = instance()->getCursor();
 
 
 	if (cursor)
 	if (cursor)
-	{
-		cursor->retain();
 		luax_pushtype(L, "Cursor", MOUSE_CURSOR_T, cursor);
 		luax_pushtype(L, "Cursor", MOUSE_CURSOR_T, cursor);
-	}
 	else
 	else
 		lua_pushnil(L);
 		lua_pushnil(L);
 
 

+ 1 - 1
src/modules/physics/box2d/Body.cpp

@@ -432,7 +432,6 @@ int Body::getFixtureList(lua_State *L) const
 		Fixture *fixture = (Fixture *)Memoizer::find(f);
 		Fixture *fixture = (Fixture *)Memoizer::find(f);
 		if (!fixture)
 		if (!fixture)
 			throw love::Exception("A fixture has escaped Memoizer!");
 			throw love::Exception("A fixture has escaped Memoizer!");
-		fixture->retain();
 		luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, fixture);
 		luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, fixture);
 		lua_rawseti(L, -2, i);
 		lua_rawseti(L, -2, i);
 		i++;
 		i++;
@@ -458,6 +457,7 @@ int Body::getContactList(lua_State *L) const
 			contact->retain();
 			contact->retain();
 		
 		
 		luax_pushtype(L, "Contact", PHYSICS_CONTACT_T, contact);
 		luax_pushtype(L, "Contact", PHYSICS_CONTACT_T, contact);
+		contact->release();
 		lua_rawseti(L, -2, i);
 		lua_rawseti(L, -2, i);
 		i++;
 		i++;
 	}
 	}

+ 2 - 1
src/modules/physics/box2d/Physics.cpp

@@ -125,8 +125,8 @@ int Physics::newPolygonShape(lua_State *L)
 	}
 	}
 
 
 	PolygonShape *p = new PolygonShape(s);
 	PolygonShape *p = new PolygonShape(s);
-
 	luax_pushtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, p);
 	luax_pushtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, p);
+	p->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -167,6 +167,7 @@ int Physics::newChainShape(lua_State *L)
 
 
 	ChainShape *c = new ChainShape(s);
 	ChainShape *c = new ChainShape(s);
 	luax_pushtype(L, "ChainShape", PHYSICS_CHAIN_SHAPE_T, c);
 	luax_pushtype(L, "ChainShape", PHYSICS_CHAIN_SHAPE_T, c);
+	c->release();
 	return 1;
 	return 1;
 }
 }
 
 

+ 2 - 12
src/modules/physics/box2d/World.cpp

@@ -57,10 +57,7 @@ void World::ContactCallback::process(b2Contact *contact, const b2ContactImpulse
 		{
 		{
 			Fixture *a = (Fixture *)Memoizer::find(contact->GetFixtureA());
 			Fixture *a = (Fixture *)Memoizer::find(contact->GetFixtureA());
 			if (a != 0)
 			if (a != 0)
-			{
-				a->retain();
 				luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, a);
 				luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, a);
-			}
 			else
 			else
 				throw love::Exception("A fixture has escaped Memoizer!");
 				throw love::Exception("A fixture has escaped Memoizer!");
 		}
 		}
@@ -69,10 +66,7 @@ void World::ContactCallback::process(b2Contact *contact, const b2ContactImpulse
 		{
 		{
 			Fixture *b = (Fixture *)Memoizer::find(contact->GetFixtureB());
 			Fixture *b = (Fixture *)Memoizer::find(contact->GetFixtureB());
 			if (b != 0)
 			if (b != 0)
-			{
-				b->retain();
 				luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, b);
 				luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, b);
-			}
 			else
 			else
 				throw love::Exception("A fixture has escaped Memoizer!");
 				throw love::Exception("A fixture has escaped Memoizer!");
 		}
 		}
@@ -84,6 +78,7 @@ void World::ContactCallback::process(b2Contact *contact, const b2ContactImpulse
 			cobj->retain();
 			cobj->retain();
 
 
 		luax_pushtype(L, "Contact", (PHYSICS_CONTACT_T), cobj);
 		luax_pushtype(L, "Contact", (PHYSICS_CONTACT_T), cobj);
+		cobj->release();
 
 
 		int args = 3;
 		int args = 3;
 		if (impulse)
 		if (impulse)
@@ -131,8 +126,6 @@ bool World::ContactFilter::process(Fixture *a, Fixture *b)
 
 
 	if (ref != 0)
 	if (ref != 0)
 	{
 	{
-		a->retain();
-		b->retain();
 		lua_State *L = ref->getL();
 		lua_State *L = ref->getL();
 		ref->push();
 		ref->push();
 		luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, a);
 		luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, a);
@@ -163,7 +156,6 @@ bool World::QueryCallback::ReportFixture(b2Fixture *fixture)
 		Fixture *f = (Fixture *)Memoizer::find(fixture);
 		Fixture *f = (Fixture *)Memoizer::find(fixture);
 		if (!f)
 		if (!f)
 			throw love::Exception("A fixture has escaped Memoizer!");
 			throw love::Exception("A fixture has escaped Memoizer!");
-		f->retain();
 		luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, f);
 		luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, f);
 		lua_call(L, 1, 1);
 		lua_call(L, 1, 1);
 		return luax_toboolean(L, -1);
 		return luax_toboolean(L, -1);
@@ -191,7 +183,6 @@ float32 World::RayCastCallback::ReportFixture(b2Fixture *fixture, const b2Vec2 &
 		Fixture *f = (Fixture *)Memoizer::find(fixture);
 		Fixture *f = (Fixture *)Memoizer::find(fixture);
 		if (!f)
 		if (!f)
 			throw love::Exception("A fixture has escaped Memoizer!");
 			throw love::Exception("A fixture has escaped Memoizer!");
-		f->retain();
 		luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, f);
 		luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, f);
 		b2Vec2 scaledPoint = Physics::scaleUp(point);
 		b2Vec2 scaledPoint = Physics::scaleUp(point);
 		lua_pushnumber(L, scaledPoint.x);
 		lua_pushnumber(L, scaledPoint.x);
@@ -440,7 +431,6 @@ int World::getBodyList(lua_State *L) const
 		Body *body = (Body *)Memoizer::find(b);
 		Body *body = (Body *)Memoizer::find(b);
 		if (!body)
 		if (!body)
 			throw love::Exception("A body has escaped Memoizer!");
 			throw love::Exception("A body has escaped Memoizer!");
-		body->retain();
 		luax_pushtype(L, "Body", PHYSICS_BODY_T, body);
 		luax_pushtype(L, "Body", PHYSICS_BODY_T, body);
 		lua_rawseti(L, -2, i);
 		lua_rawseti(L, -2, i);
 		i++;
 		i++;
@@ -459,7 +449,6 @@ int World::getJointList(lua_State *L) const
 		if (!j) break;
 		if (!j) break;
 		Joint *joint = (Joint *)Memoizer::find(j);
 		Joint *joint = (Joint *)Memoizer::find(j);
 		if (!joint) throw love::Exception("A joint has escaped Memoizer!");
 		if (!joint) throw love::Exception("A joint has escaped Memoizer!");
-		joint->retain();
 		luax_pushtype(L, "Joint", PHYSICS_JOINT_T, joint);
 		luax_pushtype(L, "Joint", PHYSICS_JOINT_T, joint);
 		lua_rawseti(L, -2, i);
 		lua_rawseti(L, -2, i);
 		i++;
 		i++;
@@ -482,6 +471,7 @@ int World::getContactList(lua_State *L) const
 		else
 		else
 			contact->retain();
 			contact->retain();
 		luax_pushtype(L, "Contact", PHYSICS_CONTACT_T, contact);
 		luax_pushtype(L, "Contact", PHYSICS_CONTACT_T, contact);
+		contact->release();
 		lua_rawseti(L, -2, i);
 		lua_rawseti(L, -2, i);
 		i++;
 		i++;
 	}
 	}

+ 0 - 1
src/modules/physics/box2d/wrap_Body.cpp

@@ -526,7 +526,6 @@ int w_Body_getWorld(lua_State *L)
 {
 {
 	Body *t = luax_checkbody(L, 1);
 	Body *t = luax_checkbody(L, 1);
 	World *world = t->getWorld();
 	World *world = t->getWorld();
-	world->retain();
 	luax_pushtype(L, "World", PHYSICS_WORLD_T, world);
 	luax_pushtype(L, "World", PHYSICS_WORLD_T, world);
 	return 1;
 	return 1;
 }
 }

+ 1 - 0
src/modules/physics/box2d/wrap_ChainShape.cpp

@@ -66,6 +66,7 @@ int w_ChainShape_getChildEdge(lua_State *L)
 	EdgeShape *e = 0;
 	EdgeShape *e = 0;
 	luax_catchexcept(L, [&](){ e = c->getChildEdge(index); });
 	luax_catchexcept(L, [&](){ e = c->getChildEdge(index); });
 	luax_pushtype(L, "EdgeShape", PHYSICS_EDGE_SHAPE_T, e);
 	luax_pushtype(L, "EdgeShape", PHYSICS_EDGE_SHAPE_T, e);
+	e->release();
 	return 1;
 	return 1;
 }
 }
 
 

+ 0 - 2
src/modules/physics/box2d/wrap_Contact.cpp

@@ -146,9 +146,7 @@ int w_Contact_getFixtures(lua_State *L)
 	Fixture *b = nullptr;
 	Fixture *b = nullptr;
 	luax_catchexcept(L, [&](){ t->getFixtures(a, b); });
 	luax_catchexcept(L, [&](){ t->getFixtures(a, b); });
 
 
-	a->retain();
 	luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, a);
 	luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, a);
-	b->retain();
 	luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, b);
 	luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, b);
 	return 2;
 	return 2;
 }
 }

+ 1 - 1
src/modules/physics/box2d/wrap_Fixture.cpp

@@ -111,7 +111,6 @@ int w_Fixture_getBody(lua_State *L)
 	Body *body = t->getBody();
 	Body *body = t->getBody();
 	if (body == 0)
 	if (body == 0)
 		return 0;
 		return 0;
-	body->retain();
 	luax_pushtype(L, "Body", PHYSICS_BODY_T, body);
 	luax_pushtype(L, "Body", PHYSICS_BODY_T, body);
 	return 1;
 	return 1;
 }
 }
@@ -140,6 +139,7 @@ int w_Fixture_getShape(lua_State *L)
 		luax_pushtype(L, "Shape", PHYSICS_SHAPE_T, shape);
 		luax_pushtype(L, "Shape", PHYSICS_SHAPE_T, shape);
 		break;
 		break;
 	}
 	}
+	shape->release();
 	return 1;
 	return 1;
 }
 }
 
 

+ 19 - 0
src/modules/physics/box2d/wrap_Physics.cpp

@@ -60,6 +60,7 @@ int w_newWorld(lua_State *L)
 	World *w;
 	World *w;
 	luax_catchexcept(L, [&](){ w = instance()->newWorld(gx, gy, sleep); });
 	luax_catchexcept(L, [&](){ w = instance()->newWorld(gx, gy, sleep); });
 	luax_pushtype(L, "World", PHYSICS_WORLD_T, w);
 	luax_pushtype(L, "World", PHYSICS_WORLD_T, w);
+	w->release();
 
 
 	return 1;
 	return 1;
 }
 }
@@ -78,6 +79,7 @@ int w_newBody(lua_State *L)
 	Body *body;
 	Body *body;
 	luax_catchexcept(L, [&](){ body = instance()->newBody(world, x, y, btype); });
 	luax_catchexcept(L, [&](){ body = instance()->newBody(world, x, y, btype); });
 	luax_pushtype(L, "Body", PHYSICS_BODY_T, body);
 	luax_pushtype(L, "Body", PHYSICS_BODY_T, body);
+	body->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -89,6 +91,7 @@ int w_newFixture(lua_State *L)
 	Fixture *fixture;
 	Fixture *fixture;
 	luax_catchexcept(L, [&](){ fixture = instance()->newFixture(body, shape, density); });
 	luax_catchexcept(L, [&](){ fixture = instance()->newFixture(body, shape, density); });
 	luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, fixture);
 	luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, fixture);
+	fixture->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -102,6 +105,7 @@ int w_newCircleShape(lua_State *L)
 		CircleShape *shape;
 		CircleShape *shape;
 		luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(radius); });
 		luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(radius); });
 		luax_pushtype(L, "CircleShape", PHYSICS_CIRCLE_SHAPE_T, shape);
 		luax_pushtype(L, "CircleShape", PHYSICS_CIRCLE_SHAPE_T, shape);
+		shape->release();
 		return 1;
 		return 1;
 	}
 	}
 	else if (top == 3)
 	else if (top == 3)
@@ -112,6 +116,7 @@ int w_newCircleShape(lua_State *L)
 		CircleShape *shape;
 		CircleShape *shape;
 		luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(x, y, radius); });
 		luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(x, y, radius); });
 		luax_pushtype(L, "CircleShape", PHYSICS_CIRCLE_SHAPE_T, shape);
 		luax_pushtype(L, "CircleShape", PHYSICS_CIRCLE_SHAPE_T, shape);
+		shape->release();
 		return 1;
 		return 1;
 	}
 	}
 	else
 	else
@@ -129,6 +134,7 @@ int w_newRectangleShape(lua_State *L)
 		PolygonShape *shape;
 		PolygonShape *shape;
 		luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(w, h); });
 		luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(w, h); });
 		luax_pushtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, shape);
 		luax_pushtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, shape);
+		shape->release();
 		return 1;
 		return 1;
 	}
 	}
 	else if (top == 4 || top == 5)
 	else if (top == 4 || top == 5)
@@ -141,6 +147,7 @@ int w_newRectangleShape(lua_State *L)
 		PolygonShape *shape;
 		PolygonShape *shape;
 		luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(x, y, w, h, angle); });
 		luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(x, y, w, h, angle); });
 		luax_pushtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, shape);
 		luax_pushtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, shape);
+		shape->release();
 		return 1;
 		return 1;
 	}
 	}
 	else
 	else
@@ -156,6 +163,7 @@ int w_newEdgeShape(lua_State *L)
 	EdgeShape *shape;
 	EdgeShape *shape;
 	luax_catchexcept(L, [&](){ shape = instance()->newEdgeShape(x1, y1, x2, y2); });
 	luax_catchexcept(L, [&](){ shape = instance()->newEdgeShape(x1, y1, x2, y2); });
 	luax_pushtype(L, "EdgeShape", PHYSICS_EDGE_SHAPE_T, shape);
 	luax_pushtype(L, "EdgeShape", PHYSICS_EDGE_SHAPE_T, shape);
+	shape->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -187,6 +195,7 @@ int w_newDistanceJoint(lua_State *L)
 		j = instance()->newDistanceJoint(body1, body2, x1, y1, x2, y2, collideConnected);
 		j = instance()->newDistanceJoint(body1, body2, x1, y1, x2, y2, collideConnected);
 	});
 	});
 	luax_pushtype(L, "DistanceJoint", PHYSICS_DISTANCE_JOINT_T, j);
 	luax_pushtype(L, "DistanceJoint", PHYSICS_DISTANCE_JOINT_T, j);
+	j->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -198,6 +207,7 @@ int w_newMouseJoint(lua_State *L)
 	MouseJoint *j;
 	MouseJoint *j;
 	luax_catchexcept(L, [&](){ j = instance()->newMouseJoint(body, x, y); });
 	luax_catchexcept(L, [&](){ j = instance()->newMouseJoint(body, x, y); });
 	luax_pushtype(L, "MouseJoint", PHYSICS_MOUSE_JOINT_T, j);
 	luax_pushtype(L, "MouseJoint", PHYSICS_MOUSE_JOINT_T, j);
+	j->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -213,6 +223,7 @@ int w_newRevoluteJoint(lua_State *L)
 		j = instance()->newRevoluteJoint(body1, body2, x, y, collideConnected);
 		j = instance()->newRevoluteJoint(body1, body2, x, y, collideConnected);
 	});
 	});
 	luax_pushtype(L, "RevoluteJoint", PHYSICS_REVOLUTE_JOINT_T, j);
 	luax_pushtype(L, "RevoluteJoint", PHYSICS_REVOLUTE_JOINT_T, j);
+	j->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -245,6 +256,7 @@ int w_newPrismaticJoint(lua_State *L)
 		j = instance()->newPrismaticJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);
 		j = instance()->newPrismaticJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);
 	});
 	});
 	luax_pushtype(L, "PrismaticJoint", PHYSICS_PRISMATIC_JOINT_T, j);
 	luax_pushtype(L, "PrismaticJoint", PHYSICS_PRISMATIC_JOINT_T, j);
+	j->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -268,6 +280,7 @@ int w_newPulleyJoint(lua_State *L)
 		j = instance()->newPulleyJoint(body1, body2, b2Vec2(gx1,gy1), b2Vec2(gx2,gy2), b2Vec2(x1,y1), b2Vec2(x2,y2), ratio, collideConnected);
 		j = instance()->newPulleyJoint(body1, body2, b2Vec2(gx1,gy1), b2Vec2(gx2,gy2), b2Vec2(x1,y1), b2Vec2(x2,y2), ratio, collideConnected);
 	});
 	});
 	luax_pushtype(L, "PulleyJoint", PHYSICS_PULLEY_JOINT_T, j);
 	luax_pushtype(L, "PulleyJoint", PHYSICS_PULLEY_JOINT_T, j);
+	j->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -283,6 +296,7 @@ int w_newGearJoint(lua_State *L)
 		j = instance()->newGearJoint(joint1, joint2, ratio, collideConnected);
 		j = instance()->newGearJoint(joint1, joint2, ratio, collideConnected);
 	});
 	});
 	luax_pushtype(L, "GearJoint", PHYSICS_GEAR_JOINT_T, j);
 	luax_pushtype(L, "GearJoint", PHYSICS_GEAR_JOINT_T, j);
+	j->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -311,6 +325,7 @@ int w_newFrictionJoint(lua_State *L)
 		j = instance()->newFrictionJoint(body1, body2, xA, yA, xB, yB, collideConnected);
 		j = instance()->newFrictionJoint(body1, body2, xA, yA, xB, yB, collideConnected);
 	});
 	});
 	luax_pushtype(L, "FrictionJoint", PHYSICS_FRICTION_JOINT_T, j);
 	luax_pushtype(L, "FrictionJoint", PHYSICS_FRICTION_JOINT_T, j);
+	j->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -339,6 +354,7 @@ int w_newWeldJoint(lua_State *L)
 		j = instance()->newWeldJoint(body1, body2, xA, yA, xB, yB, collideConnected);
 		j = instance()->newWeldJoint(body1, body2, xA, yA, xB, yB, collideConnected);
 	});
 	});
 	luax_pushtype(L, "WeldJoint", PHYSICS_WELD_JOINT_T, j);
 	luax_pushtype(L, "WeldJoint", PHYSICS_WELD_JOINT_T, j);
+	j->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -372,6 +388,7 @@ int w_newWheelJoint(lua_State *L)
 		j = instance()->newWheelJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);
 		j = instance()->newWheelJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);
 	});
 	});
 	luax_pushtype(L, "WheelJoint", PHYSICS_WHEEL_JOINT_T, j);
 	luax_pushtype(L, "WheelJoint", PHYSICS_WHEEL_JOINT_T, j);
+	j->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -390,6 +407,7 @@ int w_newRopeJoint(lua_State *L)
 		j = instance()->newRopeJoint(body1, body2, x1, y1, x2, y2, maxLength, collideConnected);
 		j = instance()->newRopeJoint(body1, body2, x1, y1, x2, y2, maxLength, collideConnected);
 	});
 	});
 	luax_pushtype(L, "RopeJoint", PHYSICS_ROPE_JOINT_T, j);
 	luax_pushtype(L, "RopeJoint", PHYSICS_ROPE_JOINT_T, j);
+	j->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -410,6 +428,7 @@ int w_newMotorJoint(lua_State *L)
 		luax_catchexcept(L, [&](){ j = instance()->newMotorJoint(body1, body2); });
 		luax_catchexcept(L, [&](){ j = instance()->newMotorJoint(body1, body2); });
 	}
 	}
 	luax_pushtype(L, "MotorJoint", PHYSICS_MOTOR_JOINT_T, j);
 	luax_pushtype(L, "MotorJoint", PHYSICS_MOTOR_JOINT_T, j);
+	j->release();
 	return 1;
 	return 1;
 }
 }
 
 

+ 2 - 0
src/modules/sound/wrap_Sound.cpp

@@ -59,6 +59,7 @@ int w_newSoundData(lua_State *L)
 	}
 	}
 
 
 	luax_pushtype(L, "SoundData", SOUND_SOUND_DATA_T, t);
 	luax_pushtype(L, "SoundData", SOUND_SOUND_DATA_T, t);
+	t->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -77,6 +78,7 @@ int w_newDecoder(lua_State *L)
 		return luaL_error(L, "Extension \"%s\" not supported.", data->getExtension().c_str());
 		return luaL_error(L, "Extension \"%s\" not supported.", data->getExtension().c_str());
 
 
 	luax_pushtype(L, "Decoder", SOUND_DECODER_T, t);
 	luax_pushtype(L, "Decoder", SOUND_DECODER_T, t);
+	t->release();
 	return 1;
 	return 1;
 }
 }
 
 

+ 3 - 0
src/modules/thread/wrap_ThreadModule.cpp

@@ -55,6 +55,7 @@ int w_newThread(lua_State *L)
 
 
 	LuaThread *t = instance()->newThread(name, data);
 	LuaThread *t = instance()->newThread(name, data);
 	luax_pushtype(L, "Thread", THREAD_THREAD_T, t);
 	luax_pushtype(L, "Thread", THREAD_THREAD_T, t);
+	t->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -62,6 +63,7 @@ int w_newChannel(lua_State *L)
 {
 {
 	Channel *c = instance()->newChannel();
 	Channel *c = instance()->newChannel();
 	luax_pushtype(L, "Channel", THREAD_CHANNEL_T, c);
 	luax_pushtype(L, "Channel", THREAD_CHANNEL_T, c);
+	c->release();
 	return 1;
 	return 1;
 }
 }
 
 
@@ -70,6 +72,7 @@ int w_getChannel(lua_State *L)
 	std::string name = luax_checkstring(L, 1);
 	std::string name = luax_checkstring(L, 1);
 	Channel *c = instance()->getChannel(name);
 	Channel *c = instance()->getChannel(name);
 	luax_pushtype(L, "Channel", THREAD_CHANNEL_T, c);
 	luax_pushtype(L, "Channel", THREAD_CHANNEL_T, c);
+	c->release();
 	return 1;
 	return 1;
 }
 }
 
 

+ 0 - 3
src/modules/window/wrap_Window.cpp

@@ -262,10 +262,7 @@ int w_getIcon(lua_State *L)
 {
 {
 	image::ImageData *i = instance()->getIcon();
 	image::ImageData *i = instance()->getIcon();
 	if (i)
 	if (i)
-	{
-		i->retain();
 		luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, i);
 		luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, i);
-	}
 	else
 	else
 		lua_pushnil(L);
 		lua_pushnil(L);
 	return 1;
 	return 1;