[vm/compiler] Fix generation of Smi immediates when using compressed pointers

When compiler generates 32-bit instructions with immediate operand
(such as add/sub etc) it expects to find 32-bit immediate value.
In compressed pointers mode Smi occupies 32 bits with unspecified
upper bits. So getting a raw value of a Smi using

  static_cast<int64_t>(constant.ptr())

is not correct. For example it may yield 0xfffffffe instead of
0xfffffffffffffffe for -1 value.

This change fixes a few places in code generator to use Smi::RawValue
instead of doing a static_cast.

TEST=runtime/tests/vm/dart/regress_47704_test.dart
Fixes https://github.com/dart-lang/sdk/issues/47704

Change-Id: I1f649c5a22f221c7f4e69a884c88c265973be606
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/220660
Auto-Submit: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Alexander Markov 2021-11-18 17:12:18 +00:00 committed by commit-bot@chromium.org
parent 8dcc1dcf5e
commit 071d50f679
4 changed files with 78 additions and 5 deletions

View file

@ -0,0 +1,35 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Regression test for https://github.com/dart-lang/sdk/issues/47704.
// Verifies that compiler doesn't crash with compressed pointers when
// generating code involving as 32-bit Smi constant which is not
// sign-extended to 64 bits.
// VMOptions=--deterministic --optimization_counter_threshold=80
import 'dart:typed_data';
import "package:expect/expect.dart";
const int minLevel = -1;
void foo() {
// Make sure this method is compiled.
for (int i = 0; i < 100; i++) {}
bool ok = false;
try {
for (int loc0 in ((Uint16List(40)).sublist(minLevel, 42))) {
print(loc0);
}
} catch (e) {
ok = true;
}
Expect.isTrue(ok);
}
void main() {
foo();
foo();
}

View file

@ -0,0 +1,37 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Regression test for https://github.com/dart-lang/sdk/issues/47704.
// Verifies that compiler doesn't crash with compressed pointers when
// generating code involving as 32-bit Smi constant which is not
// sign-extended to 64 bits.
// VMOptions=--deterministic --optimization_counter_threshold=80
// @dart = 2.9
import 'dart:typed_data';
import "package:expect/expect.dart";
const int minLevel = -1;
void foo() {
// Make sure this method is compiled.
for (int i = 0; i < 100; i++) {}
bool ok = false;
try {
for (int loc0 in ((Uint16List(40)).sublist(minLevel, 42))) {
print(loc0);
}
} catch (e) {
ok = true;
}
Expect.isTrue(ok);
}
void main() {
foo();
foo();
}

View file

@ -1071,7 +1071,7 @@ Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
Location right = locs()->in(1);
if (right.IsConstant()) {
ASSERT(right.constant().IsSmi());
const int64_t imm = static_cast<int64_t>(right.constant().ptr());
const int64_t imm = Smi::RawValue(Smi::Cast(right.constant()).Value());
__ TestImmediate(left, imm, compiler::kObjectBytes);
} else {
__ tst(left, compiler::Operand(right.reg()), compiler::kObjectBytes);
@ -3438,7 +3438,7 @@ void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
if (locs()->in(1).IsConstant()) {
const Object& constant = locs()->in(1).constant();
ASSERT(constant.IsSmi());
const int64_t imm = static_cast<int64_t>(constant.ptr());
const int64_t imm = Smi::RawValue(Smi::Cast(constant).Value());
switch (op_kind()) {
case Token::kADD: {
if (deopt == NULL) {

View file

@ -1037,7 +1037,7 @@ Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
Location right = locs()->in(1);
if (right.IsConstant()) {
ASSERT(right.constant().IsSmi());
const int64_t imm = static_cast<int64_t>(right.constant().ptr());
const int64_t imm = Smi::RawValue(Smi::Cast(right.constant()).Value());
__ TestImmediate(left_reg, compiler::Immediate(imm),
compiler::kObjectBytes);
} else {
@ -3487,7 +3487,8 @@ static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
static bool CanBeImmediate(const Object& constant) {
return constant.IsSmi() &&
compiler::Immediate(static_cast<int64_t>(constant.ptr())).is_int32();
compiler::Immediate(Smi::RawValue(Smi::Cast(constant).Value()))
.is_int32();
}
static bool IsSmiValue(const Object& constant, intptr_t value) {
@ -3620,7 +3621,7 @@ void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
if (locs()->in(1).IsConstant()) {
const Object& constant = locs()->in(1).constant();
ASSERT(constant.IsSmi());
const int64_t imm = static_cast<int64_t>(constant.ptr());
const int64_t imm = Smi::RawValue(Smi::Cast(constant).Value());
switch (op_kind()) {
case Token::kADD: {
__ AddImmediate(left, compiler::Immediate(imm), compiler::kObjectBytes);