PageRenderTime 14ms CodeModel.GetById 9ms app.highlight 2ms RepoModel.GetById 1ms app.codeStats 0ms

Plain Text | 65 lines | 54 code | 11 blank | 0 comment | 0 complexity | 2d377a1ad7bb8101acd5bced3203cec1 MD5 | raw file
 2Added submodules for dependencies, working on making them build correctly now.
 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)".)
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.
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.
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.
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).
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.
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.
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.
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.
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.
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.