Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ext/ffi): Safe number pointers #15173

Merged
merged 14 commits into from
Jul 24, 2022

Conversation

aapoalas
Copy link
Collaborator

@aapoalas aapoalas commented Jul 12, 2022

This PR changes the JS representation of pointers returned by the FFI API to use plain JS numbers on 64 bit systems when the pointer value can be safely represented as a JS number. (Note: There would be another option as well, which is to always turn pointers into f64 as they are, bitwise, and save that into a JS Number. Whether or not that actually works depends entirely on if V8 does any kind of changes on the f64 it's given, eg. unifying any NaN values to be the same NaN.)

@aapoalas aapoalas force-pushed the feat-ext-ffi-32-bit-support branch from 58b055c to c59a522 Compare July 22, 2022 18:30
Copy link
Member

@littledivy littledivy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add typescript tests in test_ffi/tests/ffi_types.ts

@aapoalas
Copy link
Collaborator Author

Please add typescript tests in test_ffi/tests/ffi_types.ts

Turns out these are quite well handled by the existing type tests. The tests had just turned off with deno check no longer type checking by default.

NativeType::I64 => "int64_t",
NativeType::ISize => "intptr_t",
NativeType::USize => "uintptr_t",
NativeType::Pointer | NativeType::Function => "void*",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C does not mandate that function pointers and data pointers are the same.
A quick search yielded this: https://stackoverflow.com/questions/1473935/can-the-size-of-pointers-vary-between-data-and-function-pointers.

See the documents that they reference: https://c-faq.com/ptrs/generic.html; you should use void(*)(), but because of C's irregular syntax regarding some types (such as functions), you should emit a type alias near the top of the file (typedef void (*function_pointer_t)()), and then use that here (Function => "function_pointer_t").

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opened a new issue for this: #15292

It seems that the main case where this is true is Harvard architecture, which is not supported by Deno either. These seem to usually be lower-bitness environments, eg. 16 bit data pointers, which would mean that compiling V8 for those might not be possible in the first place. Compiling Rust might not work either.

Copy link

@ghost ghost Jul 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opened a new issue for this: #15292

It seems that the main case where this is true is Harvard architecture, which is not supported by Deno either.

These seem to usually be lower-bitness environments, eg. 16 bit data pointers, which would mean that compiling V8 for those might not be possible in the first place.

Indeed, this is the usual case, that sizeof::<fn()>() >= size_of::<usize>().

Compiling Rust might not work either.

I believe Rust could still work on such platforms, as it requests passing fn() as FFI functions.
https://doc.rust-lang.org/std/primitive.fn.html
And Rust acknowledges that function pointers may not be pointer-sized.
https://rust-lang.github.io/unsafe-code-guidelines/layout/function-pointers.html

But if we have confirmation that V8 can't support such platforms, then it is perfectly understandable to disregard this situation as not relevant.
(I'm not sure if V8's JiT compiler would work on such platforms, as Harvard platforms are more complicated to do so on.)

Although, another case may be CHERI and such...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps a const assert assert!(sizeof::<fn()>() == size_of::<usize>()) is fine.

Copy link
Member

@littledivy littledivy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@aapoalas aapoalas changed the title feat(ext/ffi): Support 32 bit pointers, variable JS-side pointer representation feat(ext/ffi): Safe number pointers Jul 24, 2022
@littledivy littledivy merged commit f8fee6c into denoland:main Jul 24, 2022
Officialstrike pushed a commit to Officialstrike/deno that referenced this pull request Jul 30, 2022
crowlKats pushed a commit that referenced this pull request Aug 4, 2022
@aapoalas aapoalas deleted the feat-ext-ffi-32-bit-support branch August 23, 2022 19:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants