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.

Reply via email to