mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:09:49 +00:00
[vm/compiler] Fix materialization of Float32List
Before value is stored into Float32List, it is converted to 32-bit float using DoubleToFloat instruction. If allocation sinking eliminated the allocation of Float32List but we need to deoptimize, the list is materialized and elements are filled. In such case, we shouldn't perform double->float conversion as it already happened. This change also updates the assertion in DoubleToFloatInstr::Canonicalize which verifies that DoubleToFloat instruction can be used only in certain cases. TEST=tests/language/vm/allocation_sinking_arrays_test.dart Fixes https://github.com/dart-lang/sdk/issues/45547 Change-Id: I9a1bd28a9fc09bccad6aa3c91a7880abd002f7c9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193831 Reviewed-by: Ryan Macnak <rmacnak@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
parent
628193450a
commit
38d05280e5
|
@ -2232,14 +2232,18 @@ static Definition* CanonicalizeCommutativeDoubleArithmetic(Token::Kind op,
|
|||
|
||||
Definition* DoubleToFloatInstr::Canonicalize(FlowGraph* flow_graph) {
|
||||
#ifdef DEBUG
|
||||
// Must only be used in Float32 StoreIndexedInstr or FloatToDoubleInstr or
|
||||
// Phis introduce by load forwarding.
|
||||
// Must only be used in Float32 StoreIndexedInstr, FloatToDoubleInstr,
|
||||
// Phis introduce by load forwarding, or MaterializeObject for
|
||||
// eliminated Float32 array.
|
||||
ASSERT(env_use_list() == NULL);
|
||||
for (Value* use = input_use_list(); use != NULL; use = use->next_use()) {
|
||||
ASSERT(use->instruction()->IsPhi() ||
|
||||
use->instruction()->IsFloatToDouble() ||
|
||||
(use->instruction()->IsStoreIndexed() &&
|
||||
(use->instruction()->AsStoreIndexed()->class_id() ==
|
||||
kTypedDataFloat32ArrayCid)) ||
|
||||
(use->instruction()->IsMaterializeObject() &&
|
||||
(use->instruction()->AsMaterializeObject()->cls().id() ==
|
||||
kTypedDataFloat32ArrayCid)));
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -394,9 +394,16 @@ void DeferredObject::Fill() {
|
|||
static_cast<uint64_t>(Integer::Cast(value).AsInt64Value()));
|
||||
break;
|
||||
case kTypedDataFloat32ArrayCid:
|
||||
typed_data.SetFloat32(
|
||||
element_offset,
|
||||
static_cast<float>(Double::Cast(value).value()));
|
||||
// Although element of Float32 array is represented with Double,
|
||||
// it is already converted to 32-bit float via DoubleToFloat
|
||||
// instruction before it was stored.
|
||||
// Reinterpret double value as float to get the value back.
|
||||
union {
|
||||
double d;
|
||||
float f;
|
||||
} v;
|
||||
v.d = Double::Cast(value).value();
|
||||
typed_data.SetFloat32(element_offset, v.f);
|
||||
break;
|
||||
case kTypedDataFloat64ArrayCid:
|
||||
typed_data.SetFloat64(element_offset,
|
||||
|
|
|
@ -66,9 +66,13 @@ String foo(double x, num doDeopt) {
|
|||
Vector2 v2 = new Vector2(1.0, 2.0);
|
||||
Vector2 v3 = v2 + Vector2(x, x);
|
||||
double sum = v3.x + v3.y;
|
||||
Float32List v4 = Float32List(2);
|
||||
v4[0] = 11.0;
|
||||
v4[1] = sum + 3;
|
||||
print(v4[0]);
|
||||
// Deoptimization is triggered here to materialize removed allocations.
|
||||
doDeopt + 2;
|
||||
return "v1: [${v1[0]},${v1[1]}], v2: [${v2.x},${v2.y}], v3: [${v3.x},${v3.y}], sum: $sum";
|
||||
return "v1: [${v1[0]},${v1[1]}], v2: [${v2.x},${v2.y}], v3: [${v3.x},${v3.y}], v4: [${v4[0]}, ${v4[1]}], sum: $sum";
|
||||
}
|
||||
|
||||
main() {
|
||||
|
@ -80,6 +84,8 @@ main() {
|
|||
for (int i = 0; i < 130; ++i) {
|
||||
final num doDeopt = (i < 120 ? 1 : 2.0);
|
||||
final result = foo(3.0, doDeopt);
|
||||
Expect.equals("v1: [1,hi], v2: [1.0,2.0], v3: [4.0,5.0], sum: 9.0", result);
|
||||
Expect.equals(
|
||||
"v1: [1,hi], v2: [1.0,2.0], v3: [4.0,5.0], v4: [11.0, 12.0], sum: 9.0",
|
||||
result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,9 +66,13 @@ String foo(double x, num doDeopt) {
|
|||
Vector2 v2 = new Vector2(1.0, 2.0);
|
||||
Vector2 v3 = v2 + Vector2(x, x);
|
||||
double sum = v3.x + v3.y;
|
||||
Float32List v4 = Float32List(2);
|
||||
v4[0] = 11.0;
|
||||
v4[1] = sum + 3;
|
||||
print(v4[0]);
|
||||
// Deoptimization is triggered here to materialize removed allocations.
|
||||
doDeopt + 2;
|
||||
return "v1: [${v1[0]},${v1[1]}], v2: [${v2.x},${v2.y}], v3: [${v3.x},${v3.y}], sum: $sum";
|
||||
return "v1: [${v1[0]},${v1[1]}], v2: [${v2.x},${v2.y}], v3: [${v3.x},${v3.y}], v4: [${v4[0]}, ${v4[1]}], sum: $sum";
|
||||
}
|
||||
|
||||
main() {
|
||||
|
@ -80,6 +84,8 @@ main() {
|
|||
for (int i = 0; i < 130; ++i) {
|
||||
final num doDeopt = (i < 120 ? 1 : 2.0);
|
||||
final result = foo(3.0, doDeopt);
|
||||
Expect.equals("v1: [1,hi], v2: [1.0,2.0], v3: [4.0,5.0], sum: 9.0", result);
|
||||
Expect.equals(
|
||||
"v1: [1,hi], v2: [1.0,2.0], v3: [4.0,5.0], v4: [11.0, 12.0], sum: 9.0",
|
||||
result);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue