notes on binding C++

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Wed Jan 31 11:12:00 UTC 2018



On 31/01/18 07:05, Samuel Audet wrote:
> So that's what UpcallHandler is for, good to know! Yes, this is neat. 
> It's basically libffi on steroids. It would be nice to have this 
> documented somewhere.
>
> Now, I will eventually figure out something that is not supported by 
> jextract to make my point :) What about function-like macros? How are 
> those supported? We basically have the same problem with C++ 
> templates: We need a C/C++ compiler to compile them and the compiler 
> needed by the library the user wants to use might not be Clang. And as 
> I pointed out previously, although Clang usually emulates GCC pretty 
> well, it does not work so well in the case of Visual Studio:
> https://clang.llvm.org/docs/MSVCCompatibility.html
> No mention of MSVC 2017! And we're 2018 already...
A macro is... a macro. It doesn't leave trace of any kind in a 
.so/.dll/.dynsym file, so it's not clear as to why jextract should worry 
about macros (at least at this phase of the project).
> When I mean "abandon" I mean abandon the current effort to support C++ 
> with jextract because the specs will have been frozen in stone, unable 
> to make accommodations for C++.
I think what we would like to set in stone is some kind of API, 
interfaces, annotations to describe native layouts and native function 
entry points. Those are the basic building bricks that are needed for 
any kind of follow up work - the 'primitives' of this native interop 
game. But once the dust settles on that front, nothing prevents us from 
allowing more metadata for describing more exotic things (such as 
compiler-generated constructs, as C++ templates). The way I see this is 
as a layered cake; to get at the upper layers you need the bottom 
layers; to implement John's proposal (linked in a previous email) with 
jextract generating snippets with 'simple' C entry points you need glue 
to implement those 'simple' C entry points.
>
> How about this, how about we include in jextract a "fallback mode" 
> that basically does what JavaCPP does, and uses JNI along with a C/C++ 
> compiler provided by the user? I mean, it is possible to come up with 
> a whole new C++ runtime, which can instantiate templates for a number 
> of other C++ runtimes (basically figuring out how to do what Clang 
> itself is not even able to do), but do we care? For example, very few 
> people care about features like virtual inheritance, but they are 
> there, and they are required to use some C++ libraries. Since virtual 
> inheritance, for example, is an inefficient feature of the C++ 
> language, it is not something developers use for performance sensitive 
> calls. We could let the C++ compiler figure itself out and we make the 
> call with JNI, until someone complains that this is "slow", but in my 
> opinion that moment will not arrive because it is an inherently 
> inefficient call. The call gets made, it works, that's all that 
> matters, for now.
>
> With a fallback mode in place in the specs, we (the community) could 
> then comfortably be reassured that jextract can be extended with JNI 
> --because we know that that works--whenever required. Why not do it?
I believe doing this would essentially defeat the goal of Panama, which 
is to deliver ease of use, safety and performances, as described in this 
(old but still very relevant) document by John:

http://cr.openjdk.java.net/~jrose/panama/isthmus-in-the-vm-2014.html

The name of the game here is to build enough VM infrastructure so that 
the VM can reason about calls into native API points; which means it can 
optimize them as would for any other piece of Java code, and guarantee 
some kind of basic safety - all things that cannot be achieved when 
going through an opaque JNI layer. This effort is not in opposition with 
what JavaCPP and other tools are doing; but in my opinion the right 
question is not whether Panama at some point will be expressive enough 
to incorporate JavaCPP - I envision there will always be a tiny amount 
of corner cases that one framework is better/more equipped at handling 
than another - but, rather, as to what can Panama do to make life easier 
for tools such as JavaCPP?

Maurizio

