digitalmars.D - Custom calling conventions
- Manu (38/38) Feb 21 2012 So I was thinking about this extern(language) thing, the obvious ones ar...
- Daniel Murphy (5/5) Feb 21 2012 Why can't you do that with existing language features?
- Manu (18/24) Feb 21 2012 You could, but that's really ugly. I did make the point in my OP that it
- Paulo Pinto (15/40) Feb 21 2012 I think this fails in the same trap as extern "language" in C++.
- Manu (21/32) Feb 21 2012 Well since the languages I'm using as examples are VM based, the
- Michel Fortin (26/63) Feb 21 2012 In all currently existing cases, extern(Lang) offers not only a way to
- Manu (40/102) Feb 21 2012 Interesting point.
- =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= (5/114) Feb 21 2012 Sure it could. Why wouldn't it be able to? This is how extern +
- Manu (5/18) Feb 21 2012 But that only works because C# has DLL support, which knows about the C
- =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= (5/24) Feb 21 2012 Surely Java 'native' methods require the native functions to conform to
- Jacob Carlborg (9/20) Feb 21 2012 Template bloat. Every call bridging D/Objective-C is made throw a series...
- Manu (6/28) Feb 21 2012 Why aren't the templates inline themselves? Although if the templates do...
- Michel Fortin (7/29) Feb 21 2012 I answered in my other post. In short: virtual functions you can
- Jacob Carlborg (23/55) Feb 21 2012 Michel Fortin explained this better in two of his answers. You can also
- Manu (5/75) Feb 21 2012 But they should all be inlined, and the symbol table should be stripped,
- Jacob Carlborg (4/85) Feb 21 2012 Well, that's not what happen with templates.
- Manu (5/123) Feb 21 2012 ... really? why?
- Michel Fortin (24/64) Feb 21 2012 I'm not sure what Jacob is referring to.
- Jacob Carlborg (34/77) Feb 21 2012 I referring to that every instantiation of a template function is put in...
- Michel Fortin (13/27) Feb 22 2012 That's expected indeed.
- Jacob Carlborg (16/39) Feb 22 2012 1. The example is correct, you can call a method without parentheses
- H. S. Teoh (9/10) Feb 22 2012 [...]
- Jacob Carlborg (5/12) Feb 22 2012 As I understand it, that will most likely be where we're going. But
- Michel Fortin (21/66) Feb 22 2012 I'm still on v2.055. And I can confirm -L-dead_strip worked for me, but
- Jacob Carlborg (4/66) Feb 22 2012 Yes, exactly.
- Jacob Carlborg (4/10) Feb 21 2012 --
- Michel Fortin (56/76) Feb 21 2012 I had one D class for every corresponding Objective-C class, each
So I was thinking about this extern(language) thing, the obvious ones are supported, but it would be really nice to be able to implement custom conventions for other languages/scripting languages. For instance, I'm thinking about Android, I have JNI binding code everywhere, it's really ugly. I'd love to be able to declare: extern(Java) int someJavaFunc(int x, float y) And then use my function like any regular function, with the 'extern(Java)' bit handling the JNI business behind the scenes. all be implemented the same way. I'm imaging some mechanism to declare a calling convention (which would be resolved within the extern(...) statement), and define it with a template, something like: callconv Java { R call(T...) { // process tuple of args, make the call, return something? } R thisCall(Class, T...) { // also need a way to implementing methods... this might be enough. } } Some fancy code in there could conceivably call into any foreign language, and this would be great! Now when I: import java.jni; I have the jni interface, but I also have access to extern(Java), and that's awesome! :) The main benefit over using a template, for instance: jniCall!"functionName"(args...), would be the function name is not a string, or require custom code construct (facilitating later re-factoring or delegation to script without changing masses of existing code, something I have done often), and if it was seen by the language as a regular function call, you can mark it with all the usual stuff, const/pure/etc, and apply the expected set of optimisations to the call. I'm sure this has been discussed before... so go on, tear it apart :)
Feb 21 2012
Why can't you do that with existing language features? alias JniExternFunc!(void function(int)) someJNIFuncYouWantToCallFromD; mixin JniExportFunc!(&dFuncYouWantToCallUsingJNI); Where the templates generate the wrapper code/calling convention arg shuffle for each function.
Feb 21 2012
On 21 February 2012 14:13, Daniel Murphy <yebblies nospamgmail.com> wrote:Why can't you do that with existing language features? alias JniExternFunc!(void function(int)) someJNIFuncYouWantToCallFromD; mixin JniExportFunc!(&dFuncYouWantToCallUsingJNI); Where the templates generate the wrapper code/calling convention arg shuffle for each function.You could, but that's really ugly. I did make the point in my OP that it can be hacked right now, but I also listed the benefits of making it a proper feature: 1. It would be very neat and tidy. Clarity and readability is important for code longevity. 2. Ease of refactoring/delegation to scripts without refactoring all the calling code throughout your app (this is real, I have done this on many occasions) 3. Declaring functions in the regular way, and annotating them with various properties (const/pure/etc) allows all the usual type safety and optimisation potentials available to the language. As far as the compiler is concerned, it is a real and normal function call. All surrounding code gen/optimisations are still applicable, the language will simply substitute the marshalling function at the final step of the call. 4-ish. It actually seems relatively simple to implement... and it's not a breaking change. I can't really see any down sides.
Feb 21 2012
I think this fails in the same trap as extern "language" in C++. Besides C and C++, I think the only variation I saw so far for the language part has been fortran, and cannot recall anylonger in what compiler it was. In C++'s case, since it is implementation defined, most compiler vendors did not bother to support more than what the standard specifies (C and C++). In you proposal, how to keep the feature portable across D implementations? If you make it part of D language specification, which languages would be the chosen ones to be made available in any D compiler? How to garantee correct interoperability (ABI) with other languages? After deciding the set of chosen languages, which compilers/runtimes would be the lucky ones? -- Paulo Am 21.02.2012 13:29, schrieb Manu:On 21 February 2012 14:13, Daniel Murphy <yebblies nospamgmail.com <mailto:yebblies nospamgmail.com>> wrote: Why can't you do that with existing language features? alias JniExternFunc!(void function(int)) someJNIFuncYouWantToCallFromD; mixin JniExportFunc!(&dFuncYouWantToCallUsingJNI); Where the templates generate the wrapper code/calling convention arg shuffle for each function. You could, but that's really ugly. I did make the point in my OP that it can be hacked right now, but I also listed the benefits of making it a proper feature: 1. It would be very neat and tidy. Clarity and readability is important for code longevity. 2. Ease of refactoring/delegation to scripts without refactoring all the calling code throughout your app (this is real, I have done this on many occasions) 3. Declaring functions in the regular way, and annotating them with various properties (const/pure/etc) allows all the usual type safety and optimisation potentials available to the language. As far as the compiler is concerned, it is a real and normal function call. All surrounding code gen/optimisations are still applicable, the language will simply substitute the marshalling function at the final step of the call. 4-ish. It actually seems relatively simple to implement... and it's not a breaking change. I can't really see any down sides.
Feb 21 2012
On 21 February 2012 21:03, Paulo Pinto <pjmlp progtools.org> wrote:I think this fails in the same trap as extern "language" in C++. Besides C and C++, I think the only variation I saw so far for the language part has been fortran, and cannot recall anylonger in what compiler it was. In C++'s case, since it is implementation defined, most compiler vendors did not bother to support more than what the standard specifies (C and C++). In you proposal, how to keep the feature portable across D implementations?Well since the languages I'm using as examples are VM based, the interaction is through a standardised API, which is most likely part of the same module that defines the custom extern type, both would be presented in the same package. If you make it part of D language specification, which languages would bethe chosen ones to be made available in any D compiler?I'm not making any language part of the D specification, I'm suggesting a system to integrate custom calling code, which can be introduced in libraries. No intrinsic support in D for any particular language. How to garantee correct interoperability (ABI) with other languages? Afterdeciding the set of chosen languages, which compilers/runtimes would be the lucky ones?VM based languages have a strictly defined API, this is guaranteed, no problem. Extern to hard-linking languages requires the extra bits I detailed in a prior post (name mangler, call receiver), and probably some version() mess to support different compilers just like C/C++ does all over the place. Many C compilers can't link against each others binaries, but with a mature lib, you'd be able to support the calling convention of popular compilers for your language of interest I would think. t's probably quite do-able, but I'm not proposing to take the system that far initially. Custom calling conventions to integrate with VM's seems more useful, and much simpler to start with.
Feb 21 2012
On 2012-02-21 11:03:09 +0000, Manu <turkeyman gmail.com> said:So I was thinking about this extern(language) thing, the obvious ones are supported, but it would be really nice to be able to implement custom conventions for other languages/scripting languages. For instance, I'm thinking about Android, I have JNI binding code everywhere, it's really ugly. I'd love to be able to declare: extern(Java) int someJavaFunc(int x, float y) And then use my function like any regular function, with the 'extern(Java)' bit handling the JNI business behind the scenes. all be implemented the same way. I'm imaging some mechanism to declare a calling convention (which would be resolved within the extern(...) statement), and define it with a template, something like: callconv Java { R call(T...) { // process tuple of args, make the call, return something? } R thisCall(Class, T...) { // also need a way to implementing methods... this might be enough. } } Some fancy code in there could conceivably call into any foreign language, and this would be great! Now when I: import java.jni; I have the jni interface, but I also have access to extern(Java), and that's awesome! :)In all currently existing cases, extern(Lang) offers not only a way to declare and call foreign-language functions, but also a way to define functions to be called from the foreign language. Basically, you have two-way compatibility. How would that work with Java? - - - Also, I see you're thinking about methods, which means you're thinking about declaring Java classes. How is that supposed to work exactly? I have some experience bridging Objective-C and D. I once built a complete wrapper system for Objective-C objects, each object was wrapped by a D one. It worked very well, but it generated so much bloat that it became unusable as soon as I started defining enough classes for it to be useful. See the D/Objective-C bridge: <http://michelf.com/projects/d-objc-bridge/>. Maybe you'll have more luck, but for me wrappers just couldn't work. So I decided making the compiler understand the Objective-C runtime and object model was a much better solution. It was fun to do and wasn't that hard actually. Here's the result: <http://michelf.com/projects/d-objc/>. Unfortunately I don't have much time to work on it anymore. More background: <http://michelf.com/weblog/2010/dobjc-dead-end-start-anew/> -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 21 2012
On 21 February 2012 16:59, Michel Fortin <michel.fortin michelf.com> wrote:On 2012-02-21 11:03:09 +0000, Manu <turkeyman gmail.com> said:Interesting point. Java (or any VM based language) can't hard link to the binary, so it never could try and call back in through an extern-ed function directly, it must be explicitly supplied the pointer in the first place. In that case, the API that supplies the callback to Java can produce the appropriate incoming call wrapper. I can imagine a way to doing a hard-extern under my proposal if you were hard linking against an unsupported language language... you might need to provide a name mangler in the definition block I describe to match the foreign language, and an incoming call template would also need to be defined as a naked function with the responsibility of managing the args/stack appropriately, and calling the externed function as a regular D-call (this would probably only be some light register/stack management, I don't think it would bloat a lot). This would allow D code to also call the externed function, since the physical definition is still a D-call, you just call it directly internally. Anyway, while I can imagine a solution, I don't think it would be needed immediately. It'll just open a further can of worms like foreign language struct layout as people try to use it in complex scenarios ;) I don't think this reduces the usefulness of my proposal at all though, ie. being able to apply it to outgoing calls for any foreign language. - - -So I was thinking about this extern(language) thing, the obvious ones are supported, but it would be really nice to be able to implement custom conventions for other languages/scripting languages. For instance, I'm thinking about Android, I have JNI binding code everywhere, it's really ugly. I'd love to be able to declare: extern(Java) int someJavaFunc(int x, float y) And then use my function like any regular function, with the 'extern(Java)' bit handling the JNI business behind the scenes. all be implemented the same way. I'm imaging some mechanism to declare a calling convention (which would be resolved within the extern(...) statement), and define it with a template, something like: callconv Java { R call(T...) { // process tuple of args, make the call, return something? } R thisCall(Class, T...) { // also need a way to implementing methods... this might be enough. } } Some fancy code in there could conceivably call into any foreign language, and this would be great! Now when I: import java.jni; I have the jni interface, but I also have access to extern(Java), and that's awesome! :)In all currently existing cases, extern(Lang) offers not only a way to declare and call foreign-language functions, but also a way to define functions to be called from the foreign language. Basically, you have two-way compatibility. How would that work with Java?Also, I see you're thinking about methods, which means you're thinking about declaring Java classes. How is that supposed to work exactly?Well I was thinking about that with respect to calling functions on classes that I have imported from a foreign language, not declared locally for export to a foreign language. I clearly didn't think that through though, I'll try and clarify my thoughts to that end... I get the feeling that idea was a dead-end though.I have some experience bridging Objective-C and D. I once built a complete wrapper system for Objective-C objects, each object was wrapped by a D one. It worked very well, but it generated so much bloat that it became unusable as soon as I started defining enough classes for it to be useful. See the D/Objective-C bridge: <http://michelf.com/projects/**d-objc-bridge/<http://michelf.com/projects/d-objc-bridge/>What was the primary cause of the bloat? I can't imagine my proposal causing any more bloat than the explicit jni call (or equivalent) woudl have otherwise..Maybe you'll have more luck, but for me wrappers just couldn't work. So I decided making the compiler understand the Objective-C runtime and object model was a much better solution. It was fun to do and wasn't that hard actually. Here's the result: <http://michelf.com/projects/**d-objc/<http://michelf.com/projects/d-objc/>>. Unfortunately I don't have much time to work on it anymore.That sounds appropriate for Obj-C, but I don't think it applies to VM based languages however you slice it, since there's not actually a direct binary linkage. There's no way to know about the Java/.NET/Lua/etc object model internally, the VM owns that entirely, so you're forced to marshal through API's. That's okay though, you have to do it anyway. I'm proposing a way to unify the concept of calling functions without obscuring the actual call with junk, and still allowing the D language to annotate and optimise to its fullest extent. More background:<http://michelf.com/weblog/**2010/dobjc-dead-end-start-**anew/<http://michelf.com/weblog/2010/dobjc-dead-end-start-anew/>-- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 21 2012
On 21-02-2012 18:03, Manu wrote:On 21 February 2012 16:59, Michel Fortin <michel.fortin michelf.com <mailto:michel.fortin michelf.com>> wrote: On 2012-02-21 11:03:09 +0000, Manu <turkeyman gmail.com <mailto:turkeyman gmail.com>> said: So I was thinking about this extern(language) thing, the obvious ones are supported, but it would be really nice to be able to implement custom conventions for other languages/scripting languages. For instance, I'm thinking about Android, I have JNI binding code everywhere, it's really ugly. I'd love to be able to declare: extern(Java) int someJavaFunc(int x, float y) And then use my function like any regular function, with the 'extern(Java)' bit handling the JNI business behind the scenes. these could all be implemented the same way. I'm imaging some mechanism to declare a calling convention (which would be resolved within the extern(...) statement), and define it with a template, something like: callconv Java { R call(T...) { // process tuple of args, make the call, return something? } R thisCall(Class, T...) { // also need a way to implementing methods... this might be enough. } } Some fancy code in there could conceivably call into any foreign language, and this would be great! Now when I: import java.jni; I have the jni interface, but I also have access to extern(Java), and that's awesome! :) In all currently existing cases, extern(Lang) offers not only a way to declare and call foreign-language functions, but also a way to define functions to be called from the foreign language. Basically, you have two-way compatibility. How would that work with Java? Interesting point. Java (or any VM based language) can't hard link to the binary, so it never could try and call back in through an extern-ed function directly,Sure it could. Why wouldn't it be able to? This is how extern +it must be explicitly supplied the pointer in the first place. In that case, the API that supplies the callback to Java can produce the appropriate incoming call wrapper. I can imagine a way to doing a hard-extern under my proposal if you were hard linking against an unsupported language language... you might need to provide a name mangler in the definition block I describe to match the foreign language, and an incoming call template would also need to be defined as a naked function with the responsibility of managing the args/stack appropriately, and calling the externed function as a regular D-call (this would probably only be some light register/stack management, I don't think it would bloat a lot). This would allow D code to also call the externed function, since the physical definition is still a D-call, you just call it directly internally. Anyway, while I can imagine a solution, I don't think it would be needed immediately. It'll just open a further can of worms like foreign language struct layout as people try to use it in complex scenarios ;) I don't think this reduces the usefulness of my proposal at all though, ie. being able to apply it to outgoing calls for any foreign language. - - - Also, I see you're thinking about methods, which means you're thinking about declaring Java classes. How is that supposed to work exactly? Well I was thinking about that with respect to calling functions on classes that I have imported from a foreign language, not declared locally for export to a foreign language. I clearly didn't think that through though, I'll try and clarify my thoughts to that end... I get the feeling that idea was a dead-end though. I have some experience bridging Objective-C and D. I once built a complete wrapper system for Objective-C objects, each object was wrapped by a D one. It worked very well, but it generated so much bloat that it became unusable as soon as I started defining enough classes for it to be useful. See the D/Objective-C bridge: <http://michelf.com/projects/__d-objc-bridge/ <http://michelf.com/projects/d-objc-bridge/>>. What was the primary cause of the bloat? I can't imagine my proposal causing any more bloat than the explicit jni call (or equivalent) woudl have otherwise. Maybe you'll have more luck, but for me wrappers just couldn't work.. So I decided making the compiler understand the Objective-C runtime and object model was a much better solution. It was fun to do and wasn't that hard actually. Here's the result: <http://michelf.com/projects/__d-objc/ <http://michelf.com/projects/d-objc/>>. Unfortunately I don't have much time to work on it anymore. That sounds appropriate for Obj-C, but I don't think it applies to VM based languages however you slice it, since there's not actually a direct binary linkage. There's no way to know about the Java/.NET/Lua/etc object model internally, the VM owns that entirely, so you're forced to marshal through API's. That's okay though, you have to do it anyway. I'm proposing a way to unify the concept of calling functions without obscuring the actual call with junk, and still allowing the D language to annotate and optimise to its fullest extent. More background: <http://michelf.com/weblog/__2010/dobjc-dead-end-start-__anew/ <http://michelf.com/weblog/2010/dobjc-dead-end-start-anew/>> -- Michel Fortin michel.fortin michelf.com <mailto:michel.fortin michelf.com> http://michelf.com/-- - Alex
Feb 21 2012
On 21 February 2012 19:10, Alex R=C3=B8nne Petersen <xtzgzorex gmail.com> w= rote:On 21-02-2012 18:03, Manu wrote:calling convention, so you just need to export an extern(C) in that case, like any regular DLL.On 21 February 2012 16:59, Michel Fortin <michel.fortin michelf.com <mailto:michel.fortin michelf.**com <michel.fortin michelf.com>>> wrote: On 2012-02-21 11:03:09 +0000, Manu <turkeyman gmail.com <mailto:turkeyman gmail.com>> said: Interesting point. Java (or any VM based language) can't hard link to the binary, so it never could try and call back in through an extern-ed function directly,Sure it could. Why wouldn't it be able to? This is how extern + DllImport
Feb 21 2012
On 21-02-2012 20:43, Manu wrote:On 21 February 2012 19:10, Alex Rønne Petersen <xtzgzorex gmail.com <mailto:xtzgzorex gmail.com>> wrote: On 21-02-2012 18:03, Manu wrote: On 21 February 2012 16:59, Michel Fortin <michel.fortin michelf.com <mailto:michel.fortin michelf.com> <mailto:michel.fortin michelf.__com <mailto:michel.fortin michelf.com>>> wrote: On 2012-02-21 11:03:09 +0000, Manu <turkeyman gmail.com <mailto:turkeyman gmail.com> <mailto:turkeyman gmail.com <mailto:turkeyman gmail.com>>> said: Interesting point. Java (or any VM based language) can't hard link to the binary, so it never could try and call back in through an extern-ed function directly, Sure it could. Why wouldn't it be able to? This is how extern + calling convention, so you just need to export an extern(C) in that case, like any regular DLL.Surely Java 'native' methods require the native functions to conform to some calling convention? -- - Alex
Feb 21 2012
On 2012-02-21 18:03, Manu wrote:On 21 February 2012 16:59, Michel Fortin <michel.fortin michelf.com I have some experience bridging Objective-C and D. I once built a complete wrapper system for Objective-C objects, each object was wrapped by a D one. It worked very well, but it generated so much bloat that it became unusable as soon as I started defining enough classes for it to be useful. See the D/Objective-C bridge: <http://michelf.com/projects/__d-objc-bridge/ <http://michelf.com/projects/d-objc-bridge/>>. What was the primary cause of the bloat? I can't imagine my proposal causing any more bloat than the explicit jni call (or equivalent) woudl have otherwise.Template bloat. Every call bridging D/Objective-C is made throw a series of templates. This is for making it possible (less verbose) to create bindings. It might be possible to decrease the template bloat by having a tool that automatically generates the bindings and outputs what the templates do inline. -- /Jacob Carlborg
Feb 21 2012
On 21 February 2012 20:12, Jacob Carlborg <doob me.com> wrote:On 2012-02-21 18:03, Manu wrote:Why aren't the templates inline themselves? Although if the templates do a lot of work, wouldn't that INCREASE the code volume? I can't really imagine how Obj-C linkage could bloat so much, what was involved? What did you have to do in addition to what a regular Obj-C function call would have done?On 21 February 2012 16:59, Michel Fortin <michel.fortin michelf.com I have some experience bridging Objective-C and D. I once built a complete wrapper system for Objective-C objects, each object was wrapped by a D one. It worked very well, but it generated so much bloat that it became unusable as soon as I started defining enough classes for it to be useful. See the D/Objective-C bridge: <http://michelf.com/projects/_**_d-objc-bridge/<http://michelf.com/projects/__d-objc-bridge/> <http://michelf.com/projects/**d-objc-bridge/<http://michelf.com/projects/d-objc-bridge/>Template bloat. Every call bridging D/Objective-C is made throw a series of templates. This is for making it possible (less verbose) to create bindings. It might be possible to decrease the template bloat by having a tool that automatically generates the bindings and outputs what the templates do inline.What was the primary cause of the bloat? I can't imagine my proposal causing any more bloat than the explicit jni call (or equivalent) woudl have otherwise..
Feb 21 2012
On 2012-02-21 19:45:37 +0000, Manu <turkeyman gmail.com> said:On 21 February 2012 20:12, Jacob Carlborg <doob me.com> wrote:I answered in my other post. In short: virtual functions you can override to override Objective-C methods. -- Michel Fortin michel.fortin michelf.com http://michelf.com/On 2012-02-21 18:03, Manu wrote:Why aren't the templates inline themselves? Although if the templates do a lot of work, wouldn't that INCREASE the code volume? I can't really imagine how Obj-C linkage could bloat so much, what was involved? What did you have to do in addition to what a regular Obj-C function call would have done?On 21 February 2012 16:59, Michel Fortin <michel.fortin michelf.com What was the primary cause of the bloat? I can't imagine my proposal causing any more bloat than the explicit jni call (or equivalent) woudl have otherwise.Template bloat. Every call bridging D/Objective-C is made throw a series of templates. This is for making it possible (less verbose) to create bindings. It might be possible to decrease the template bloat by having a tool that automatically generates the bindings and outputs what the templates do inline.
Feb 21 2012
On 2012-02-21 20:45, Manu wrote:On 21 February 2012 20:12, Jacob Carlborg <doob me.com <mailto:doob me.com>> wrote: On 2012-02-21 18:03, Manu wrote: On 21 February 2012 16:59, Michel Fortin <michel.fortin michelf.com <mailto:michel.fortin michelf.com> I have some experience bridging Objective-C and D. I once built a complete wrapper system for Objective-C objects, each object was wrapped by a D one. It worked very well, but it generated so much bloat that it became unusable as soon as I started defining enough classes for it to be useful. See the D/Objective-C bridge: <http://michelf.com/projects/____d-objc-bridge/ <http://michelf.com/projects/__d-objc-bridge/> <http://michelf.com/projects/__d-objc-bridge/ <http://michelf.com/projects/d-objc-bridge/>>>. What was the primary cause of the bloat? I can't imagine my proposal causing any more bloat than the explicit jni call (or equivalent) woudl have otherwise. Template bloat. Every call bridging D/Objective-C is made throw a series of templates. This is for making it possible (less verbose) to create bindings. It might be possible to decrease the template bloat by having a tool that automatically generates the bindings and outputs what the templates do inline. Why aren't the templates inline themselves? Although if the templates do a lot of work, wouldn't that INCREASE the code volume? I can't really imagine how Obj-C linkage could bloat so much, what was involved? What did you have to do in addition to what a regular Obj-C function call would have done?Michel Fortin explained this better in two of his answers. You can also read the documentation of my implementation, very similar to Michel's: http://www.dsource.org/projects/dstep/wiki/ObjcBridge/BridgeInternals But to give a quick example: class Foo : NSObject { Foo foo () { return invokeObjcSelf!(Foo, "foo"); } Foo bar () { return invokeObjcSelf!(Foo, "bar"); } } "invokeObjcSelf" is a template function that calls an Objective-C method. Basically each time "invokeObjcSelf" is called a new instantiation of the template is created and that is put in the symbol table. "invokeObjcSelf" then calls several more template functions making the template bloat increase exponentially. -- /Jacob Carlborg
Feb 21 2012
On 21 February 2012 22:35, Jacob Carlborg <doob me.com> wrote:On 2012-02-21 20:45, Manu wrote:But they should all be inlined, and the symbol table should be stripped, which shouldn't leave anything in the end other than the inlined function calling code, and in my examples, this will be basically the exact same code that you'd have to write anyway to call through some vm's API...On 21 February 2012 20:12, Jacob Carlborg <doob me.com <mailto:doob me.com>> wrote: On 2012-02-21 18:03, Manu wrote: On 21 February 2012 16:59, Michel Fortin <michel.fortin michelf.com <mailto:michel.fortin michelf.**com<michel.fortin michelf.com>Michel Fortin explained this better in two of his answers. You can also read the documentation of my implementation, very similar to Michel's: http://www.dsource.org/**projects/dstep/wiki/**ObjcBridge/BridgeInternals<http://www.dsource.org/projects/dstep/wiki/ObjcBridge/BridgeInternals> But to give a quick example: class Foo : NSObject { Foo foo () { return invokeObjcSelf!(Foo, "foo"); } Foo bar () { return invokeObjcSelf!(Foo, "bar"); } } "invokeObjcSelf" is a template function that calls an Objective-C method. Basically each time "invokeObjcSelf" is called a new instantiation of the template is created and that is put in the symbol table. "invokeObjcSelf" then calls several more template functions making the template bloat increase exponentially.I have some experience bridging Objective-C and D. I once built a complete wrapper system for Objective-C objects, each object was wrapped by a D one. It worked very well, but it generated so much bloat that it became unusable as soon as I started defining enough classes for it to be useful. See the D/Objective-C bridge: <http://michelf.com/projects/_**___d-objc-bridge/<http://michelf.com/projects/____d-objc-bridge/> <http://michelf.com/projects/_**_d-objc-bridge/<http://michelf.com/projects/__d-objc-bridge/><http://michelf.com/projects/_**_d-objc-bridge/<http://michelf.com/projects/__d-objc-bridge/> <http://michelf.com/projects/**d-objc-bridge/<http://michelf.com/projects/d-objc-bridge/>What was the primary cause of the bloat? I can't imagine my proposal causing any more bloat than the explicit jni call (or equivalent) woudl have otherwise. Template bloat. Every call bridging D/Objective-C is made throw a series of templates. This is for making it possible (less verbose) to create bindings. It might be possible to decrease the template bloat by having a tool that automatically generates the bindings and outputs what the templates do inline. Why aren't the templates inline themselves? Although if the templates do a lot of work, wouldn't that INCREASE the code volume? I can't really imagine how Obj-C linkage could bloat so much, what was involved? What did you have to do in addition to what a regular Obj-C function call would have done?.
Feb 21 2012
On 2012-02-21 22:01, Manu wrote:On 21 February 2012 22:35, Jacob Carlborg <doob me.com <mailto:doob me.com>> wrote: On 2012-02-21 20:45, Manu wrote: On 21 February 2012 20:12, Jacob Carlborg <doob me.com <mailto:doob me.com> <mailto:doob me.com <mailto:doob me.com>>> wrote: On 2012-02-21 18:03, Manu wrote: On 21 February 2012 16:59, Michel Fortin <michel.fortin michelf.com <mailto:michel.fortin michelf.com> <mailto:michel.fortin michelf.__com <mailto:michel.fortin michelf.com>> I have some experience bridging Objective-C and D. I once built a complete wrapper system for Objective-C objects, each object was wrapped by a D one. It worked very well, but it generated so much bloat that it became unusable as soon as I started defining enough classes for it to be useful. See the D/Objective-C bridge: <http://michelf.com/projects/______d-objc-bridge/ <http://michelf.com/projects/____d-objc-bridge/> <http://michelf.com/projects/____d-objc-bridge/ <http://michelf.com/projects/__d-objc-bridge/>> <http://michelf.com/projects/____d-objc-bridge/ <http://michelf.com/projects/__d-objc-bridge/> <http://michelf.com/projects/__d-objc-bridge/ <http://michelf.com/projects/d-objc-bridge/>>>>. What was the primary cause of the bloat? I can't imagine my proposal causing any more bloat than the explicit jni call (or equivalent) woudl have otherwise. Template bloat. Every call bridging D/Objective-C is made throw a series of templates. This is for making it possible (less verbose) to create bindings. It might be possible to decrease the template bloat by having a tool that automatically generates the bindings and outputs what the templates do inline. Why aren't the templates inline themselves? Although if the templates do a lot of work, wouldn't that INCREASE the code volume? I can't really imagine how Obj-C linkage could bloat so much, what was involved? What did you have to do in addition to what a regular Obj-C function call would have done? Michel Fortin explained this better in two of his answers. You can also read the documentation of my implementation, very similar to Michel's: http://www.dsource.org/__projects/dstep/wiki/__ObjcBridge/BridgeInternals <http://www.dsource.org/projects/dstep/wiki/ObjcBridge/BridgeInternals> But to give a quick example: class Foo : NSObject { Foo foo () { return invokeObjcSelf!(Foo, "foo"); } Foo bar () { return invokeObjcSelf!(Foo, "bar"); } } "invokeObjcSelf" is a template function that calls an Objective-C method. Basically each time "invokeObjcSelf" is called a new instantiation of the template is created and that is put in the symbol table. "invokeObjcSelf" then calls several more template functions making the template bloat increase exponentially. But they should all be inlined, and the symbol table should be stripped, which shouldn't leave anything in the end other than the inlined function calling code, and in my examples, this will be basically the exact same code that you'd have to write anyway to call through some vm's API...Well, that's not what happen with templates. -- /Jacob Carlborg
Feb 21 2012
On 21 February 2012 23:06, Jacob Carlborg <doob me.com> wrote:On 2012-02-21 22:01, Manu wrote:... really? why? You've just made me very very scared for my simd module :/ I've had a serious concern about D's lack of a force-inline for quite a while...On 21 February 2012 22:35, Jacob Carlborg <doob me.com <mailto:doob me.com>> wrote: On 2012-02-21 20:45, Manu wrote: On 21 February 2012 20:12, Jacob Carlborg <doob me.com <mailto:doob me.com> <mailto:doob me.com <mailto:doob me.com>>> wrote: On 2012-02-21 18:03, Manu wrote: On 21 February 2012 16:59, Michel Fortin <michel.fortin michelf.com <mailto:michel.fortin michelf.**com<michel.fortin michelf.com>Well, that's not what happen with templates.<mailto:michel.fortin michelf.**__com <mailto:michel.fortin michelf.**com <michel.fortin michelf.com>>> I have some experience bridging Objective-C and D. I once built a complete wrapper system for Objective-C objects, each object was wrapped by a D one. It worked very well, but it generated so much bloat that it became unusable as soon as I started defining enough classes for it to be useful. See the D/Objective-C bridge: <http://michelf.com/projects/_**_____d-objc-bridge/<http://michelf.com/projects/______d-objc-bridge/> <http://michelf.com/projects/_**___d-objc-bridge/<http://michelf.com/projects/____d-objc-bridge/><http://michelf.com/projects/_**___d-objc-bridge/<http://michelf.com/projects/____d-objc-bridge/> <http://michelf.com/projects/_**_d-objc-bridge/<http://michelf.com/projects/__d-objc-bridge/><http://michelf.com/projects/_**___d-objc-bridge/<http://michelf.com/projects/____d-objc-bridge/> <http://michelf.com/projects/_**_d-objc-bridge/<http://michelf.com/projects/__d-objc-bridge/><http://michelf.com/projects/_**_d-objc-bridge/<http://michelf.com/projects/__d-objc-bridge/> <http://michelf.com/projects/**d-objc-bridge/<http://michelf.com/projects/d-objc-bridge/>What was the primary cause of the bloat? I can't imagine my proposal causing any more bloat than the explicit jni call (or equivalent) woudl have otherwise. Template bloat. Every call bridging D/Objective-C is made throw a series of templates. This is for making it possible (less verbose) to create bindings. It might be possible to decrease the template bloat by having a tool that automatically generates the bindings and outputs what the templates do inline. Why aren't the templates inline themselves? Although if the templates do a lot of work, wouldn't that INCREASE the code volume? I can't really imagine how Obj-C linkage could bloat so much, what was involved? What did you have to do in addition to what a regular Obj-C function call would have done? Michel Fortin explained this better in two of his answers. You can also read the documentation of my implementation, very similar to Michel's: http://www.dsource.org/__**projects/dstep/wiki/__** ObjcBridge/BridgeInternals<http://www.dsource.org/__projects/dstep/wiki/__ObjcBridge/BridgeInternals> <http://www.dsource.org/**projects/dstep/wiki/** ObjcBridge/BridgeInternals<http://www.dsource.org/projects/dstep/wiki/ObjcBridge/BridgeInternals>.But to give a quick example: class Foo : NSObject { Foo foo () { return invokeObjcSelf!(Foo, "foo"); } Foo bar () { return invokeObjcSelf!(Foo, "bar"); } } "invokeObjcSelf" is a template function that calls an Objective-C method. Basically each time "invokeObjcSelf" is called a new instantiation of the template is created and that is put in the symbol table. "invokeObjcSelf" then calls several more template functions making the template bloat increase exponentially. But they should all be inlined, and the symbol table should be stripped, which shouldn't leave anything in the end other than the inlined function calling code, and in my examples, this will be basically the exact same code that you'd have to write anyway to call through some vm's API...
Feb 21 2012
On 2012-02-21 23:13:31 +0000, Manu <turkeyman gmail.com> said:On 21 February 2012 23:06, Jacob Carlborg <doob me.com> wrote:I'm not sure what Jacob is referring to. But here's what I can tell: Foo's methods can't be stripped because they're referenced by the virtual table. invokeObjcSelf could be inlined in theory, but it probably isn't because it is not that small considering it actually does exception bridging and argument/return value conversions as needed. Also, for each method there's also a trampoline function generated (by a mixin which is not in his example) which is referenced by the corresponding Objective-C reverse wrapper class (which is added dynamically on demand), so the Objective-C side can call the D method if you subclass the D wrapper and override one of its methods. The problem is that if you write bindings for a significant part of Cocoa, you end up with thousands of those functions, and none can be stripped because they're all referenced somehow because they're needed for dynamic dispatch. Sure, you could inline what is inside the virtual function (invokeObjcSelf), but beside saving a few function prologues I don't expect it'll have a very noticeable effect. Even if you saved 25% of the symbols it won't bring things to a reasonable size or a reasonable compilation time. -- Michel Fortin michel.fortin michelf.com http://michelf.com/On 2012-02-21 22:01, Manu wrote:... really? why? You've just made me very very scared for my simd module :/ I've had a serious concern about D's lack of a force-inline for quite a while...On 21 February 2012 22:35, Jacob Carlborg <doob me.comWell, that's not what happen with templates.But to give a quick example: class Foo : NSObject { Foo foo () { return invokeObjcSelf!(Foo, "foo"); } Foo bar () { return invokeObjcSelf!(Foo, "bar"); } } "invokeObjcSelf" is a template function that calls an Objective-C method. Basically each time "invokeObjcSelf" is called a new instantiation of the template is created and that is put in the symbol table. "invokeObjcSelf" then calls several more template functions making the template bloat increase exponentially.But they should all be inlined, and the symbol table should be stripped, which shouldn't leave anything in the end other than the inlined function calling code, and in my examples, this will be basically the exact same code that you'd have to write anyway to call through some vm's API...
Feb 21 2012
On 2012-02-22 05:38, Michel Fortin wrote:On 2012-02-21 23:13:31 +0000, Manu <turkeyman gmail.com> said:I referring to that every instantiation of a template function is put in the symbol table. If this is an implementation issue with DMD not being able to properly optimize this I don't know. I thought that this was one of the major reason for the executable size when using the Objective-C/D bridge. For example: void foo () {} void main () {} $ dmd -inline -O -release main.d $ nm main | grep foo 00000001000012b4 T _D4main3fooFZv Outputs one symbol as expected --------------------------------------- void foo (T) () {} void main () {} $ dmd -inline -O -release main.d $ nm main | grep foo Doesn't output anything since the template functions is not instantiated, it won't even be fully compiled (only lexed and perhaps parsed). -------------------------------------------------------------- void foo (T) () {} void main () { foo!(int); foo!(char); } $ dmd -inline -O -release main.d $ nm main | grep foo 00000001000012b8 T _D4main10__T3fooTaZ3fooFZv 00000001000012b0 T _D4main10__T3fooTiZ3fooFZv Outputs two symbols as expected, one for each instantiation. -- /Jacob CarlborgOn 21 February 2012 23:06, Jacob Carlborg <doob me.com> wrote:I'm not sure what Jacob is referring to.On 2012-02-21 22:01, Manu wrote:... really? why? You've just made me very very scared for my simd module :/ I've had a serious concern about D's lack of a force-inline for quite a while...On 21 February 2012 22:35, Jacob Carlborg <doob me.comWell, that's not what happen with templates.But to give a quick example: class Foo : NSObject { Foo foo () { return invokeObjcSelf!(Foo, "foo"); } Foo bar () { return invokeObjcSelf!(Foo, "bar"); } } "invokeObjcSelf" is a template function that calls an Objective-C method. Basically each time "invokeObjcSelf" is called a new instantiation of the template is created and that is put in the symbol table. "invokeObjcSelf" then calls several more template functions making the template bloat increase exponentially.But they should all be inlined, and the symbol table should be stripped, which shouldn't leave anything in the end other than the inlined function calling code, and in my examples, this will be basically the exact same code that you'd have to write anyway to call through some vm's API...
Feb 21 2012
On 2012-02-22 07:41:21 +0000, Jacob Carlborg <doob me.com> said:void foo (T) () {} void main () { foo!(int); foo!(char); } $ dmd -inline -O -release main.d $ nm main | grep foo 00000001000012b8 T _D4main10__T3fooTaZ3fooFZv 00000001000012b0 T _D4main10__T3fooTiZ3fooFZv Outputs two symbols as expected, one for each instantiation.That's expected indeed. This doesn't mean the inliner will not inline the templates. In fact, if you correct the example and look at the assembler output you'll see it will (in your example there is nothing to inline since you're just instantiating the template without calling it). What doesn't happen is stripping the unreferenced symbols from the executable. On OS X, try adding "-L-dead_strip" to DMD's argument to instruct the linker to do so. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 22 2012
On 2012-02-22 13:53, Michel Fortin wrote:On 2012-02-22 07:41:21 +0000, Jacob Carlborg <doob me.com> said:1. The example is correct, you can call a method without parentheses 2. Adding -L-dead_strip does not seem to strip the "foo" symbols 3. Adding -L-dead_strip causes a segmentation fault with this example (DMD 2.057) import std.stdio; void foo (T) () { writeln("asd"); } void main () { foo!(int); foo!(char); } 4. I thought the reason for the big executable using the Objective-C/D bridge was due to all these template symbols. -- /Jacob Carlborgvoid foo (T) () {} void main () { foo!(int); foo!(char); } $ dmd -inline -O -release main.d $ nm main | grep foo 00000001000012b8 T _D4main10__T3fooTaZ3fooFZv 00000001000012b0 T _D4main10__T3fooTiZ3fooFZv Outputs two symbols as expected, one for each instantiation.That's expected indeed. This doesn't mean the inliner will not inline the templates. In fact, if you correct the example and look at the assembler output you'll see it will (in your example there is nothing to inline since you're just instantiating the template without calling it). What doesn't happen is stripping the unreferenced symbols from the executable. On OS X, try adding "-L-dead_strip" to DMD's argument to instruct the linker to do so.
Feb 22 2012
On Wed, Feb 22, 2012 at 06:32:14PM +0100, Jacob Carlborg wrote: [...]1. The example is correct, you can call a method without parentheses[...] This is not directly related, but isn't calling methods without parentheses deprecated, unless it's marked property? I thought we will soon enforce property. T -- Talk is cheap. Whining is actually free. -- Lars Wirzenius
Feb 22 2012
On 2012-02-22 18:40, H. S. Teoh wrote:On Wed, Feb 22, 2012 at 06:32:14PM +0100, Jacob Carlborg wrote: [...]As I understand it, that will most likely be where we're going. But we're not there yet. -- /Jacob Carlborg1. The example is correct, you can call a method without parentheses[...] This is not directly related, but isn't calling methods without parentheses deprecated, unless it's marked property? I thought we will soon enforce property.
Feb 22 2012
On 2012-02-22 17:32:14 +0000, Jacob Carlborg <doob me.com> said:On 2012-02-22 13:53, Michel Fortin wrote:Ah, seems I forgot this.On 2012-02-22 07:41:21 +0000, Jacob Carlborg <doob me.com> said:1. The example is correct, you can call a method without parenthesesvoid foo (T) () {} void main () { foo!(int); foo!(char); } $ dmd -inline -O -release main.d $ nm main | grep foo 00000001000012b8 T _D4main10__T3fooTaZ3fooFZv 00000001000012b0 T _D4main10__T3fooTiZ3fooFZv Outputs two symbols as expected, one for each instantiation.That's expected indeed. This doesn't mean the inliner will not inline the templates. In fact, if you correct the example and look at the assembler output you'll see it will (in your example there is nothing to inline since you're just instantiating the template without calling it). What doesn't happen is stripping the unreferenced symbols from the executable. On OS X, try adding "-L-dead_strip" to DMD's argument to instruct the linker to do so.2. Adding -L-dead_strip does not seem to strip the "foo" symbols 3. Adding -L-dead_strip causes a segmentation fault with this example (DMD 2.057) import std.stdio; void foo (T) () { writeln("asd"); } void main () { foo!(int); foo!(char); }I'm still on v2.055. And I can confirm -L-dead_strip worked for me, but I did a change similar to yours so the template was calling printf (that makes it easier to see if it was inlined when looking at the assembly). Everything worked as expected with printf. Calling writeln, which is a template itself, which could be inlined into foo, could cause foo to not be inlined, although it doesn't explain the segfault. I'm starting to suspect the empty version of foo doesn't get inlined for some reason.4. I thought the reason for the big executable using the Objective-C/D bridge was due to all these template symbols.I might have been, but I'd be surprised I didn't try striping the executable to fix the problem. In the end, mostly all the instantiated code has to be there for the virtual tables. There's almost one instanciation per method, and that is a lot of bloat. Whether the template instanciation is inlined or not just changes under which symbol the code resides, the code doesn't magically disappear, it still has to be there somewhere. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 22 2012
On 2012-02-22 19:39, Michel Fortin wrote:On 2012-02-22 17:32:14 +0000, Jacob Carlborg <doob me.com> said:Yes, exactly. -- /Jacob CarlborgOn 2012-02-22 13:53, Michel Fortin wrote:Ah, seems I forgot this.On 2012-02-22 07:41:21 +0000, Jacob Carlborg <doob me.com> said:1. The example is correct, you can call a method without parenthesesvoid foo (T) () {} void main () { foo!(int); foo!(char); } $ dmd -inline -O -release main.d $ nm main | grep foo 00000001000012b8 T _D4main10__T3fooTaZ3fooFZv 00000001000012b0 T _D4main10__T3fooTiZ3fooFZv Outputs two symbols as expected, one for each instantiation.That's expected indeed. This doesn't mean the inliner will not inline the templates. In fact, if you correct the example and look at the assembler output you'll see it will (in your example there is nothing to inline since you're just instantiating the template without calling it). What doesn't happen is stripping the unreferenced symbols from the executable. On OS X, try adding "-L-dead_strip" to DMD's argument to instruct the linker to do so.2. Adding -L-dead_strip does not seem to strip the "foo" symbols 3. Adding -L-dead_strip causes a segmentation fault with this example (DMD 2.057) import std.stdio; void foo (T) () { writeln("asd"); } void main () { foo!(int); foo!(char); }I'm still on v2.055. And I can confirm -L-dead_strip worked for me, but I did a change similar to yours so the template was calling printf (that makes it easier to see if it was inlined when looking at the assembly). Everything worked as expected with printf. Calling writeln, which is a template itself, which could be inlined into foo, could cause foo to not be inlined, although it doesn't explain the segfault. I'm starting to suspect the empty version of foo doesn't get inlined for some reason.4. I thought the reason for the big executable using the Objective-C/D bridge was due to all these template symbols.I might have been, but I'd be surprised I didn't try striping the executable to fix the problem. In the end, mostly all the instantiated code has to be there for the virtual tables. There's almost one instanciation per method, and that is a lot of bloat. Whether the template instanciation is inlined or not just changes under which symbol the code resides, the code doesn't magically disappear, it still has to be there somewhere.
Feb 22 2012
On 2012-02-22 00:13, Manu wrote:On 21 February 2012 23:06, Jacob Carlborg <doob me.com Well, that's not what happen with templates. ... really? why? You've just made me very very scared for my simd module :/I've answered to this in an answer to Michel's answer.I've had a serious concern about D's lack of a force-inline for quite a while...-- /Jacob Carlborg
Feb 21 2012
On 2012-02-21 17:03:56 +0000, Manu <turkeyman gmail.com> said:What was the primary cause of the bloat? I can't imagine my proposal causing any more bloat than the explicit jni call (or equivalent) woudl have otherwise.I had one D class for every corresponding Objective-C class, each method wrapped in both direction, each wrapper doing automatic mapping of D and Objective-C wrapper objects and translating exceptions. I could actually override a method in a derived class of the D wrapper and it'd effectively override the method on the Objective-C side. But with all those D classes having virtual tables referring to all these wrapper functions, even if you use only 1% of all the bindings nothing can be stripped of the final executable. Quoting from a blog post of mine: """ But the real show stopper is the size of the generated code for the bindings. The system I created needs to generate a lot of code for each and every one of the functions and classes you define bindings for. This makes the final executable awfully big (and might also explain in part the slowness while compiling). The small test application included with the bridge takes about 60 Mb of code, thats for something that’d be only a few kilobytes when written in Objective-C. This wasn’t the case at first. This bloat appeared as I added bindings for more and more classes in Cocoa. It is a real problem because no one in his right mind will want to ship a 60 Mb application that contains so much binding code that stay unused most of the time. A solution could be that everyone would have to write bindings that only contains the classes and methods he needs, but this is of rather limited interest. """UnfortunatelyMaybe you'll have more luck, but for me wrappers just couldn't work. So I decided making the compiler understand the Objective-C runtime and object model was a much better solution. It was fun to do and wasn't that hard actually. Here's the result: <http://michelf.com/projects/**d-objc/<http://michelf.com/projects/d-objc/>>.That's not actually very different from what I'm doing for Objective-C. Call to Objective-C methods are all done through low-level API functions in the Objective-C runtime. Class definitions are static data, but could be done dynamically through API calls in module constructors. The most interesting bit however is that class *declarations* require nothing to be compiled, the compiler will just emit the right code when calling a method, using objc_msgSend(). This has a major impact on compilation time if you have thousands of such functions.I don't have much time to work on it anymore.That sounds appropriate for Obj-C, but I don't think it applies to VM based languages however you slice it, since there's not actually a direct binary linkage. There's no way to know about the Java/.NET/Lua/etc object model internally, the VM owns that entirely, so you're forced to marshal through API's.That's okay though, you have to do it anyway. I'm proposing a way to unify the concept of calling functions without obscuring the actual call with junk, and still allowing the D language to annotate and optimise to its fullest extent.The goal is certainly worthwhile. I think your proposal has merit if you goal is just to call functions and not define function or classes, although I'm skeptical overloading extern() is the right way to do that (perhaps a pragma?). But I'd suggest you define your goals more throughly before deciding on an implementation. Some questions you should try to have an answer for regarding OO: if you're interacting with classes, how should it work in an ideal world? Then, do you need to define new classes that'd be available in the foreign language? Do you need to override functions on existing classes? How do you want code using foreign objects to look? Then ask yourself what would be an acceptable compromise, and start implementing it. For my part, I came to the conclusion that you couldn't really use Objective-C APIs in a meaningful way without the ability to create subclasses and override functions… which led me to the current design where you can use Objective-C classes as if they were D classes. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 21 2012