[vm, compiler] Respect --use_slow_path in CheckedSmiOp/Comparison.

TEST=ci
Change-Id: Ib2b1a9b067beb1cbeea2b12355e62a45396697f5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/192726
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak
2021-03-25 17:39:24 +00:00
committed by commit-bot@chromium.org
parent 3b76190e02
commit 2c371ff74e
17 changed files with 446 additions and 28 deletions
+15 -13
View File
@@ -3928,18 +3928,19 @@ void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
intptr_t left_cid = this->left()->Type()->ToCid();
intptr_t right_cid = this->right()->Type()->ToCid();
bool combined_smi_check = false;
if (this->left()->definition() == this->right()->definition()) {
__ tst(left, compiler::Operand(kSmiTagMask));
if (FLAG_use_slow_path) {
__ b(slow_path->entry_label());
} else if (this->left()->definition() == this->right()->definition()) {
__ BranchIfNotSmi(left, slow_path->entry_label());
} else if (left_cid == kSmiCid) {
__ tst(right, compiler::Operand(kSmiTagMask));
__ BranchIfNotSmi(right, slow_path->entry_label());
} else if (right_cid == kSmiCid) {
__ tst(left, compiler::Operand(kSmiTagMask));
__ BranchIfNotSmi(left, slow_path->entry_label());
} else {
combined_smi_check = true;
__ orr(result, left, compiler::Operand(right));
__ tst(result, compiler::Operand(kSmiTagMask));
__ BranchIfNotSmi(result, slow_path->entry_label());
}
__ b(slow_path->entry_label(), NE);
switch (op_kind()) {
case Token::kADD:
__ adds(result, left, compiler::Operand(right));
@@ -4148,17 +4149,18 @@ Condition CheckedSmiComparisonInstr::EmitComparisonCode(
Register temp = locs()->temp(0).reg(); \
intptr_t left_cid = this->left()->Type()->ToCid(); \
intptr_t right_cid = this->right()->Type()->ToCid(); \
if (this->left()->definition() == this->right()->definition()) { \
__ tst(left, compiler::Operand(kSmiTagMask)); \
if (FLAG_use_slow_path) { \
__ b(slow_path->entry_label()); \
} else if (this->left()->definition() == this->right()->definition()) { \
__ BranchIfNotSmi(left, slow_path->entry_label()); \
} else if (left_cid == kSmiCid) { \
__ tst(right, compiler::Operand(kSmiTagMask)); \
__ BranchIfNotSmi(right, slow_path->entry_label()); \
} else if (right_cid == kSmiCid) { \
__ tst(left, compiler::Operand(kSmiTagMask)); \
__ BranchIfNotSmi(left, slow_path->entry_label()); \
} else { \
__ orr(temp, left, compiler::Operand(right)); \
__ tst(temp, compiler::Operand(kSmiTagMask)); \
} \
__ b(slow_path->entry_label(), NE)
__ BranchIfNotSmi(temp, slow_path->entry_label()); \
}
void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
+6 -2
View File
@@ -3492,7 +3492,9 @@ void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
intptr_t left_cid = this->left()->Type()->ToCid();
intptr_t right_cid = this->right()->Type()->ToCid();
bool combined_smi_check = false;
if (this->left()->definition() == this->right()->definition()) {
if (FLAG_use_slow_path) {
__ b(slow_path->entry_label());
} else if (this->left()->definition() == this->right()->definition()) {
__ BranchIfNotSmi(left, slow_path->entry_label());
} else if (left_cid == kSmiCid) {
__ BranchIfNotSmi(right, slow_path->entry_label());
@@ -3672,7 +3674,9 @@ Condition CheckedSmiComparisonInstr::EmitComparisonCode(
Register temp = locs()->temp(0).reg(); \
intptr_t left_cid = this->left()->Type()->ToCid(); \
intptr_t right_cid = this->right()->Type()->ToCid(); \
if (this->left()->definition() == this->right()->definition()) { \
if (FLAG_use_slow_path) { \
__ b(slow_path->entry_label()); \
} else if (this->left()->definition() == this->right()->definition()) { \
__ BranchIfNotSmi(left, slow_path->entry_label()); \
} else if (left_cid == kSmiCid) { \
__ BranchIfNotSmi(right, slow_path->entry_label()); \
+15 -13
View File
@@ -3600,18 +3600,19 @@ void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
intptr_t right_cid = right()->Type()->ToCid();
Register left = locs()->in(0).reg();
Register right = locs()->in(1).reg();
if (this->left()->definition() == this->right()->definition()) {
__ testq(left, compiler::Immediate(kSmiTagMask));
if (FLAG_use_slow_path) {
__ jmp(slow_path->entry_label());
} else if (this->left()->definition() == this->right()->definition()) {
__ BranchIfNotSmi(left, slow_path->entry_label());
} else if (left_cid == kSmiCid) {
__ testq(right, compiler::Immediate(kSmiTagMask));
__ BranchIfNotSmi(right, slow_path->entry_label());
} else if (right_cid == kSmiCid) {
__ testq(left, compiler::Immediate(kSmiTagMask));
__ BranchIfNotSmi(left, slow_path->entry_label());
} else {
__ movq(TMP, left);
__ orq(TMP, right);
__ testq(TMP, compiler::Immediate(kSmiTagMask));
__ BranchIfNotSmi(TMP, slow_path->entry_label());
}
__ j(NOT_ZERO, slow_path->entry_label());
Register result = locs()->out(0).reg();
switch (op_kind()) {
case Token::kADD:
@@ -3791,18 +3792,19 @@ Condition CheckedSmiComparisonInstr::EmitComparisonCode(
intptr_t right_cid = right()->Type()->ToCid(); \
Register left = locs()->in(0).reg(); \
Register right = locs()->in(1).reg(); \
if (this->left()->definition() == this->right()->definition()) { \
__ testq(left, compiler::Immediate(kSmiTagMask)); \
if (FLAG_use_slow_path) { \
__ jmp(slow_path->entry_label()); \
} else if (this->left()->definition() == this->right()->definition()) { \
__ BranchIfNotSmi(left, slow_path->entry_label()); \
} else if (left_cid == kSmiCid) { \
__ testq(right, compiler::Immediate(kSmiTagMask)); \
__ BranchIfNotSmi(right, slow_path->entry_label()); \
} else if (right_cid == kSmiCid) { \
__ testq(left, compiler::Immediate(kSmiTagMask)); \
__ BranchIfNotSmi(left, slow_path->entry_label()); \
} else { \
__ movq(TMP, left); \
__ orq(TMP, right); \
__ testq(TMP, compiler::Immediate(kSmiTagMask)); \
} \
__ j(NOT_ZERO, slow_path->entry_label())
__ BranchIfNotSmi(TMP, slow_path->entry_label()); \
}
void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
@@ -0,0 +1,86 @@
// 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.
// VMOptions=
// VMOptions=--use_slow_path
import "package:expect/expect.dart";
@pragma("vm:never-inline")
dynamic hiddenSmi() {
try {
throw 42;
} catch (e) {
return e;
}
return 0;
}
@pragma("vm:never-inline")
dynamic hiddenMint() {
try {
throw 0x8000000000000000;
} catch (e) {
return e;
}
return 0;
}
@pragma("vm:never-inline")
dynamic hiddenDouble() {
try {
throw 3.0;
} catch (e) {
return e;
}
return 0;
}
@pragma("vm:never-inline")
dynamic hiddenCustom() {
try {
throw new Custom();
} catch (e) {
return e;
}
return 0;
}
class Custom {
operator <(other) => "lt";
operator >(other) => "gt";
operator <=(other) => "le";
operator >=(other) => "ge";
operator ==(other) => false;
}
main() {
Expect.equals(false, hiddenSmi() < 2);
Expect.equals(true, hiddenSmi() > 2);
Expect.equals(false, hiddenSmi() <= 2);
Expect.equals(true, hiddenSmi() >= 2);
Expect.equals(false, hiddenSmi() == 2);
Expect.equals(true, hiddenSmi() != 2);
Expect.equals(true, hiddenMint() < 2);
Expect.equals(false, hiddenMint() > 2);
Expect.equals(true, hiddenMint() <= 2);
Expect.equals(false, hiddenMint() >= 2);
Expect.equals(false, hiddenMint() == 2);
Expect.equals(true, hiddenMint() != 2);
Expect.equals(false, hiddenDouble() < 2);
Expect.equals(true, hiddenDouble() > 2);
Expect.equals(false, hiddenDouble() <= 2);
Expect.equals(true, hiddenDouble() >= 2);
Expect.equals(false, hiddenDouble() == 2);
Expect.equals(true, hiddenDouble() != 2);
Expect.equals("lt", hiddenCustom() < 2);
Expect.equals("gt", hiddenCustom() > 2);
Expect.equals("le", hiddenCustom() <= 2);
Expect.equals("ge", hiddenCustom() >= 2);
Expect.equals(false, hiddenCustom() == 2);
Expect.equals(true, hiddenCustom() != 2);
}
+113
View File
@@ -0,0 +1,113 @@
// 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.
// SharedOptions=--enable-experiment=triple-shift
// VMOptions=
// VMOptions=--use_slow_path
import "package:expect/expect.dart";
@pragma("vm:never-inline")
dynamic hiddenSmi() {
try {
throw 42;
} catch (e) {
return e;
}
return 0;
}
@pragma("vm:never-inline")
dynamic hiddenMint() {
try {
throw 0x8000000000000000;
} catch (e) {
return e;
}
return 0;
}
@pragma("vm:never-inline")
dynamic hiddenDouble() {
try {
throw 3.0;
} catch (e) {
return e;
}
return 0;
}
@pragma("vm:never-inline")
dynamic hiddenCustom() {
try {
throw new Custom();
} catch (e) {
return e;
}
return 0;
}
class Custom {
operator +(other) => "add";
operator -(other) => "sub";
operator *(other) => "mul";
operator ~/(other) => "div";
operator %(other) => "mod";
operator &(other) => "and";
operator |(other) => "or";
operator ^(other) => "xor";
operator <<(other) => "sll";
operator >>(other) => "sra";
operator >>>(other) => "srl";
}
main() {
Expect.equals(44, hiddenSmi() + 2);
Expect.equals(40, hiddenSmi() - 2);
Expect.equals(84, hiddenSmi() * 2);
Expect.equals(21, hiddenSmi() ~/ 2);
Expect.equals(0, hiddenSmi() % 2);
Expect.equals(2, hiddenSmi() & 2);
Expect.equals(42, hiddenSmi() | 2);
Expect.equals(40, hiddenSmi() ^ 2);
Expect.equals(168, hiddenSmi() << 2);
Expect.equals(10, hiddenSmi() >> 2);
Expect.equals(10, hiddenSmi() >>> 2);
Expect.equals(-9223372036854775806, hiddenMint() + 2);
Expect.equals(9223372036854775806, hiddenMint() - 2);
Expect.equals(0, hiddenMint() * 2);
Expect.equals(-4611686018427387904, hiddenMint() ~/ 2);
Expect.equals(0, hiddenMint() % 2);
Expect.equals(0, hiddenMint() & 2);
Expect.equals(-9223372036854775806, hiddenMint() | 2);
Expect.equals(-9223372036854775806, hiddenMint() ^ 2);
Expect.equals(0, hiddenMint() << 2);
Expect.equals(-2305843009213693952, hiddenMint() >> 2);
Expect.equals(2305843009213693952, hiddenMint() >>> 2);
Expect.equals(5.0, hiddenDouble() + 2);
Expect.equals(1.0, hiddenDouble() - 2);
Expect.equals(6.0, hiddenDouble() * 2);
Expect.equals(1, hiddenDouble() ~/ 2);
Expect.equals(1.0, hiddenDouble() % 2);
Expect.throws(() => hiddenDouble() & 2, (e) => e is NoSuchMethodError);
Expect.throws(() => hiddenDouble() | 2, (e) => e is NoSuchMethodError);
Expect.throws(() => hiddenDouble() ^ 2, (e) => e is NoSuchMethodError);
Expect.throws(() => hiddenDouble() << 2, (e) => e is NoSuchMethodError);
Expect.throws(() => hiddenDouble() >> 2, (e) => e is NoSuchMethodError);
Expect.throws(() => hiddenDouble() >>> 2, (e) => e is NoSuchMethodError);
Expect.equals("add", hiddenCustom() + 2);
Expect.equals("sub", hiddenCustom() - 2);
Expect.equals("mul", hiddenCustom() * 2);
Expect.equals("div", hiddenCustom() ~/ 2);
Expect.equals("mod", hiddenCustom() % 2);
Expect.equals("and", hiddenCustom() & 2);
Expect.equals("or", hiddenCustom() | 2);
Expect.equals("xor", hiddenCustom() ^ 2);
Expect.equals("sll", hiddenCustom() << 2);
Expect.equals("sra", hiddenCustom() >> 2);
Expect.equals("srl", hiddenCustom() >>> 2);
}
+1
View File
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
// VMOptions=--deterministic
// VMOptions=--deterministic --use_slow_path
// Unit tests on DIV and MOV operations by various constants.
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
// VMOptions=--no_background_compilation --optimization_counter_threshold=10
// VMOptions=--no_background_compilation --optimization_counter_threshold=10 --use_slow_path
import "package:expect/expect.dart";
+1
View File
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
// VMOptions=--no_background_compilation --optimization_counter_threshold=10
// VMOptions=--no_background_compilation --optimization_counter_threshold=10 --use_slow_path
import "package:expect/expect.dart";
+1
View File
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
// VMOptions=--no_background_compilation --optimization_counter_threshold=10
// VMOptions=--no_background_compilation --optimization_counter_threshold=10 --use_slow_path
import "package:expect/expect.dart";
@@ -1,7 +1,9 @@
// Copyright (c) 2018, 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.
// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
// VMOptions=--optimization-counter-threshold=10 --no-background-compilation --use_slow_path
// Test for special cases of << and >> integer operations with int64.
@@ -0,0 +1,86 @@
// 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.
// VMOptions=
// VMOptions=--use_slow_path
import "package:expect/expect.dart";
@pragma("vm:never-inline")
dynamic hiddenSmi() {
try {
throw 42;
} catch (e) {
return e;
}
return 0;
}
@pragma("vm:never-inline")
dynamic hiddenMint() {
try {
throw 0x8000000000000000;
} catch (e) {
return e;
}
return 0;
}
@pragma("vm:never-inline")
dynamic hiddenDouble() {
try {
throw 3.0;
} catch (e) {
return e;
}
return 0;
}
@pragma("vm:never-inline")
dynamic hiddenCustom() {
try {
throw new Custom();
} catch (e) {
return e;
}
return 0;
}
class Custom {
operator <(other) => "lt";
operator >(other) => "gt";
operator <=(other) => "le";
operator >=(other) => "ge";
operator ==(other) => false;
}
main() {
Expect.equals(false, hiddenSmi() < 2);
Expect.equals(true, hiddenSmi() > 2);
Expect.equals(false, hiddenSmi() <= 2);
Expect.equals(true, hiddenSmi() >= 2);
Expect.equals(false, hiddenSmi() == 2);
Expect.equals(true, hiddenSmi() != 2);
Expect.equals(true, hiddenMint() < 2);
Expect.equals(false, hiddenMint() > 2);
Expect.equals(true, hiddenMint() <= 2);
Expect.equals(false, hiddenMint() >= 2);
Expect.equals(false, hiddenMint() == 2);
Expect.equals(true, hiddenMint() != 2);
Expect.equals(false, hiddenDouble() < 2);
Expect.equals(true, hiddenDouble() > 2);
Expect.equals(false, hiddenDouble() <= 2);
Expect.equals(true, hiddenDouble() >= 2);
Expect.equals(false, hiddenDouble() == 2);
Expect.equals(true, hiddenDouble() != 2);
Expect.equals("lt", hiddenCustom() < 2);
Expect.equals("gt", hiddenCustom() > 2);
Expect.equals("le", hiddenCustom() <= 2);
Expect.equals("ge", hiddenCustom() >= 2);
Expect.equals(false, hiddenCustom() == 2);
Expect.equals(true, hiddenCustom() != 2);
}
@@ -0,0 +1,113 @@
// 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.
// SharedOptions=--enable-experiment=triple-shift
// VMOptions=
// VMOptions=--use_slow_path
import "package:expect/expect.dart";
@pragma("vm:never-inline")
dynamic hiddenSmi() {
try {
throw 42;
} catch (e) {
return e;
}
return 0;
}
@pragma("vm:never-inline")
dynamic hiddenMint() {
try {
throw 0x8000000000000000;
} catch (e) {
return e;
}
return 0;
}
@pragma("vm:never-inline")
dynamic hiddenDouble() {
try {
throw 3.0;
} catch (e) {
return e;
}
return 0;
}
@pragma("vm:never-inline")
dynamic hiddenCustom() {
try {
throw new Custom();
} catch (e) {
return e;
}
return 0;
}
class Custom {
operator +(other) => "add";
operator -(other) => "sub";
operator *(other) => "mul";
operator ~/(other) => "div";
operator %(other) => "mod";
operator &(other) => "and";
operator |(other) => "or";
operator ^(other) => "xor";
operator <<(other) => "sll";
operator >>(other) => "sra";
operator >>>(other) => "srl";
}
main() {
Expect.equals(44, hiddenSmi() + 2);
Expect.equals(40, hiddenSmi() - 2);
Expect.equals(84, hiddenSmi() * 2);
Expect.equals(21, hiddenSmi() ~/ 2);
Expect.equals(0, hiddenSmi() % 2);
Expect.equals(2, hiddenSmi() & 2);
Expect.equals(42, hiddenSmi() | 2);
Expect.equals(40, hiddenSmi() ^ 2);
Expect.equals(168, hiddenSmi() << 2);
Expect.equals(10, hiddenSmi() >> 2);
Expect.equals(10, hiddenSmi() >>> 2);
Expect.equals(-9223372036854775806, hiddenMint() + 2);
Expect.equals(9223372036854775806, hiddenMint() - 2);
Expect.equals(0, hiddenMint() * 2);
Expect.equals(-4611686018427387904, hiddenMint() ~/ 2);
Expect.equals(0, hiddenMint() % 2);
Expect.equals(0, hiddenMint() & 2);
Expect.equals(-9223372036854775806, hiddenMint() | 2);
Expect.equals(-9223372036854775806, hiddenMint() ^ 2);
Expect.equals(0, hiddenMint() << 2);
Expect.equals(-2305843009213693952, hiddenMint() >> 2);
Expect.equals(2305843009213693952, hiddenMint() >>> 2);
Expect.equals(5.0, hiddenDouble() + 2);
Expect.equals(1.0, hiddenDouble() - 2);
Expect.equals(6.0, hiddenDouble() * 2);
Expect.equals(1, hiddenDouble() ~/ 2);
Expect.equals(1.0, hiddenDouble() % 2);
Expect.throws(() => hiddenDouble() & 2, (e) => e is NoSuchMethodError);
Expect.throws(() => hiddenDouble() | 2, (e) => e is NoSuchMethodError);
Expect.throws(() => hiddenDouble() ^ 2, (e) => e is NoSuchMethodError);
Expect.throws(() => hiddenDouble() << 2, (e) => e is NoSuchMethodError);
Expect.throws(() => hiddenDouble() >> 2, (e) => e is NoSuchMethodError);
Expect.throws(() => hiddenDouble() >>> 2, (e) => e is NoSuchMethodError);
Expect.equals("add", hiddenCustom() + 2);
Expect.equals("sub", hiddenCustom() - 2);
Expect.equals("mul", hiddenCustom() * 2);
Expect.equals("div", hiddenCustom() ~/ 2);
Expect.equals("mod", hiddenCustom() % 2);
Expect.equals("and", hiddenCustom() & 2);
Expect.equals("or", hiddenCustom() | 2);
Expect.equals("xor", hiddenCustom() ^ 2);
Expect.equals("sll", hiddenCustom() << 2);
Expect.equals("sra", hiddenCustom() >> 2);
Expect.equals("srl", hiddenCustom() >>> 2);
}
+1
View File
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
// VMOptions=--deterministic
// VMOptions=--deterministic --use_slow_path
// Unit tests on DIV and MOV operations by various constants.
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
// VMOptions=--no_background_compilation --optimization_counter_threshold=10
// VMOptions=--no_background_compilation --optimization_counter_threshold=10 --use_slow_path
import "package:expect/expect.dart";
+1
View File
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
// VMOptions=--no_background_compilation --optimization_counter_threshold=10
// VMOptions=--no_background_compilation --optimization_counter_threshold=10 --use_slow_path
import "package:expect/expect.dart";
+1
View File
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
// VMOptions=--no_background_compilation --optimization_counter_threshold=10
// VMOptions=--no_background_compilation --optimization_counter_threshold=10 --use_slow_path
import "package:expect/expect.dart";
@@ -1,7 +1,9 @@
// Copyright (c) 2018, 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.
// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
// VMOptions=--optimization-counter-threshold=10 --no-background-compilation --use_slow_path
// Test for special cases of << and >> integer operations with int64.