[vm/ffi] Unbox `Pointer`
Opened this issue · 2 comments
We should explore unboxing Pointer
.
(I don't believe we had a tracking issue yet.)
We've stopped reifying the type argument of Pointer
:
So, essentially the Pointer
is now just an object with an unboxed integer as field.
Replacing it with a Dart int
however does not exactly give the semantics that we want. We don't want to start boxing things in Mints again. So rather, it should be unboxed as an unboxed integer, and as an unboxed integer that has a different representation on 32 bit and 64 bit platforms.
Code such as this is not optimal:
12: v7 <- StaticCall:16( allocate<1> v2, v3, v4) T{*?}
[...]
42: PushArgument(v7 T{Pointer})
44: v54 <- StaticCall:12( get:address<0> v7 T{Pointer}, recognized_kind = FfiGetAddress) [-9223372036854775808, 9223372036854775807] T{int}
46: v140 <- UnboxInt64:14([non-speculative], v10) [1, 9] T{int}
48: v141 <- UnboxInt64:14([non-speculative], v54) [-9223372036854775808, 9223372036854775807] T{int}
50: v55 <- BinaryInt64Op:14(+ [tr], v141 T{int}, v140 T{_Smi}) [-9223372036854775808, 9223372036854775807] T{int}
52: v142 <- BoxInt64(v55 T{int}) [-9223372036854775808, 9223372036854775807] T{int}
54: PushArgument(v53)
56: PushArgument(v142 T{int})
58: v113 <- StaticCall:12( _fromAddress@8050071<1> v53, v142 T{int}, recognized_kind = FfiFromAddress) T{*?}
60: MemoryCopy(v7 T{Pointer}, v113 T{*?}, v16, v16, v139)
- MemoryCopy + Pointer.fromAddress -> MemoryCopy should just take the address.
- BoxInt + Pointer.fromAddress -> We box to unbox again within fromAddress. We would not have to box either if MemoryCopy would take unboxed address directly.
- allocate + get:address -> if Pointer were unboxed we wouldn't have to box in allocate and unbox later.
We should consider using kUntagged
as the representation of FFI pointers instead of kUnboxedFfiIntPtr
, and only convert to/from kUnboxedFffiIntPtr
explicitly when using the value of the address as a integer, now that kUntagged
values are more understood by the flow graph compiler and aren't limited to being generated/killed within a single basic block. That is,
- when performing arithmetic on the address internally (so untagged->uint32/int64, perform arithmetic, uint32/int64->untagged, similar to how
BuildTypedDataViewFactoryConstructor
inkernel_to_il.cc
updates the inner pointer), - when returning the address as a Dart
int
inPointer.address
, and - when receiving a Dart
int
to turn into an address inPointer.fromAddress
.
This way, like in C++, using a pointer as an integer requires explicit conversion and is obvious in the IL.