Hey, Thank you for getting back to me!
I'm definitely interested in implementing Externals for C callbacks both as parameters and as returns values. Returning void pointers should prove to be more difficult I guess. I can see two ways to go about it: 1. Take the same route as you mention for returning TypedArrays, where V8 will allocate a placeholder before calling the callback. 2. Simply have the C callback return the pointer and have V8 do the allocation after calling it. I presume this should be doable since the return value CType can (or perhaps "should") be trusted to speak the truth, and returning a pointer does not cause any issues calling convention wise. My personal preference is definitely on #2, as it feels more "natural" and contains less indirection. It also has the slight benefit of not doing any unnecessary allocations for the External when the fast callback signals a need to deopt using the fallback flag. I wonder if #2 could be used to likewise implement TypedArray returning? I can't exactly remember the System V ABI for C++ structures but I seem to recall that a structure with a size of up two two pointers worth can be returned through RAX and an extra register (that is, as long as the class does not have an non-trivial copy constructors or destructor). Other ABIs might of course differ on that. Still, if it happened to be so that all ABIs allowed returning two pointers, it would mean that a C callback could return the same TypedArray struct that is used to pass them in as parameters. (I'm skipping considerations of ownership, lifetime, copying, memory management and all that because it gets hard and ruins my idea pretty well :D ) On Strings: It turns out that as long as one keeps a pointer to the Isolate somewhere, it's already possible to support String parameters in fast calls, at least to a limited and possibly unstable degree. See this PR of mine: https://github.com/denoland/deno/pull/16014 Essentially, if a parameter is declared as v8::Value then it will happily accept a String as well, and with the Isolate pointer it is then possible to write the string data out. I'm unsure of the safety of this, I expect it should panic on roped strings as V8 flattens them but so far I've not seen clear evidence of that happening. I personally think that a limited C string return only -kind of string support would not be a good idea. As an example, I expect that the Chrome / Blink team would find good use for returning of UTF8 strings in atob / btoa and TextDecoder APIs. (And so would Deno.) Again here I ponder on the possibility of the option #2 above. About Deno's interest in Fast API in general: I'm not part of the Deno team, and am only contributing to the FFI and a little bit on the core ops (JS <-> Rust binding) layer so I cannot truly speak for what the team considers important and am just speaking for myself. That being said: 1. Deno's FFI API relies heavily on Fast API. Every foreign library's symbol (C function) that a user wants to use will by default use the Fast API. Only symbols that call back into V8 need to / should opt out of this using a "callback" boolean option. Adding more supported types to Fast API directly adds to wider and better support for Deno FFI. As an example, currently returning of 64 bit integers (eg. pointers) is done via a TypedArray out pointer, where the pointer is written into. If returning of External objects was possible, this out pointer system and its (slight) performance overhead could be removed. (And most importantly, numbers-as-pointers insecurity could be eliminated.) Returning of C strings would allow Deno FFI to have "native" support of those (currently C string extraction is done via a separate method). 2. Deno's ops layer has recently moved to using Fast API by default where possible. Deno's binding functions are written as normal Rust functions and an ops macro takes care of writing the binding logic to V8's FunctionTemplate. Due to the near-universality of the ops macro, any Fast API binding logic needs to only be written once and the macro will take care of taking setting up the bindings for all ops that are bindable. Thus, here even more than with FFI, having more supported types leads near-automatically to faster binding layer in Deno, which is very much of interest to the Deno team. Some examples: * FFI might not benefit from Strings as parameters that much, since foreign APIs would only expect C strings. Deno ops however very much would like to get arbitrary (UTF8) strings in fast calls. They would also love to return arbitrary UTF8 strings. * FFI only cares about returning pointers in some form, External being the most logical. Deno ops would very much want to return TypedArrays of varying sizes, and they would not mind being explicit about memory management either. * ops have cases where eg. a String or TypedArray parameter might be optional. Overloads are already supported to a degree, but eg. null parameters in the middle currently are not supported directly (except as v8::Values which I'm not sure if it would ruin the "better typed" overload matching) * (Completely impossible stretch goal): Some ops take objects of some given shape. If V8 were to match its JS object shapes to a declared parameter struct shape, now that would be impossibly cool. Also, probably too hard to feasibly do but a man can dream. This has become a massive, meandering writeup. Sorry about that. Back onto topic: If you can give me some pointers on where I should look to add the External<JSExternalObject> stuff for, I would much appreciate it. I would personally also prefer to write the code such that the C callback receives not the v8::External object but is directly called with the pointer that the External represents. This I expect to require some changes in the lowering code. Thank you for your time -Aapo Alasuutari On Friday, 30 September 2022 at 11:23:56 UTC+3 [email protected] wrote: > Hi, > > First of all I'm really sorry for the late reply, I didn't see Leszek's > ping in time. > > External sounds like the right type to represent embedder pointers, though > the poor performance you report sounds unfortunate. Tbh I'm not aware of > particular efforts to optimize it, but it might be indeed due to the > ExternalMap. I'll check with colleagues if it's possible to do something > about the performance there. > > On the main topic, adding C callbacks that accept an argument of type > External<JSExternalObject > <https://source.chromium.org/chromium/chromium/src/+/main:v8/src/objects/js-objects.h;drc=ca79bd5301566d1a3fc573c6e6858b5880c00fbd;bpv=1;bpt=1;l=911?gsn=JSExternalObject&gs=kythe%3A%2F%2Fchromium.googlesource.com%2Fchromium%2Fsrc%3Flang%3Dc%252B%252B%3Fpath%3Dv8%2Fsrc%2Fobjects%2Fjs-objects.h%23JSExternalObject%253Ainternal%253Av8%2523c%2523iz6AV1GPx3E&gs=kythe%3A%2F%2Fchromium.googlesource.com%2Fchromium%2Fsrc%3Flang%3Dc%252B%252B%3Fpath%3Dv8%2Fsrc%2Fobjects%2Fjs-objects.h%23JSExternalObject%253Ainternal%253Av8%2523c%2523bNyn58S6iE1&gs=kythe%3A%2F%2Fchromium.googlesource.com%2Fchromium%2Fsrc%3Flang%3Dc%252B%252B%3Fpath%3Dv8%2Fsrc%2Fobjects%2Fjs-objects.h%23E1nu-FvBjuQ-EDx8Ny1DO3ZL7UJtt6bOOeiU34UFYGw&gs=kythe%3A%2F%2Fchromium.googlesource.com%2Fchromium%2Fsrc%3Flang%3Dc%252B%252B%3Fpath%3Dout%2Fandroid-Debug%2Fgen%2Fv8%2Ftorque-generated%2Fclass-forward-declarations.h%23oOxlJQnIiQ9TdjrwzIe-NzNBbjuKOvOptxzBUUoilOc&gs=kythe%3A%2F%2Fchromium.googlesource.com%2Fchromium%2Fsrc%3Flang%3Dc%252B%252B%3Fpath%3Dout%2Fandroid-Debug%2Fgen%2Fv8%2Ftorque-generated%2Fsrc%2Fobjects%2Fjs-objects-tq.inc%23L9uwfd2l6uOWvbRRILcxKp1VYllIsCCFPIecleuaEFI&gs=kythe%3A%2F%2Fchromium.googlesource.com%2Fchromium%2Fsrc%3Flang%3Dc%252B%252B%3Fpath%3Dv8%2Fsrc%2Fheap%2Fobjects-visiting.h%23TyseKlOYyb_hrIxmiwvcWeGQvP1INehKCer2kV7xG6o&gs=kythe%3A%2F%2Fchromium.googlesource.com%2Fchromium%2Fsrc%3Flang%3Dc%252B%252B%3Fpath%3Dout%2Fchromeos-Debug%2Fgen%2Fv8%2Ftorque-generated%2Fclass-forward-declarations.h%23-xwKU2vBSmUrnUm0jR5GI1mRjxJU6CM4EWCILgXHArg&gs=kythe%3A%2F%2Fchromium.googlesource.com%2Fchromium%2Fsrc%3Flang%3Dc%252B%252B%3Fpath%3Dout%2Fchromeos-Debug%2Fgen%2Fv8%2Ftorque-generated%2Fsrc%2Fobjects%2Fjs-objects-tq.inc%233_drfRrSdKh0O1Osknb0zTSBaGNV_S6BOBULYV3JPWM&gs=kythe%3A%2F%2Fchromium.googlesource.com%2Fchromium%2Fsrc%3Flang%3Dc%252B%252B%3Fpath%3Dout%2Ffuchsia-Debug%2Fgen%2Fv8%2Ftorque-generated%2Fclass-forward-declarations.h%234v0WVozoJqd2EihNGkWvPiA8BoPsJcdwXuoyVp6QHOQ&gs=kythe%3A%2F%2Fchromium.googlesource.com%2Fchromium%2Fsrc%3Flang%3Dc%252B%252B%3Fpath%3Dout%2Ffuchsia-Debug%2Fgen%2Fv8%2Ftorque-generated%2Fsrc%2Fobjects%2Fjs-objects-tq.inc%23LSy3_Kz2Yjawt37W-b83WmwOsNDUY4ajMD0DAb7V3Mc&gs=kythe%3A%2F%2Fchromium.googlesource.com%2Fchromium%2Fsrc%3Flang%3Dc%252B%252B%3Fpath%3Dout%2FDebug%2Fgen%2Fv8%2Ftorque-generated%2Fclass-forward-declarations.h%23mTH4BKG-IJiVtR9UIw5dWrwbrfkz9qT70rqpwU4XjrU&gs=kythe%3A%2F%2Fchromium.googlesource.com%2Fchromium%2Fsrc%3Flang%3Dc%252B%252B%3Fpath%3Dout%2FDebug%2Fgen%2Fv8%2Ftorque-generated%2Fsrc%2Fobjects%2Fjs-objects-tq.inc%23whuyQbV2vlE-tTFI1uVnQfjP17lKMmgcfoUlNVo-Klw&gs=kythe%3A%2F%2Fchromium.googlesource.com%2Fchromium%2Fsrc%3Flang%3Dc%252B%252B%3Fpath%3Dout%2Fmac-Debug%2Fgen%2Fv8%2Ftorque-generated%2Fclass-forward-declarations.h%23GzTsTV0SjMocKlp1gFc9rdY5cM8CLb1snxpk-K_Yl6w&gs=kythe%3A%2F%2Fchromium.googlesource.com%2Fchromium%2Fsrc%3Flang%3Dc%252B%252B%3Fpath%3Dout%2Fmac-Debug%2Fgen%2Fv8%2Ftorque-generated%2Fsrc%2Fobjects%2Fjs-objects-tq.inc%23e8ogLQjp7_4HdRE3K0x5oqhCsc1cPbcQrRxJ93YsGgY&gs=kythe%3A%2F%2Fchromium.googlesource.com%2Fchromium%2Fsrc%3Flang%3Dc%252B%252B%3Fpath%3Dout%2Fwebview-Debug%2Fclang_x86_v8_arm%2Fgen%2Fv8%2Ftorque-generated%2Fclass-forward-declarations.h%23eCSrpBoyJxJqKLLRwerXtYRgNRCFPzhqMlFvXB1GgXk&gs=kythe%3A%2F%2Fchromium.googlesource.com%2Fchromium%2Fsrc%3Flang%3Dc%252B%252B%3Fpath%3Dout%2Fwebview-Debug%2Fclang_x86_v8_arm%2Fgen%2Fv8%2Ftorque-generated%2Fsrc%2Fobjects%2Fjs-objects-tq.inc%23zx7jBWmo0iWo0ZDZ_UwWDKwgXrTwOQ0CKrx6zw1BU6c&gs=kythe%3A%2F%2Fchromium.googlesource.com%2Fchromium%2Fsrc%3Flang%3Dc%252B%252B%3Fpath%3Dout%2Fwin-Debug%2Fgen%2Fv8%2Ftorque-generated%2Fclass-forward-declarations.h%23GSrIGaBEY2iOQfmCfE72vSRo9s9ew9qMP3oJBgobGP8&gs=kythe%3A%2F%2Fchromium.googlesource.com%2Fchromium%2Fsrc%3Flang%3Dc%252B%252B%3Fpath%3Dout%2Fwin-Debug%2Fgen%2Fv8%2Ftorque-generated%2Fsrc%2Fobjects%2Fjs-objects-tq.inc%23qHEyn9vHXkb7XJTCTYp5eFzZgB9YbJdsNIcS6VDvHxw>> > > should be doable, given that memory wise External has the same > representation as v8::Value (which we support to pass regular > v8::Object's). It should mostly be an addition to the public interface > file, which I can guide you into implementing, if you're interested. > > Regarding the other two points: > - Strings - we decided for now to leave them out of the API, due to the > large number of string types in V8, which would make the implementation > annoyingly complex. We talked about possibly adding limited support for > return string types only, as the C++ -> JS direction would need support > only for plain C strings. Still, I don't have any particular plan to > implement it in the near future, but would be happy to support you if it's > an important feature for Deno. > - Returning TypedArrays - this is again somewhat cumbersome, as the > TypedArray object would need to be allocated as a placeholder from the > generated code before calling out to the C++ callback, as the callback > itself is not allowed to allocate. It should be generally doable, but we > didn't have a use case until now. > > Hope this helps, will let you know once I learn more about v8::External > performance. > > All the best, > Maya > > On Friday, September 30, 2022 at 7:36:21 AM UTC+2 [email protected] > wrote: > >> Still hoping to get some guidance with this. >> >> I'm also interested in support, even if limited, for string value >> parameters (or even return values) and returning of TypedArray buffers. >> Though, I expect those to be much harder to implement than returning >> External objects for void pointers. I guess a somewhat related option is to >> return external pointers as zero-sized TypedArrays / ArrayBuffers, but that >> sounds quite wrong compared to External objects. >> >> On Friday, 23 September 2022 at 15:15:10 UTC+3 Aapo Alasuutari wrote: >> >>> I presume Maya might now be back be at the office? >>> >>> Would it be possible to get some guidance regarding implementing void >>> pointer support, either here on Groups or possibly by organizing an online >>> meeting of some sort? >>> >>> -Aapo >>> >>> On Tuesday, 23 August 2022 at 11:32:30 UTC+3 [email protected] wrote: >>> >>>> Hi, yes, Maya is out until mid-september. >>>> Cheers, Camillo >>>> >>>> On Tue, 23 Aug 2022 at 07:07, Aapo Alasuutari <[email protected]> >>>> wrote: >>>> >>>>> Has Maya possibly returned from vacation? Or is their leave still >>>>> continuing? >>>>> >>>>> On Friday, 29 July 2022 at 12:08:53 UTC+3 [email protected] wrote: >>>>> >>>>>> Maya is on leave over the summer, unfortunately. >>>>>> >>>>>> On Fri, Jul 29, 2022 at 11:02 AM Leszek Swirski <[email protected]> >>>>>> wrote: >>>>>> >>>>>>> +Maya, you're probably the best person to answer this. >>>>>>> >>>>>>> On Tue, Jul 26, 2022 at 9:05 PM Aapo Alasuutari < >>>>>>> [email protected]> wrote: >>>>>>> >>>>>>>> Hello, >>>>>>>> >>>>>>>> I'm interested in implementing `void*` pointer support for Fast API >>>>>>>> calls. My thinking was that V8's `External` objects are appropriate to >>>>>>>> stand in for external `void*` pointers coming in from external code >>>>>>>> and >>>>>>>> going back out, since that's what they're (presumably) meant for. >>>>>>>> >>>>>>>> Unfortunately this seems to be a complex endeavour, a bit more than >>>>>>>> I can start hacking together directly. I'm also not sure if the >>>>>>>> `Sandboxify >>>>>>>> JSExternalObject external pointer` PR will complicate this plan of >>>>>>>> mine. >>>>>>>> >>>>>>>> The origin of my interest is Deno FFI support, that is calling >>>>>>>> native libraries from Deno JS runtime that uses the V8 engine. Recent >>>>>>>> changes to the FFI have added V8 Fast API support and made the FFI a >>>>>>>> lot >>>>>>>> faster, but unfortunately we're bound to using plain numbers as >>>>>>>> pointers, >>>>>>>> meaning both that creating pointers is as easy as just writing a >>>>>>>> number and >>>>>>>> that (Fast API compatible) pointers are limited to 53 bit numbers >>>>>>>> which >>>>>>>> will not be enough for eg. pointer cryptography on ARM v8.3. >>>>>>>> >>>>>>>> It believe it would be preferable if Deno could use `External` >>>>>>>> objects to stand for pointers but this would negate the current Fast >>>>>>>> API >>>>>>>> performance benefits. Thus, `void*` pointer support for fast calls. >>>>>>>> >>>>>>>> >>>>>>>> Any comments? Suggestions on how I might best proceed with this to >>>>>>>> implement it? Or is this perhaps not a reasonable idea? >>>>>>>> >>>>>>>> Side note: I was sad to find that getting the pointer value out of >>>>>>>> an `Local<External>` is measurably slower than getting the pointer >>>>>>>> number >>>>>>>> value out of a `Local<Number>`. This is presumably due to the >>>>>>>> `External` >>>>>>>> internally saving the pointer in the `ExternalMap`. The slower >>>>>>>> performance >>>>>>>> is still a bit sad, from having expected `External` to be the main >>>>>>>> public >>>>>>>> API meant to handle external pointers. >>>>>>>> >>>>>>>> -- >>>>>>>> -- >>>>>>>> v8-dev mailing list >>>>>>>> [email protected] >>>>>>>> http://groups.google.com/group/v8-dev >>>>>>>> --- >>>>>>>> You received this message because you are subscribed to the Google >>>>>>>> Groups "v8-dev" group. >>>>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>>>> send an email to [email protected]. >>>>>>>> To view this discussion on the web visit >>>>>>>> https://groups.google.com/d/msgid/v8-dev/a4914444-88bf-4238-828c-9ec3f2e09878n%40googlegroups.com >>>>>>>> >>>>>>>> <https://groups.google.com/d/msgid/v8-dev/a4914444-88bf-4238-828c-9ec3f2e09878n%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>>>> . >>>>>>>> >>>>>>> -- >>>>>>> -- >>>>>>> v8-dev mailing list >>>>>>> [email protected] >>>>>>> http://groups.google.com/group/v8-dev >>>>>>> --- >>>>>>> You received this message because you are subscribed to the Google >>>>>>> Groups "v8-dev" group. >>>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>>> send an email to [email protected]. >>>>>>> >>>>>> To view this discussion on the web visit >>>>>>> https://groups.google.com/d/msgid/v8-dev/CAGRskv_o%3DdZTXdYAceSM%2BdaabpJKFYZwEFMjvzS3_8jy3e0TuQ%40mail.gmail.com >>>>>>> >>>>>>> <https://groups.google.com/d/msgid/v8-dev/CAGRskv_o%3DdZTXdYAceSM%2BdaabpJKFYZwEFMjvzS3_8jy3e0TuQ%40mail.gmail.com?utm_medium=email&utm_source=footer> >>>>>>> . >>>>>>> >>>>>> -- >>>>> -- >>>>> v8-dev mailing list >>>>> [email protected] >>>>> http://groups.google.com/group/v8-dev >>>>> --- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "v8-dev" group. >>>>> To unsubscribe from this group and stop receiving emails from it, send >>>>> an email to [email protected]. >>>>> >>>> To view this discussion on the web visit >>>>> https://groups.google.com/d/msgid/v8-dev/17c3b560-e88d-41a7-b64d-d792b4021613n%40googlegroups.com >>>>> >>>>> <https://groups.google.com/d/msgid/v8-dev/17c3b560-e88d-41a7-b64d-d792b4021613n%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>> . >>>>> >>>> Camillo Bruni | Software Engineer, V8 | Google Germany GmbH | >>>> Erika-Mann >>>> Str. 33, 80636 München >>>> >>>> Registergericht und -nummer: Hamburg, HRB 86891 | Sitz der >>>> Gesellschaft: Hamburg | Geschäftsführer: Paul Manicle, Halimah DeLaine >>>> Prado >>>> >>>> Diese E-Mail ist vertraulich. Falls Ssie diese fälschlicherweise >>>> erhalten haben sollten, leiten Sie diese bitte nicht an jemand anderes >>>> weiter, löschen Sie alle Kopien und Anhänge davon und lassen Sie mich >>>> bitte >>>> wissen, dass die E-Mail an die falsche Person gesendet wurde. This >>>> e-mail is confidential. If you received this communication by mistake, >>>> please don't forward it to anyone else, please erase all copies and >>>> attachments, and please let me know that it has gone to the wrong person. >>>> >>> -- -- v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev --- You received this message because you are subscribed to the Google Groups "v8-dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/v8-dev/8cc8803f-9cd1-4597-bdec-836e9022e210n%40googlegroups.com.
