Linker vs Bindings and NewRefcount

Note: Missed last week MonoTouch 5.3 (alpha) release ? or my earlier posts on the linker vs Runtime.Arch and UI thread checks ? Read them first :)

MonoTouch 5.2 was the first stable release to support the --newrefcount option when --sgen (the new garbage collector) is enabled.

New UI in the latest (beta) of MonoDevelop

This new feature had a few impact on MonoTouch’s bindings. Here are examples from ATMHud‘s bindings, file AtmHud.g.cs, in the monotouch-bindings github repository. It’s a generated file so it’s not visible on github web site.

Listing 1

object __mt_HudView_var;
[CompilerGenerated]
public virtual AtmHudView HudView {
	[Export ("__view", ArgumentSemantic.Retain)]
	get {
		AtmHudView ret;
		ret = (AtmHudView) Runtime.GetNSObject (MonoTouch.ObjCRuntime.Messaging.IntPtr_objc_msgSend (this.Handle, sel__view));
		if (!IsNewRefcountEnabled ())
			__mt_HudView_var = ret;
		return ret;
	}
	[Export ("set__view:", ArgumentSemantic.Retain)]
	set {
		if (value == null)
			throw new ArgumentNullException ("value");
		MonoTouch.ObjCRuntime.Messaging.void_objc_msgSend_IntPtr (this.Handle, selSet__view_, value.Handle);
		if (!IsNewRefcountEnabled ())
			__mt_HudView_var = value;
	}
}

Listing 2

object __mt_WeakDelegate_var;
[CompilerGenerated]
public virtual NSObject WeakDelegate {
	[Export ("delegate")]
	get {
		NSObject ret;
		ret = (NSObject) Runtime.GetNSObject (MonoTouch.ObjCRuntime.Messaging.IntPtr_objc_msgSend (this.Handle, selDelegate));
		MarkDirty ();
		__mt_WeakDelegate_var = ret;
		return ret;
	}
	[Export ("setDelegate:")]
	set {
		MonoTouch.ObjCRuntime.Messaging.void_objc_msgSend_IntPtr (this.Handle, selSetDelegate_, value == null ? IntPtr.Zero : value.Handle);
		MarkDirty ();
		__mt_WeakDelegate_var = value;
	}
}

Listing 1 shows the use of IsNewRefcount method (line #8 and #17). It’s the most important since it show that when --newrefcount is enabled we can avoid using backing fields, like __mt_HudView_var (line #1), in several cases. That’s marvellous by itself but with MonoTouch 5.3+ it’s even better.

Why ? because that’s where the linker can shine (and why those changes are made at this stage). Not only it can rewrite the IL to remove the check !IsNewRefcountEnabled () but it can also eliminate the backing field itself, similar to a previous linker optimization (see listing 3). That means you can get types with smaller memory footprints, when using newrefcount (and the linker), since the (unneeded) backing fields won’t be present.

Listing 3: When --new-refcount is enabled

public virtual AtmHudView HudView {
	[Export ("__view", ArgumentSemantic.Retain)]
	get {
		AtmHudView ret;
		ret = (AtmHudView) Runtime.GetNSObject (MonoTouch.ObjCRuntime.Messaging.IntPtr_objc_msgSend (this.Handle, sel__view));
		return ret;
	}
	[Export ("set__view:", ArgumentSemantic.Retain)]
	set {
		if (value == null)
			throw new ArgumentNullException ("value");
		MonoTouch.ObjCRuntime.Messaging.void_objc_msgSend_IntPtr (this.Handle, selSet__view_, value.Handle);
	}
}

Listing 2 shows that a new call, to MakeDirty (line #8 and #15), was also added. However it is only required when the new refcounting is being used (note: the check resides inside the call, not the caller). So the linker can simply remove the call when the normal/default reference counting is used. In such cases the code will simply become:

Listing 4: when --new-refcount is NOT enabled

object __mt_WeakDelegate_var;
public virtual NSObject WeakDelegate {
	[Export ("delegate")]
	get {
		NSObject ret;
		ret = (NSObject) Runtime.GetNSObject (MonoTouch.ObjCRuntime.Messaging.IntPtr_objc_msgSend (this.Handle, selDelegate));
		__mt_WeakDelegate_var = ret;
		return ret;
	}
	[Export ("setDelegate:")]
	set {
		MonoTouch.ObjCRuntime.Messaging.void_objc_msgSend_IntPtr (this.Handle, selSetDelegate_, value == null ? IntPtr.Zero : value.Handle);
		__mt_WeakDelegate_var = value;
	}
}

Nothing dramatic ;-) but this allows, in most cases, the linker to eliminate the use of the new registered_toggleref field inside NSObject, which means every type inheriting from NSObject it will be 4 bytes smaller than before (when you don’t use newrefcount).

This concludes the descriptions of the new linker features for the first alpha release of MonoTouch 5.3. As always testing results and feedback are greatly appreciated.

About these ads

About spouliot

Xamarin Hacker, Mono Contributor, Open Source Enthusiast with strong interests in Code Analysis, Cryptography and Security. Presently working on MonoTouch, previous projects were Moonlight and libgdiplus and a lot of the cryptographic work done on Mono.
This entry was posted in monotouch, mono, xamarin, linker. Bookmark the permalink.

One Response to Linker vs Bindings and NewRefcount

  1. Pingback: Linker vs Bindings and IsDirectBinding | take a bit, get a byte

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s