>
> Samuel
>
> On 01/31/2018 06:32 AM, Maurizio Cimadamore wrote:
>>
>> On 30/01/18 11:59, Samuel Audet wrote:
>>> Yes, performance improvement for C is the priority, and usability 
>>> for C++ is secondary. But building "more on it" is not going to work 
>>> in my opinion. It will require a redesign of pretty much everything 
>>> anyway, so all efforts towards C++ will probably just be abandoned 
>>> in the end. The message to the community needs to be clearer than that!
>> Well, I think my message was as clear as you're going to get at this 
>> point in time; I believe I showed a possible path to use jextract + 
>> JVM code snippets to get at complex API points w/o the need of JNI - 
>> that to me seems like building more on what we have e.g. having 
>> jextract generate not just a bunch of annotated interfaces, but 
>> having it also generate some snippets to go with it.
>>
>> After all, we live in a world of limited resources, and we have to 
>> decide how to spend them in order to maximize the benefits that 
>> developers could get out of this feature; as other language FFI show, 
>> there's a pretty big number of use cases that scream for better 
>> integration with native libraries, so we're going with that first. 
>> But all the info that I posted, and all the previous discusson on the 
>> topic should, in my opinion, be sufficient evidence that we're not 
>> just going to stop at C and abandon everything else. If we wanted to 
>> do just that, we'll probably not even bother with layout descriptions 
>> in the first place.
>>>
>>> When I talk about "virtual inheritance", for example, I talk about 
>>> "callbacks". So this isn't an issue related to only C++. For the 
>>> sake of the argument, how are function pointers that call back into 
>>> a Java method implemented with jextract? My impression is that they 
>>> use JNI. If they do not, I would be curious to know how this is 
>>> achieved!
>> I'm not an expert of this part of the code (yet), but my 
>> understanding is that there's no JNI involved; when a native library 
>> is called with a function pointer a so called UpcallHandler [1] is 
>> created - this is a thin wrapper around a method handle (the 
>> functional interface method to be called), a unique ID and an 
>> UpcallStub; the stub is created from Hotspot code [2] and is 
>> essentially a code snippet that performs an upcall back to the Java 
>> code (e.g. it calls UpcallHandler::invoke with the right ID). Then, 
>> when the argument list is processed ahead of a native call [3], 
>> functional interfaces arguments are turned into pointers to such 
>> stubs, and the invocation can then proceed normally. This allows to 
>> pass e.g. a lambda expression or a method reference where a function 
>> pointer was required by the native function, which is rather neat.
>>
>> Maurizio
>>
>> [1] - 
>> http://hg.openjdk.java.net/panama/dev/file/127cdae0dede/src/java.base/share/classes/jdk/internal/nicl/UpcallHandler.java 
>>
>> [2] - 
>> http://hg.openjdk.java.net/panama/dev/file/127cdae0dede/src/hotspot/cpu/x86/nativeInvoker_x86.cpp#l273 
>>
>> [3] - 
>> http://hg.openjdk.java.net/panama/dev/file/127cdae0dede/src/java.base/share/classes/jdk/internal/nicl/NativeInvoker.java#l357 
>>
>>
>>>
>>> Samuel
>>>
>>> On 01/30/2018 06:33 PM, Maurizio Cimadamore wrote:
>>>> Hi Samuel,
>>>> I'm not aware of any concrete C++ effort right now; as I mentioned 
>>>> to you the goal for now is to get native interop (C) up and running 
>>>> with a stable API - once that's done we can build more on it (and 
>>>> that means getting to C++).
>>>>
>>>> Regarding your question of whether generating stubs is really going 
>>>> to buy us much compared to just use JNI as JavaCPP is doing, I take 
>>>> your point; if you generate an _opaque_ stub and then compile-it 
>>>> with the target compiler, you end up in the same performance 
>>>> ballpark as JavaCPP, I believe, as the invocation cannot be direct 
>>>> and the JIT can't probably see through the stub call.
>>>>
>>>> But I've seen other plans on how to generate those stubs, and such 
>>>> plans include using JVM code snippets (for which there's a branch 
>>>> in the panama repo):
>>>>
>>>> http://mail.openjdk.java.net/pipermail/panama-dev/2016-August/000506.html 
>>>>
>>>>
>>>> A machine code snippet is a piece of assembly (hence platform 
>>>> dependent code) which can be packaged up and exposed to user as a 
>>>> method handle. This means that the JIT can optimize it more or less 
>>>> in the same way as it does for other method handles - meaning that 
>>>> it will now be able to see through the stub call and optimize that, 
>>>> if possible/needed. There are obviously a lot of 'ifs' in this 
>>>> story (the code snippet extension is experimental), but I think it 
>>>> should be clear that, at least on paper, it has the potential to be 
>>>> more efficient than simply generating some C/C++ stub, compiling 
>>>> it, and then calling it opaquely.
>>>>
>>>> You can find some examples of code snippets in this test:
>>>>
>>>> http://hg.openjdk.java.net/panama/dev/file/8437963c6282/test/jdk/panama/snippets/MachineCodeSnippetSamples.java#l51 
>>>>
>>>>
>>>> Maurizio
>>>>
>>>>
>>>> On 30/01/18 08:45, Samuel Audet wrote:
>>>>> On 01/30/2018 02:14 PM, Henry Jen wrote:
>>>>>>
>>>>>>> On Jan 29, 2018, at 8:37 PM, Samuel Audet 
>>>>>>> <samuel.audet at gmail.com> wrote:
>>>>>>>
>>>>>>> BTW, if the C API of libclang exposes all the features we need, 
>>>>>>> it is already possible to use it from Java: 
>>>>>>> https://github.com/bytedeco/javacpp-presets/tree/master/llvm Is 
>>>>>>> jextract in a good enough shape to offer us such an interface to 
>>>>>>> work with and do some dogfooding? If so, it might also be a good 
>>>>>>> place to start a testbed for jextract too. That is exactly what 
>>>>>>> the JavaCPP Presets are: A testbed for JavaCPP. This is what 
>>>>>>> makes JavaCPP actually work with (a few) C++ libraries out there 
>>>>>>> in the wild--unlike SWIG, CppSharp, rust-bindgen, etc. Thoughts?
>>>>>>>
>>>>>>
>>>>>> We have achieved to run jextract on top of libclang binding 
>>>>>> generated by jextract awhile back, probably need to bring 
>>>>>> up-to-date with current updates.
>>>>>>
>>>>>> It’s the idea that after this bootstrapping process, we would 
>>>>>> like to be able open up other capability provided by libclang, 
>>>>>> also this dogfooding would server as a validation to our approach 
>>>>>> is working.
>>>>>>
>>>>>
>>>>> Ok, cool! Has anyone tried with the C++ API of Clang since then? 
>>>>> Now that sounds like awesome dogfooding to me. And if we can get 
>>>>> that wrapped, we're probably not going to have much of any issues 
>>>>> with other C++ libraries out there, and I will happily retire 
>>>>> JavaCPP. :)
>>>>>
>>>>> Samuel
>>>>
>>>
>>
>



More information about the panama-dev mailing list