On Tue, 17 May 2022 08:41:59 GMT, Maurizio Cimadamore <mcimadam...@openjdk.org> wrote:
>> Jorn Vernee has updated the pull request incrementally with one additional >> commit since the last revision: >> >> BootstrapMethodError -> ExceptionInInitializerError > > src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java > line 291: > >> 289: emitGetStatic(Binding.Context.class, "DUMMY", >> BINDING_CONTEXT_DESC); >> 290: } else { >> 291: emitInvokeStatic(Binding.Context.class, "ofSession", >> OF_SESSION_DESC); > > Maybe this is micro-optimization, but I realized that in reality we probably > don't need any scope/session if there are no "ToSegment" bindings. Done > src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java > line 336: > >> 334: >> 335: if (callingSequence.forUpcall()) { >> 336: // for upcalls, recipes have a result, which we handle >> here > > I find this part a bit confusing. The comment speaks about recipes input and > outputs, hinting at the fact that downcall bindings have inputs, while upcall > bindings have outputs. > In reality, if we look at the bindings themselves, they look pretty symmetric: > > * UNBOX_ADDRESS = pops an Addressable and push a long on the stack > * BOX_ADDRESS = pops a long and push a MemoryAddress on the stack > > That is, in both cases it appears we have an input and an output (and the > binding is just the function which maps one into another). > > I think the input/output asymmetry comes in when we consider the full > recipes. In downcalls, for a given argument we will have the following > sequence: > > Binding0, Binding1, ... BindingN-1, VMStore > > While for upcalls we will have: > > VMLoad, Binding1, Binding2, ... BindingN > > So (ignoring return buffer for simplicity), for downcalls, it is obvious that > before we can execute Binding0, we need some kind of "input value" (e.g. the > value of some local). For upcalls, this is not needed, as the VMLoad binding > will basically do that for free. > When we finished executing the bindings, again, for downcalls there's nothing > to do, as the chain always ends with a VMStore (which stores binding result > into some local), while for upcalls we do need to set the output value > explicitly. > > In other words, it seems to me that having VMLoad and VMStore in the chains > of bindings to be interpreted/specialized does more harm than good here. > These low level bindings make sense for the VM code, as the VM needs to know > how to load a value from a register, or how to store a value into a register. > But in terms of the specializing Java code, these bindings are immaterial. At > the same time, the fact that we have these bindings, and that they are > virtualized, makes the code hard to follow, as some preparation happens in > `BindingSpecializer::specialize`, while some other preparation happens inside > `BindingSpecializer::doBindings`, as part of the virtualized impl of > VMLoad/VMStore. And, this virtualized implementation ends up doing similar > steps as what the preparation code before/after the binding execution does > (e.g. for downcalls/VMStore we call setOutput, while for upcalls/VMLoad we > call getInput). > > All I'm saying here is that, for bindings to work, we _always_ need to call > both getInput and setOutput - but it is easy to overlook this when looking at > the code, because the getInput/setOutput calls are spread across two > different places in the specializing code, perhaps making things more > asymmetric than they need to be. (I realize I'm simplifying here, and that > some details of the return buffer are not 100% quite as symmetric). I'm not sure if there is anything actionable here? I've thought in the past that it might be nice to have `GetArgument`/`SetArgument` and `GetReturnValue`/`SetReturnValue` binding operators as well, to make the inputs/outputs more explicit in the recipe. But, it doesn't seem like that would make things _much_ better... ------------- PR: https://git.openjdk.java.net/jdk/pull/8685