Why is InvokeBinder.ReturnType hardcoded to typeof( object )?

Jan 16, 2010 at 6:07 PM

Inside my InvokeBinder implementation, I want to examine metadata and conditionally return an ET that either does "real work" or is a simple no-op (Expression.Empty()). In the no-op scenario, I prefer not to return Expression.Default( typeof( object ) ), because I assume the CLR JIT won't necessarily optimize that away like I assume it would with an Expression.Empty().

Since InvokeBinder.ReturnType is hardcoded to return typeof(object), I can't return Expression.Empty() from my InvokeBinder... the call site is always expecting an expression of type object.

So...

1) Why must InvokeBinder always return an ET of type object? I suppose it would make the DLR plumbing a bit cleaner, but it seems arbitrary, from the outside looking in.

2) Are my assumptions correct w.r.t. the CLR JIT behavior?

2) Is there some other way to achieve what I'm describing? Maybe use another binder base type?

 

Thanks...

Josh

 

Coordinator
Jan 16, 2010 at 7:11 PM

1) We locked down the return types for a couple of reasons.  The first is so that the DLR does not need to apply any policy to conversions returned from the standard binders.  In this case that policy would just need to be boxing and defining how typeof(void) gets boxed (presumably to null).  But even though it’s simple there’s still policy there and it might not always be right – for example Python wants to always box bool values into one of two known boxed values so there’s only one True/False instance.  For other binders, like the conversion binder where the return type is not object, this policy would need to get more complicated.  This also simplifies interop because you are always getting a known type back – so for example you can have a dynamic object fallback and it’s very simple to compose the results without needing to check for or inject extra conversions.

2) CLR JIT doesn’t actually need to optimize anything here, the DLR emits ldnull for Default(typeof(object)) so it’s already optimal before it gets to the JIT.

3) You can certainly inherit directly from DynamicMetaObjectBinder and return whatever type you want.  IronPython and IronRuby both have a number of custom binders and we also have standard binders which those custom binders will fallback to for interop.  The only limitation there is that your return type needs to match up with the return type of the call site.

From: jplane [mailto:notifications@codeplex.com]
Sent: Saturday, January 16, 2010 11:08 AM
To: Dino Viehland
Subject: Why is InvokeBinder.ReturnType hardcoded to typeof( object )? [dlr:81041]

From: jplane

Inside my InvokeBinder implementation, I want to examine metadata and conditionally return an ET that either does "real work" or is a simple no-op (Expression.Empty()). In the no-op scenario, I prefer not to return Expression.Default( typeof( object ) ), because I assume the CLR JIT won't necessarily optimize that away like I assume it would with an Expression.Empty().

Since InvokeBinder.ReturnType is hardcoded to return typeof(object), I can't return Expression.Empty() from my InvokeBinder... the call site is always expecting an expression of type object.

So...

1) Why must InvokeBinder always return an ET of type object? I suppose it would make the DLR plumbing a bit cleaner, but it seems arbitrary, from the outside looking in.

2) Are my assumptions correct w.r.t. the CLR JIT behavior?

2) Is there some other way to achieve what I'm describing? Maybe use another binder base type?

Thanks...

Josh

Read the full discussion online.

To add a post to this discussion, reply to this email (dlr@discussions.codeplex.com)

To start a new discussion for this project, email dlr@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com

Jan 16, 2010 at 9:29 PM
Edited Jan 17, 2010 at 1:38 PM

Okay, thanks Dino... I see now where DLR's returning ldnull in both cases... just didn't trace it through far enough.

That works for me... thanks for the help, and for the info on why the standard binders work the way they do.

 

EDIT-- Oops, looks like I was too quick on the draw... LambdaCompiler.EmitDefaultExpression() emits nothing if node.Type is void... so looks like I'll have to go the custom binder implementation after all.

 

Josh