Plain Text | 65 lines | 54 code | 11 blank | 0 comment | 0 complexity | 2d377a1ad7bb8101acd5bced3203cec1 MD5 | raw file
110-20-2010 2Added submodules for dependencies, working on making them build correctly now. 3 48-31-2010 5I'd like to make certain commonly called function types such as "float getX()" and "void setX(float x)" perform as fast as possible by 6adding the ability to bypass the general purpose code and call straight to the CFunction that runs it. 7Io calls the CFunctions "blindly" without the ability to 8attach a user-defined data struct (such as by an additional void* parameter in the user method call), so we have to provide a unique 9function entry point for each "fast" function to bind. This brings us back full circle to the original design, which was to have 10a "template <typename F, F f> bind()" that's parameterized on the address of the bound function. (Note that passing the function 11address this way, as a template constant parameter, theoretically should produce identical code to a "call-by-name" implementation 12based on C macros. There is no need to use C macros for this at all except to wrap the top level, to avoid having to type 13the name of the function twice as in "bind<decltype(&f), (&f)>(name)".) 14 15This design requires doing the entire process (including marshalling) totally via templates. However with the benefit of experience 16we can be smarter about the design this time. First, we won't try to do all bindings this way; we'll keep the general purpose 17way we have now as a default and focus on only binding the most often used functions with the template/constant address technique. 18 19Second, we can use variadic templates to have it accept a list of policies (or a TypePack, or a tuple) for calls. (Note: 20I think we can handle call context in the following way: language agnostic side creates a function that accepts a Policy::CallContext 21type of argument and forwards that object to each Policy::ConvertTo<type> or Policy::ConvertFrom(type) call. 22Return value might well be stored into the context object too. Each language-specific policy creates a CallContext object 23specific to its implementation. (E.g. for Io it would be IoObject pointers for self, locals, and message (or possibly the args).) 24It would call back into the language-agnostic portion to complete the work. 25 26Third, we will put the optimized bindings into their own separate files by convention (because the template-based system 27will need to pull in nearly all of its implementation via #includes; it trades runtime speed for more compiler work. 28 29A powergoal would be to have the "fast" calls and the FromScript and ToScript type converters use the same code (that is, promote 30the implementation of the ToScript and FromScript converters into the language Policy and change the converters to call it). 31 32A nice-to-have item is to have the ability to parameterize the called functions by function-address-constant or NOT do that and 33only parameterize them by type (for instance, taking the function address from CallContext). This would allow Policies for some 34languages to only define one instance of a function for all bindings with that signature (for instance these implementations 35might attach the actual function pointer to call as part of the CallContext object). This might not have much 36effect on executable size though, especially considering Io cannot use this anyway. Perhaps it should be added when it is needed. 37 38Major limitations of fast call are: 39No type converter chaining can be done for these (or can we do some with metaprogramming?) 40No SFMO on "fast call" functions. (What is the result of trying? Can we detect it and print an error? Should we/can we try "downgrade" 41the fast call to the general call in SFMO contexts?) 42Also how do we have the instance-based IoVM and RuntimeTypeSystem objects "find" the fast implementations. 43 44Bikeshedding question: should we put the list of policies into a typepack? Use a bare list? Define a macro for the bare list? Use BOOST_PREPROCESSOR lists? 45Must re-read Alexandrescu book and see if/how he addresses this issue. 46 47Implementation concern: gcc 4.4.x doesn't allow local classes (those defined inline in a function body) to participate as template types. 48Can the fast call system be implemented using local classes / by function template mapping alone? Otherwise will need to declare 49these in class scope, or update to gcc 4.5 on all platforms. It would be nice to be able to add these fast call definitions 50directly to RuntimeTypeSystem/Class objects without them having to "search" for them. Also if they are namespace-level declared, 51they still need to have a runtime call inside a function somewhere to "activate" them. We could have them have use singleton-like 52technique of global instance + constructor run before main to register them and have runtime type system look for them, or 53we could require manually adding to runtime type system / class objects. A possible benefit of manual adding is then you could 54choose whether or not to add fastcall, but downside would be that you might forget, and you'd need to change two different files. 55 568-13-2010 57After several days' debugging, I have finally tracked down a segfault to a type conv problem (must remember to print out type converter descriptions 58more often in case it's doing a surprising conversion). In this case the feature of direct conversion from IoNil to a C++ null of any pointer type backfired 59on me, because it was converting nil to a bool* and then dereferencing it. Unfortunately that's fewer steps (or no more than) the correct conversion. 60 61I've known this problem would strike eventually so I have thought about adding weights to the type conversions and switching to djikstra's algorithm, 62but so far I have always been able to "solve" these problems by adding shortcut conversions - for instance in this case I think it's fair to add 63a shortcut conversion from IoNil to C++ "false". Anyway using weighted paths could have their own unintended consequences; suppose I set the IoNil 64to pointer conversion with a weight of 1000 to prevent it from being used indiscriminantly; this could lead to the type converter building a 65Rube Goldberg chain out of low-weight converts when I actually do want to do a nil to null pointer conversion.