Skip to content

Commit b406802

Browse files
dcharkescommit-bot@chromium.org
authored andcommitted
[vm/ffi] Unbox Pointer data field
This regresses Pointer load and store loops because LoadUntagged is never hoisted out of loops. But with support for passing TypedData, in a follow up CL, we cannot assume that only Pointers are passed in the future. It also changes the FfiCallInstr context to hold the Pointer, rather than the address, as call sites can be unoptimized and we cannot handle an untagged address there. Issue: #40767 Issue: #36730 Change-Id: Icc716d79eb9eb2b5aac4f03dbf6c622a6825ffdc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/137793 Reviewed-by: Martin Kustermann <[email protected]>
1 parent 46bc5cd commit b406802

13 files changed

+97
-87
lines changed

runtime/vm/compiler/backend/il.cc

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2620,7 +2620,7 @@ bool LoadFieldInstr::IsImmutableLengthLoad() const {
26202620
case Slot::Kind::kClosure_hash:
26212621
case Slot::Kind::kCapturedVariable:
26222622
case Slot::Kind::kDartField:
2623-
case Slot::Kind::kPointer_c_memory_address:
2623+
case Slot::Kind::kPointer_data:
26242624
case Slot::Kind::kType_arguments:
26252625
case Slot::Kind::kTypeArgumentsIndex:
26262626
return false;
@@ -3025,6 +3025,9 @@ Definition* BoxInt64Instr::Canonicalize(FlowGraph* flow_graph) {
30253025
// Find a more precise box instruction.
30263026
if (auto conv = value()->definition()->AsIntConverter()) {
30273027
Definition* replacement;
3028+
if (conv->from() == kUntagged) {
3029+
return this;
3030+
}
30283031
switch (conv->from()) {
30293032
case kUnboxedInt32:
30303033
replacement = new BoxInt32Instr(conv->value()->CopyWithType());
@@ -3170,6 +3173,14 @@ Definition* IntConverterInstr::Canonicalize(FlowGraph* flow_graph) {
31703173
return this;
31713174
}
31723175

3176+
#if defined(TARGET_ARCH_IS_32_BIT)
3177+
// Do not erase extending conversions from 32-bit untagged to 64-bit values
3178+
// because untagged does not specify whether it is signed or not.
3179+
if ((box_defn->from() == kUntagged) && to() == kUnboxedInt64) {
3180+
return this;
3181+
}
3182+
#endif
3183+
31733184
if (box_defn->from() == to()) {
31743185
return box_defn->value()->definition();
31753186
}

runtime/vm/compiler/backend/range_analysis.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2703,7 +2703,7 @@ void LoadFieldInstr::InferRange(RangeAnalysis* analysis, Range* range) {
27032703
case Slot::Kind::kClosure_function:
27042704
case Slot::Kind::kClosure_function_type_arguments:
27052705
case Slot::Kind::kClosure_instantiator_type_arguments:
2706-
case Slot::Kind::kPointer_c_memory_address:
2706+
case Slot::Kind::kPointer_data:
27072707
case Slot::Kind::kTypedDataBase_data_field:
27082708
case Slot::Kind::kTypedDataView_data:
27092709
case Slot::Kind::kType_arguments:

runtime/vm/compiler/backend/slot.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class ParsedFunction;
7272
V(ArgumentsDescriptor, positional_count, Smi, FINAL) \
7373
V(ArgumentsDescriptor, count, Smi, FINAL) \
7474
V(ArgumentsDescriptor, size, Smi, FINAL) \
75-
V(Pointer, c_memory_address, Dynamic, FINAL) \
75+
V(Pointer, data, Dynamic, FINAL) \
7676
V(Type, arguments, TypeArguments, FINAL)
7777

7878
// Slot is an abstraction that describes an readable (and possibly writeable)

runtime/vm/compiler/frontend/base_flow_graph_builder.cc

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,12 @@ Fragment BaseFlowGraphBuilder::AllocateObject(TokenPosition position,
911911
return Fragment(allocate);
912912
}
913913

914+
Fragment BaseFlowGraphBuilder::Box(Representation from) {
915+
BoxInstr* box = BoxInstr::Create(from, Pop());
916+
Push(box);
917+
return Fragment(box);
918+
}
919+
914920
Fragment BaseFlowGraphBuilder::BuildFfiAsFunctionInternalCall(
915921
const TypeArguments& signatures) {
916922
ASSERT(signatures.IsInstantiated());
@@ -926,16 +932,17 @@ Fragment BaseFlowGraphBuilder::BuildFfiAsFunctionInternalCall(
926932
Function::Handle(Z, Type::Cast(native_type).signature())));
927933

928934
Fragment code;
929-
code += LoadNativeField(Slot::Pointer_c_memory_address());
930-
LocalVariable* address = MakeTemporary();
935+
// Store the pointer in the context, we cannot load the untagged address
936+
// here as these can be unoptimized call sites.
937+
LocalVariable* pointer = MakeTemporary();
931938

932939
auto& context_slots = CompilerState::Current().GetDummyContextSlots(
933940
/*context_id=*/0, /*num_variables=*/1);
934941
code += AllocateContext(context_slots);
935942
LocalVariable* context = MakeTemporary();
936943

937944
code += LoadLocal(context);
938-
code += LoadLocal(address);
945+
code += LoadLocal(pointer);
939946
code += StoreInstanceField(TokenPosition::kNoSource, *context_slots[0]);
940947

941948
code += AllocateClosure(TokenPosition::kNoSource, target);

runtime/vm/compiler/frontend/base_flow_graph_builder.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,9 @@ class BaseFlowGraphBuilder {
205205
intptr_t index_scale,
206206
bool index_unboxed);
207207

208+
// Sign-extends kUnboxedInt32 and zero-extends kUnboxedUint32.
209+
Fragment Box(Representation from);
210+
208211
void Push(Definition* definition);
209212
Definition* Peek(intptr_t depth = 0);
210213
Value* Pop();

runtime/vm/compiler/frontend/kernel_to_il.cc

Lines changed: 47 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,15 +1215,17 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod(
12151215
LocalVariable* arg_pointer = parsed_function_->RawParameterVariable(0);
12161216
LocalVariable* arg_offset = parsed_function_->RawParameterVariable(1);
12171217

1218-
body += LoadLocal(arg_pointer);
1218+
body += LoadLocal(arg_offset);
12191219
body += CheckNullOptimized(TokenPosition::kNoSource,
12201220
String::ZoneHandle(Z, function.name()));
1221-
body += LoadNativeField(Slot::Pointer_c_memory_address());
1222-
body += UnboxTruncate(kUnboxedFfiIntPtr);
1223-
body += ConvertUnboxedToUntagged(kUnboxedFfiIntPtr);
1224-
body += LoadLocal(arg_offset);
1221+
LocalVariable* arg_offset_not_null = MakeTemporary();
1222+
1223+
body += LoadLocal(arg_pointer);
12251224
body += CheckNullOptimized(TokenPosition::kNoSource,
12261225
String::ZoneHandle(Z, function.name()));
1226+
// No GC from here til LoadIndexed.
1227+
body += LoadUntagged(compiler::target::Pointer::data_offset());
1228+
body += LoadLocal(arg_offset_not_null);
12271229
body += UnboxTruncate(kUnboxedFfiIntPtr);
12281230
body += LoadIndexedTypedData(typed_data_cid, /*index_scale=*/1,
12291231
/*index_unboxed=*/true);
@@ -1263,11 +1265,13 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod(
12631265
LocalVariable* pointer = MakeTemporary();
12641266
body += LoadLocal(pointer);
12651267
body += LoadLocal(address);
1266-
body += StoreInstanceField(TokenPosition::kNoSource,
1267-
Slot::Pointer_c_memory_address());
1268+
body += UnboxTruncate(kUnboxedFfiIntPtr);
1269+
body += ConvertUnboxedToUntagged(kUnboxedFfiIntPtr);
1270+
body += StoreUntagged(compiler::target::Pointer::data_offset());
12681271
body += DropTempsPreserveTop(1); // Drop [address] keep [pointer].
12691272
}
12701273
}
1274+
body += DropTempsPreserveTop(1); // Drop [arg_offset].
12711275
} break;
12721276
case MethodRecognizer::kFfiStoreInt8:
12731277
case MethodRecognizer::kFfiStoreInt16:
@@ -1327,21 +1331,27 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod(
13271331
}
13281332

13291333
ASSERT(function.NumParameters() == 3);
1330-
body += LoadLocal(arg_pointer); // Pointer.
1334+
body += LoadLocal(arg_offset);
13311335
body += CheckNullOptimized(TokenPosition::kNoSource,
13321336
String::ZoneHandle(Z, function.name()));
1333-
body += LoadNativeField(Slot::Pointer_c_memory_address());
1334-
body += UnboxTruncate(kUnboxedFfiIntPtr);
1335-
body += ConvertUnboxedToUntagged(kUnboxedFfiIntPtr);
1336-
body += LoadLocal(arg_offset); // Offset.
1337+
LocalVariable* arg_offset_not_null = MakeTemporary();
1338+
body += LoadLocal(arg_value);
13371339
body += CheckNullOptimized(TokenPosition::kNoSource,
13381340
String::ZoneHandle(Z, function.name()));
1339-
body += UnboxTruncate(kUnboxedFfiIntPtr);
1340-
body += LoadLocal(arg_value); // Value.
1341+
LocalVariable* arg_value_not_null = MakeTemporary();
1342+
1343+
body += LoadLocal(arg_pointer); // Pointer.
13411344
body += CheckNullOptimized(TokenPosition::kNoSource,
13421345
String::ZoneHandle(Z, function.name()));
1346+
// No GC from here til StoreIndexed.
1347+
body += LoadUntagged(compiler::target::Pointer::data_offset());
1348+
body += LoadLocal(arg_offset_not_null);
1349+
body += UnboxTruncate(kUnboxedFfiIntPtr);
1350+
body += LoadLocal(arg_value_not_null);
13431351
if (kind == MethodRecognizer::kFfiStorePointer) {
1344-
body += LoadNativeField(Slot::Pointer_c_memory_address());
1352+
// This can only be Pointer, so it is always safe to LoadUntagged.
1353+
body += LoadUntagged(compiler::target::Pointer::data_offset());
1354+
body += ConvertUntaggedToUnboxed(kUnboxedFfiIntPtr);
13451355
} else if (kind == MethodRecognizer::kFfiStoreFloat ||
13461356
kind == MethodRecognizer::kFfiStoreDouble) {
13471357
body += UnboxTruncate(kUnboxedDouble);
@@ -1353,6 +1363,8 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod(
13531363
}
13541364
body += StoreIndexedTypedData(typed_data_cid, /*index_scale=*/1,
13551365
/*index_unboxed=*/true);
1366+
body += Drop(); // Drop [arg_value].
1367+
body += Drop(); // Drop [arg_offset].
13561368
body += NullConstant();
13571369
} break;
13581370
case MethodRecognizer::kFfiFromAddress: {
@@ -1369,21 +1381,19 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod(
13691381
body += LoadLocal(parsed_function_->RawParameterVariable(0)); // Address.
13701382
body += CheckNullOptimized(TokenPosition::kNoSource,
13711383
String::ZoneHandle(Z, function.name()));
1372-
#if defined(TARGET_ARCH_IS_32_BIT)
1373-
// Truncate to 32 bits on 32 bit architecture.
13741384
body += UnboxTruncate(kUnboxedFfiIntPtr);
1375-
body += Box(kUnboxedFfiIntPtr);
1376-
#endif // defined(TARGET_ARCH_IS_32_BIT)
1377-
body += StoreInstanceField(TokenPosition::kNoSource,
1378-
Slot::Pointer_c_memory_address(),
1379-
StoreInstanceFieldInstr::Kind::kInitializing);
1385+
body += ConvertUnboxedToUntagged(kUnboxedFfiIntPtr);
1386+
body += StoreUntagged(compiler::target::Pointer::data_offset());
13801387
} break;
13811388
case MethodRecognizer::kFfiGetAddress: {
13821389
ASSERT(function.NumParameters() == 1);
13831390
body += LoadLocal(parsed_function_->RawParameterVariable(0)); // Pointer.
13841391
body += CheckNullOptimized(TokenPosition::kNoSource,
13851392
String::ZoneHandle(Z, function.name()));
1386-
body += LoadNativeField(Slot::Pointer_c_memory_address());
1393+
// This can only be Pointer, so it is always safe to LoadUntagged.
1394+
body += LoadUntagged(compiler::target::Pointer::data_offset());
1395+
body += ConvertUntaggedToUnboxed(kUnboxedFfiIntPtr);
1396+
body += Box(kUnboxedFfiIntPtr);
13871397
} break;
13881398
default: {
13891399
UNREACHABLE();
@@ -2752,12 +2762,6 @@ Fragment FlowGraphBuilder::UnboxTruncate(Representation to) {
27522762
return Fragment(unbox);
27532763
}
27542764

2755-
Fragment FlowGraphBuilder::Box(Representation from) {
2756-
BoxInstr* box = BoxInstr::Create(from, Pop());
2757-
Push(box);
2758-
return Fragment(box);
2759-
}
2760-
27612765
Fragment FlowGraphBuilder::NativeReturn(
27622766
const compiler::ffi::CallbackMarshaller& marshaller) {
27632767
auto* instr = new (Z) NativeReturnInstr(TokenPosition::kNoSource, Pop(),
@@ -2787,9 +2791,9 @@ Fragment FlowGraphBuilder::FfiPointerFromAddress(const Type& result_type) {
27872791
LocalVariable* pointer = MakeTemporary();
27882792
code += LoadLocal(pointer);
27892793
code += LoadLocal(address);
2790-
code += StoreInstanceField(TokenPosition::kNoSource,
2791-
Slot::Pointer_c_memory_address(),
2792-
StoreInstanceFieldInstr::Kind::kInitializing);
2794+
code += UnboxTruncate(kUnboxedFfiIntPtr);
2795+
code += ConvertUnboxedToUntagged(kUnboxedFfiIntPtr);
2796+
code += StoreUntagged(compiler::target::Pointer::data_offset());
27932797
code += StoreLocal(TokenPosition::kNoSource, result);
27942798
code += Drop(); // StoreLocal^
27952799
code += Drop(); // address
@@ -2837,11 +2841,13 @@ Fragment FlowGraphBuilder::FfiConvertArgumentToNative(
28372841
String::ZoneHandle(Z, marshaller.function_name()));
28382842

28392843
if (marshaller.IsPointer(arg_index)) {
2840-
body += LoadNativeField(Slot::Pointer_c_memory_address());
2844+
// This can only be Pointer, so it is always safe to LoadUntagged.
2845+
body += LoadUntagged(compiler::target::Pointer::data_offset());
2846+
body += ConvertUntaggedToUnboxed(kUnboxedFfiIntPtr);
2847+
} else {
2848+
body += UnboxTruncate(marshaller.RepInDart(arg_index));
28412849
}
28422850

2843-
body += UnboxTruncate(marshaller.RepInDart(arg_index));
2844-
28452851
if (marshaller.RequiresBitCast(arg_index)) {
28462852
body += BitCast(marshaller.RepInDart(arg_index),
28472853
marshaller.RepInFfiCall(arg_index));
@@ -2885,15 +2891,18 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFfiNative(const Function& function) {
28852891
body += FfiConvertArgumentToNative(marshaller, i);
28862892
}
28872893

2888-
// Push the function pointer, which is stored (boxed) in the first slot of the
2889-
// context.
2894+
// Push the function pointer, which is stored (as Pointer object) in the
2895+
// first slot of the context.
28902896
body += LoadLocal(parsed_function_->ParameterVariable(0));
28912897
body += LoadNativeField(Slot::Closure_context());
28922898
body += LoadNativeField(Slot::GetContextVariableSlotFor(
28932899
thread_, *MakeImplicitClosureScope(
28942900
Z, Class::Handle(I->object_store()->ffi_pointer_class()))
28952901
->context_variables()[0]));
2896-
body += UnboxTruncate(kUnboxedFfiIntPtr);
2902+
2903+
// This can only be Pointer, so it is always safe to LoadUntagged.
2904+
body += LoadUntagged(compiler::target::Pointer::data_offset());
2905+
body += ConvertUntaggedToUnboxed(kUnboxedFfiIntPtr);
28972906
body += FfiCall(marshaller);
28982907

28992908
body += FfiConvertArgumentToDart(marshaller, compiler::ffi::kResultIndex);

runtime/vm/compiler/frontend/kernel_to_il.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,6 @@ class FlowGraphBuilder : public BaseFlowGraphBuilder {
190190
// target representation.
191191
Fragment UnboxTruncate(Representation to);
192192

193-
// Sign-extends kUnboxedInt32 and zero-extends kUnboxedUint32.
194-
Fragment Box(Representation from);
195-
196193
// Creates an ffi.Pointer holding a given address (TOS).
197194
Fragment FfiPointerFromAddress(const Type& result_type);
198195

runtime/vm/compiler/runtime_api.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ class ArgumentsDescriptor : public AllStatic {
580580

581581
class Pointer : public AllStatic {
582582
public:
583-
static word c_memory_address_offset();
583+
static word data_offset();
584584
static word type_arguments_offset();
585585
static word InstanceSize();
586586
static word NextFieldOffset();

0 commit comments

Comments
 (0)