Linker vs Bindings and Runtime.Arch

Have you ever looked at the code generated by btouch for MonoTouch bindings ? If so you have seen that we sometime need to know if we’re executing on a device or inside the simulator. The reason for this is that the ObjectiveC ABI for ARM and i386 differs and requires us to call different functions.

Here’s an example from CorePlot bindings, file CTPAxis.g.cs, in the monotouch-bindings github repository. It’s a generated file so it’s not visible on github web site.

	[Export ("viewPointForCoordinateDecimalNumber:")]
	public virtual System.Drawing.PointF ViewPointForCoordinateDecimalNumber (NSDecimal coordinateDecimalNumber)
	{
		System.Drawing.PointF ret;
		if (Runtime.Arch == Arch.DEVICE){
			coreplot.Messaging.PointF_objc_msgSend_stret_NSDecimal (out ret, this.Handle, selViewPointForCoordinateDecimalNumber, coordinateDecimalNumber);
		} else {
			ret = coreplot.Messaging.PointF_objc_msgSend_NSDecimal (this.Handle, selViewPointForCoordinateDecimalNumber, coordinateDecimalNumber);
		}
		return ret;
	}

Now since there is no JIT’ing possible when using MonoTouch (on devices) we know that we’ll never have the same binaries executing on both the devices and the simulator. So this (unknown at compile-time) condition will always be known (a constant at runtime) and can be eliminated.

One way to do so is to have the MonoTouch’s linker re-write the IL of the bindings code that contains this check and remove the branch that is not needed for the platform being targeted. Once re-written the code (de-compiled back to C# for readability) will look like this for devices:

	[Export ("viewPointForCoordinateDecimalNumber:")]
	public virtual System.Drawing.PointF ViewPointForCoordinateDecimalNumber (NSDecimal coordinateDecimalNumber)
	{
		System.Drawing.PointF ret;
		coreplot.Messaging.PointF_objc_msgSend_stret_NSDecimal (out ret, this.Handle, selViewPointForCoordinateDecimalNumber, coordinateDecimalNumber);
		return ret;
	}

or like this for the simulator (less common since the simulator is not, by default, using the linker):

	[Export ("viewPointForCoordinateDecimalNumber:")]
	public virtual System.Drawing.PointF ViewPointForCoordinateDecimalNumber (NSDecimal coordinateDecimalNumber)
	{
		System.Drawing.PointF ret;
		ret = coreplot.Messaging.PointF_objc_msgSend_NSDecimal (this.Handle, selViewPointForCoordinateDecimalNumber, coordinateDecimalNumber);
		return ret;
	}

Is that safe ? Yes. MonoTouch 5.3+ (hot alpha just available from our build bots) adds [CompilerGenerated] attributes in the bindings it produce and the linker will only re-write them if the attribute is present. Any manual bindings or user code won’t have the attribute and will be ignored. That also means that old bindings won’t be re-written unless they are regenerated with the newer btouch tool.

Could this optimization be done at AOT time ? Yes. Then why not ? A few reasons…

The most interesting one is that the linker is able to remove the extra, not required anymore, Messaging methods, e.g. PointF_objc_msgSend_NSDecimal when targeting devices. This results in smaller executable size – not a huge gain but an easy one.

There are also other reasons (i.e. more blog posts) to re-write the bindings IL, some of them not AOT optimization friendly as this one. The final cost (for all of them) is also very small (another blog post ?) and once you add one the others are even more cheap.

Advertisements

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 linker, mono, monotouch, xamarin. Bookmark the permalink.

4 Responses to Linker vs Bindings and Runtime.Arch

  1. Redth says:

    Good post… I usually find your posts a bit too technical for me to follow, but this one was written very well, and I very much enjoyed it… Looking forward to some more detail here in future posts! Thanks!

    • spouliot says:

      Thanks! I don’t write so fast (it’s easy to beat me to any news) nor so well and I hate duplication. All of this results in myself not blogging often and never about stuff that’s very common – but I’m glad whenever it proves useful to more than a few people 😉

  2. Pingback: Linker vs Bindings and NewRefcount | surprisingly unimpressed

  3. 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