Closed dcharkes closed 4 years ago
(gdb) p def->ToCString()
$17 = 0xf547ba70 "PushArgument(v242) T{*?}"
(gdb) p use->instruction_->ToCString()
$18 = 0xf547bad8 "B38[join try_idx 0]:185 pred(B32, B34, B36, B37) {\n v178 <- phi(v112, v22, v43, v0) alive T{_Smi?}\n}"
~/master/sdk/out/DebugAndroidARM/clang_x86/gen_snapshot --print_environments --causal_async_stacks --deterministic --snapshot_kind=app-aot-elf --elf=/usr/local/google/home/dacoharkes/ffi_samples/vaind/objectbox-dart/example/flutter/objectbox_demo/.dart_tool/flutter_build/3aee09320b7d0ee996d0dc6e2e240f25/armeabi-v7a/app.so --strip --no-sim-use-hardfp --no-use-integer-division --print-flow-graph --disassemble --compiler-passes=* /usr/local/google/home/dacoharkes/ffi_samples/vaind/objectbox-dart/example/flutter/objectbox_demo/.dart_tool/flutter_build/3aee09320b7d0ee996d0dc6e2e240f25/app.dill &> flowgraph; tail -n 10000 flowgraph &> flowgraph-short
Flow graph after applying ICData:
...
v75 <- LoadField(v115 . _cBox@494374530) T{Pointer?}
PushArgument(v71)
v127 <- CheckNull:176(v71, NoSuchMethodError) T{*} env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, v71, a3, v71 }
v77 <- StaticCall:178( get:ptr<0> v71, result_type = T{Pointer?}) T{Pointer?} env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, v0, a3 }
PushArgument(v127 T{*})
CheckNull:180(v127 T{*}, NoSuchMethodError) T{*} env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, v71, a4, v71 }
v79 <- StaticCall:182( get:length<0> v127 T{*}, result_type = T{int?}) T{int?} env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, v0, a4 }
// bunch of checks
Branch if StrictCompare:26(===, v25, v25) goto (32, 33) env={ v115, v49, v0, v49, v0, v25, v25 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
B32[target try_idx 0]:30 env={ v115, v49, v0, v49, v0 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
goto:14 B38 env={ v115, v49, v0, v49, v0, v112 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
B33[target try_idx 0]:32 env={ v115, v49, v0, v49, v0 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
Branch if StrictCompare:36(===, v216, v25) goto (34, 35) env={ v115, v49, v0, v49, v0, v216, v25 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
B34[target try_idx 0]:40 env={ v115, v49, v0, v49, v0 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
goto:18 B38 env={ v115, v49, v0, v49, v0, v22 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
B35[target try_idx 0]:42 env={ v115, v49, v0, v49, v0 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
Branch if StrictCompare:46(===, v216, v25) goto (36, 37) env={ v115, v49, v0, v49, v0, v216, v25 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
B36[target try_idx 0]:50 env={ v115, v49, v0, v49, v0 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
goto:22 B38 env={ v115, v49, v0, v49, v0, v43 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
B37[target try_idx 0]:52 env={ v115, v49, v0, v49, v0 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
goto:56 B38 env={ v115, v49, v0, v49, v0, v0 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
// end of bunch of checks
B38[join try_idx 0]:185 pred(B32, B34, B36, B37) { // USE. (as one of: a0, a1, a2, a3, a4)
v178 <- phi(v112, v22, v43, v0) alive T{_Smi?}
} env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4, v1, v1, v178 }
PushArgument(v148)
v242 <- StaticCall:222( get:obx_box_put<0> v148) T{(Pointer<Void>, int, Pointer<Uint8>, int, int) => int?} env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0 }
PushArgument(v242) T{*?} // DEF.
PushArgument(v75) T{*?}
PushArgument(v64) T{*?}
PushArgument(v77) T{*?}
PushArgument(v79) T{*?}
PushArgument(v178 T{_Smi?}) T{*?}
v83 <- InstanceCall:224( call<0>, v242, v75, v64, v77, v79, v178 T{_Smi?} IC[0: ]) T{*?} env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4, a5 }
PushArgument(v83 T{*?})
...
The use is before the def in the flow graph?
Before applying ICData:
...
PushArgument(v148)
v75 <- LoadField(v115 . _cBox@494374530) T{Pointer?}
PushArgument(v75)
PushArgument(v64)
PushArgument(v71)
v127 <- CheckNull:176(v71, NoSuchMethodError) T{*} env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, v71, a3, v71 }
v77 <- StaticCall:178( get:ptr<0> v71, result_type = T{Pointer?}) T{Pointer?} env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, v0, a3 }
PushArgument(v77)
PushArgument(v127 T{*})
CheckNull:180(v127 T{*}, NoSuchMethodError) T{*} env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, v71, a4, v71 }
v79 <- StaticCall:182( get:length<0> v127 T{*}, result_type = T{int?}) T{int?} env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, v0, a4 }
PushArgument(v79)
// bunch of checks
Branch if StrictCompare:26(===, v25, v25) goto (32, 33) env={ v115, v49, v0, v49, v0, v25, v25 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
B32[target try_idx 0]:30 env={ v115, v49, v0, v49, v0 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
goto:14 B38 env={ v115, v49, v0, v49, v0, v112 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
B33[target try_idx 0]:32 env={ v115, v49, v0, v49, v0 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
Branch if StrictCompare:36(===, v216, v25) goto (34, 35) env={ v115, v49, v0, v49, v0, v216, v25 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
B34[target try_idx 0]:40 env={ v115, v49, v0, v49, v0 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
goto:18 B38 env={ v115, v49, v0, v49, v0, v22 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
B35[target try_idx 0]:42 env={ v115, v49, v0, v49, v0 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
Branch if StrictCompare:46(===, v216, v25) goto (36, 37) env={ v115, v49, v0, v49, v0, v216, v25 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
B36[target try_idx 0]:50 env={ v115, v49, v0, v49, v0 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
goto:22 B38 env={ v115, v49, v0, v49, v0, v43 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
B37[target try_idx 0]:52 env={ v115, v49, v0, v49, v0 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
goto:56 B38 env={ v115, v49, v0, v49, v0, v0 } env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4 }
// end bunch of checks
B38[join try_idx 0]:185 pred(B32, B34, B36, B37) {
v178 <- phi(v112, v22, v43, v0) alive T{_Smi?}
} env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4, v1, v1, v178 }
PushArgument(v178 T{_Smi?})
v83 <- InstanceCall:186( obx_box_put<0>, v148, v75, v64, v77, v79, v178 T{_Smi?} IC[0: ]) T{*?} env={ v36, v38, v49, v16, v0, v0, v0, v0, v50, v0, v52, v64, v68, v71, a0, a1, a2, a3, a4, a5 }
PushArgument(v83)
...
repro:
$ ~/master/sdk/out/DebugAndroidARM/clang_x86/gen_snapshot --print_environments --causal_async_stacks --deterministic --snapshot_kind=app-aot-elf --elf=/usr/local/google/home/dacoharkes/ffi_samples/vaind/objectbox-dart/example/flutter/objectbox_demo/.dart_tool/flutter_build/3aee09320b7d0ee996d0dc6e2e240f25/armeabi-v7a/app.so --strip --no-sim-use-hardfp --no-use-integer-division --print-flow-graph --disassemble --compiler-passes=* /usr/local/google/home/dacoharkes/ffi_samples/vaind/objectbox-dart/example/flutter/objectbox_demo/.dart_tool/flutter_build/3aee09320b7d0ee996d0dc6e2e240f25/app.dill &> flowgraph; tail -n 10000 flowgraph &> flowgraph-short
The method call gets turned into a getter and function call, with an new intermediate result.
cc @mkustermann
Working around the flow graph checker triggers:
../../runtime/vm/compiler/backend/il.h: 8122: error: expected: to != kUntagged || (from == kUnboxedIntPtr || from == kUnboxedFfiIntPtr)
#0 0xf7fd4069 in __kernel_vsyscall ()
#1 0xf7df8c82 in raise () from /lib/i386-linux-gnu/libc.so.6
#2 0xf7de2b3d in abort () from /lib/i386-linux-gnu/libc.so.6
#3 0x00843dc8 in dart::Assert::Fail (this=0xffffbe30, format=0x65d173 "expected: %s") at ../../runtime/platform/assert.cc:44
#4 0x00bbe803 in dart::IntConverterInstr::IntConverterInstr (this=0xf5464a68, from=dart::kUnboxedInt64, to=dart::kUntagged, value=0xf5464ab8, deopt_id=-1) at ../../runtime/vm/compiler/backend/il.h:799
#5 0x00be5351 in dart::IntConverterInstr::Canonicalize (this=0xf5470e60, flow_graph=0xf54e3e90) at ../../runtime/vm/compiler/backend/il.cc:3190
#6 0x00bc007d in dart::FlowGraph::Canonicalize (this=0xf54e3e90) at ../../runtime/vm/compiler/backend/flow_graph.cc:2198
#7 0x00ca59f8 in dart::CompilerPass_Canonicalize::DoBody (this=0xfda83c <dart::compiler_pass_Canonicalize>, state=0xffffc078) at ../../runtime/vm/compiler/compiler_pass.cc:400
#8 0x00ca4f87 in dart::CompilerPass::Run (this=0xfda83c <dart::compiler_pass_Canonicalize>, state=0xffffc078) at ../../runtime/vm/compiler/compiler_pass.cc:189
#9 0x00ca4ee4 in dart::CompilerPass::Run (this=0xfda890 <dart::compiler_pass_CSE>, state=0xffffc078) at ../../runtime/vm/compiler/compiler_pass.cc:183
#10 0x00ca5536 in dart::CompilerPass::RunPipeline (mode=dart::CompilerPass::kAOT, pass_state=0xffffc078) at ../../runtime/vm/compiler/compiler_pass.cc:320
#11 0x00b66f4c in dart::PrecompileParsedFunctionHelper::Compile (this=0xffffc3d8, pipeline=0xffffc550) at ../../runtime/vm/compiler/aot/precompiler.cc:2397
#12 0x00b69381 in dart::PrecompileFunctionHelper (precompiler=<optimized out>, pipeline=<optimized out>, function=..., optimized=<optimized out>) at ../../runtime/vm/compiler/aot/precompiler.cc:2560
#13 0x00b640ed in dart::Precompiler::CompileFunction (precompiler=0xffffc7f8, thread=0xfede60, zone=<optimized out>, function=...) at ../../runtime/vm/compiler/aot/precompiler.cc:2612
#14 0x00b62a46 in dart::Precompiler::ProcessFunction (this=0xffffc7f8, function=...) at ../../runtime/vm/compiler/aot/precompiler.cc:628
#15 0x00b5e842 in dart::Precompiler::Iterate (this=0xffffc7f8) at ../../runtime/vm/compiler/aot/precompiler.cc:541
#16 0x00b5b968 in dart::Precompiler::DoCompileAll (this=0xffffc7f8) at ../../runtime/vm/compiler/aot/precompiler.cc:362
#17 0x00b5b263 in dart::Precompiler::CompileAll () at ../../runtime/vm/compiler/aot/precompiler.cc:144
#18 0x00fc52ec in Dart_Precompile () at ../../runtime/vm/dart_api_impl.cc:6109
#19 0x0081901b in dart::bin::CreateAndWritePrecompiledSnapshot () at ../../runtime/bin/gen_snapshot.cc:625
#20 dart::bin::CreateIsolateAndSnapshot (inputs=...) at ../../runtime/bin/gen_snapshot.cc:831
#21 dart::bin::main (argc=9, argv=0xffffcbd4) at ../../runtime/bin/gen_snapshot.cc:943
#22 0x00819f24 in main (argc=9, argv=0xffffcbd4) at ../../runtime/bin/gen_snapshot.cc:961
IL before the assert:
...
v330 <- BoxInt64((v73, v74) T{int})
v288 <- UnboxUint32([tr], v330 T{int}) T{int} // Throws away v73 basically.
v290 <- BoxUint32(v288) T{int}
...
v255 <- UnboxUint32([tr], v290) T{int} // Truncates again, but does nothing.
v340 <- IntConverter(uint32->int32, v255 T{int}) // Hm, okay.
v268 <- IntConverter(int32->untagged[tr], v340 T{int}) T{int} // Truncate does nothing.
...
It seems to coalesce two intconverter instructions
0xf5464b20 "v358 <- IntConverter(int64->int32, (v73, v74) T{int}) T{int}"
0xf5464bb0 "v268 <- IntConverter(int32->untagged[tr], v358 T{int}) T{int}"
v358
does not have truncation anymore?
The asserts in IntConverterInstr
constructor do not accept the int64 -> untagged
conversion:
IntConverterInstr(Representation from,
Representation to,
Value* value,
intptr_t deopt_id)
: TemplateDefinition(deopt_id),
from_representation_(from),
to_representation_(to),
is_truncating_(to == kUnboxedUint32) {
ASSERT(from != to);
ASSERT(from == kUnboxedInt64 || from == kUnboxedUint32 ||
from == kUnboxedInt32 || from == kUntagged);
ASSERT(to == kUnboxedInt64 || to == kUnboxedUint32 || to == kUnboxedInt32 ||
to == kUntagged);
ASSERT(from != kUntagged ||
(to == kUnboxedIntPtr || to == kUnboxedFfiIntPtr));
ASSERT(to != kUntagged ||
(from == kUnboxedIntPtr || from == kUnboxedFfiIntPtr));
SetInputAt(0, value);
}
Either the asserts should be relaxed (and implemented in ::EmitCode
) or the IntConverterInstr
s should not me coalesced.
Also, truncation should not get lost.
Creating Dart SDK issue to track https://github.com/flutter/flutter/issues/47454 (see for repro).
Most likely caused by use of FFI (reported as FFI issue), and crashes in IntConverterInstr which is used in FFI IL code.
Reproduces with
gen_snapshot
from Dart SDK with the dill file from the original repro:Asserts in debug: