From bc3aa70e2043d0e950c1cb7efdc45f76f9ecaf71 Mon Sep 17 00:00:00 2001 From: Ryan Macnak Date: Thu, 3 Jun 2021 22:47:56 +0000 Subject: [PATCH] [vm, compiler] Fix size of sign-extension in x64c BigInt intrinsics. TEST=ci Change-Id: I99aa9875705823c22b5474bb1d66c7bc1aaac9fb Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/202309 Reviewed-by: Liam Appelbe Commit-Queue: Ryan Macnak --- runtime/vm/compiler/asm_intrinsifier_x64.cc | 30 ++++++++++----------- tests/corelib/very_big_integer_test.dart | 18 +++++++++++++ tests/corelib_2/very_big_integer_test.dart | 20 ++++++++++++++ 3 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 tests/corelib/very_big_integer_test.dart create mode 100644 tests/corelib_2/very_big_integer_test.dart diff --git a/runtime/vm/compiler/asm_intrinsifier_x64.cc b/runtime/vm/compiler/asm_intrinsifier_x64.cc index eb5b694a53c..da97a491e1f 100644 --- a/runtime/vm/compiler/asm_intrinsifier_x64.cc +++ b/runtime/vm/compiler/asm_intrinsifier_x64.cc @@ -243,13 +243,13 @@ void AsmIntrinsifier::Bigint_lsh(Assembler* assembler, Label* normal_ir_body) { __ movq(RDI, Address(RSP, 4 * target::kWordSize)); // x_digits __ movq(R8, Address(RSP, 3 * target::kWordSize)); // x_used is Smi #if defined(DART_COMPRESSED_POINTERS) - __ movsxw(R8, R8); + __ movsxd(R8, R8); #endif __ subq(R8, Immediate(2)); // x_used > 0, Smi. R8 = x_used - 1, round up. __ sarq(R8, Immediate(2)); // R8 + 1 = number of digit pairs to read. __ movq(RCX, Address(RSP, 2 * target::kWordSize)); // n is Smi #if defined(DART_COMPRESSED_POINTERS) - __ movsxw(RCX, RCX); + __ movsxd(RCX, RCX); #endif __ SmiUntag(RCX); __ movq(RBX, Address(RSP, 1 * target::kWordSize)); // r_digits @@ -289,7 +289,7 @@ void AsmIntrinsifier::Bigint_rsh(Assembler* assembler, Label* normal_ir_body) { __ movq(RDI, Address(RSP, 4 * target::kWordSize)); // x_digits __ movq(RCX, Address(RSP, 2 * target::kWordSize)); // n is Smi #if defined(DART_COMPRESSED_POINTERS) - __ movsxw(RCX, RCX); + __ movsxd(RCX, RCX); #endif __ SmiUntag(RCX); __ movq(RBX, Address(RSP, 1 * target::kWordSize)); // r_digits @@ -297,7 +297,7 @@ void AsmIntrinsifier::Bigint_rsh(Assembler* assembler, Label* normal_ir_body) { __ sarq(RDX, Immediate(6)); // RDX = n ~/ (2*_DIGIT_BITS). __ movq(RSI, Address(RSP, 3 * target::kWordSize)); // x_used is Smi #if defined(DART_COMPRESSED_POINTERS) - __ movsxw(RSI, RSI); + __ movsxd(RSI, RSI); #endif __ subq(RSI, Immediate(2)); // x_used > 0, Smi. RSI = x_used - 1, round up. __ sarq(RSI, Immediate(2)); @@ -335,14 +335,14 @@ void AsmIntrinsifier::Bigint_absAdd(Assembler* assembler, __ movq(RDI, Address(RSP, 5 * target::kWordSize)); // digits __ movq(R8, Address(RSP, 4 * target::kWordSize)); // used is Smi #if defined(DART_COMPRESSED_POINTERS) - __ movsxw(R8, R8); + __ movsxd(R8, R8); #endif __ addq(R8, Immediate(2)); // used > 0, Smi. R8 = used + 1, round up. __ sarq(R8, Immediate(2)); // R8 = number of digit pairs to process. __ movq(RSI, Address(RSP, 3 * target::kWordSize)); // a_digits __ movq(RCX, Address(RSP, 2 * target::kWordSize)); // a_used is Smi #if defined(DART_COMPRESSED_POINTERS) - __ movsxw(RCX, RCX); + __ movsxd(RCX, RCX); #endif __ addq(RCX, Immediate(2)); // a_used > 0, Smi. R8 = a_used + 1, round up. __ sarq(RCX, Immediate(2)); // R8 = number of digit pairs to process. @@ -402,14 +402,14 @@ void AsmIntrinsifier::Bigint_absSub(Assembler* assembler, __ movq(RDI, Address(RSP, 5 * target::kWordSize)); // digits __ movq(R8, Address(RSP, 4 * target::kWordSize)); // used is Smi #if defined(DART_COMPRESSED_POINTERS) - __ movsxw(R8, R8); + __ movsxd(R8, R8); #endif __ addq(R8, Immediate(2)); // used > 0, Smi. R8 = used + 1, round up. __ sarq(R8, Immediate(2)); // R8 = number of digit pairs to process. __ movq(RSI, Address(RSP, 3 * target::kWordSize)); // a_digits __ movq(RCX, Address(RSP, 2 * target::kWordSize)); // a_used is Smi #if defined(DART_COMPRESSED_POINTERS) - __ movsxw(RCX, RCX); + __ movsxd(RCX, RCX); #endif __ addq(RCX, Immediate(2)); // a_used > 0, Smi. R8 = a_used + 1, round up. __ sarq(RCX, Immediate(2)); // R8 = number of digit pairs to process. @@ -489,7 +489,7 @@ void AsmIntrinsifier::Bigint_mulAdd(Assembler* assembler, __ movq(RCX, Address(RSP, 7 * target::kWordSize)); // x_digits __ movq(RAX, Address(RSP, 6 * target::kWordSize)); // xi is Smi #if defined(DART_COMPRESSED_POINTERS) - __ movsxw(RAX, RAX); + __ movsxd(RAX, RAX); #endif __ movq(RBX, FieldAddress(RCX, RAX, TIMES_2, target::TypedData::data_offset())); @@ -499,7 +499,7 @@ void AsmIntrinsifier::Bigint_mulAdd(Assembler* assembler, // R8 = (SmiUntag(n) + 1)/2, no_op if n == 0 __ movq(R8, Address(RSP, 1 * target::kWordSize)); // n is Smi #if defined(DART_COMPRESSED_POINTERS) - __ movsxw(R8, R8); + __ movsxd(R8, R8); #endif __ addq(R8, Immediate(2)); __ sarq(R8, Immediate(2)); // R8 = number of digit pairs to process. @@ -509,7 +509,7 @@ void AsmIntrinsifier::Bigint_mulAdd(Assembler* assembler, __ movq(RDI, Address(RSP, 5 * target::kWordSize)); // m_digits __ movq(RAX, Address(RSP, 4 * target::kWordSize)); // i is Smi #if defined(DART_COMPRESSED_POINTERS) - __ movsxw(RAX, RAX); + __ movsxd(RAX, RAX); #endif __ leaq(RDI, FieldAddress(RDI, RAX, TIMES_2, target::TypedData::data_offset())); @@ -518,7 +518,7 @@ void AsmIntrinsifier::Bigint_mulAdd(Assembler* assembler, __ movq(RSI, Address(RSP, 3 * target::kWordSize)); // a_digits __ movq(RAX, Address(RSP, 2 * target::kWordSize)); // j is Smi #if defined(DART_COMPRESSED_POINTERS) - __ movsxw(RAX, RAX); + __ movsxd(RAX, RAX); #endif __ leaq(RSI, FieldAddress(RSI, RAX, TIMES_2, target::TypedData::data_offset())); @@ -609,7 +609,7 @@ void AsmIntrinsifier::Bigint_sqrAdd(Assembler* assembler, __ movq(RDI, Address(RSP, 4 * target::kWordSize)); // x_digits __ movq(RAX, Address(RSP, 3 * target::kWordSize)); // i is Smi #if defined(DART_COMPRESSED_POINTERS) - __ movsxw(RAX, RAX); + __ movsxd(RAX, RAX); #endif __ leaq(RDI, FieldAddress(RDI, RAX, TIMES_2, target::TypedData::data_offset())); @@ -730,7 +730,7 @@ void AsmIntrinsifier::Bigint_estimateQuotientDigit(Assembler* assembler, __ movq(RBX, Address(RSP, 2 * target::kWordSize)); // digits __ movq(RAX, Address(RSP, 1 * target::kWordSize)); // i is Smi and odd. #if defined(DART_COMPRESSED_POINTERS) - __ movsxw(RAX, RAX); + __ movsxd(RAX, RAX); #endif __ leaq(RBX, FieldAddress( RBX, RAX, TIMES_2, @@ -785,7 +785,7 @@ void AsmIntrinsifier::Montgomery_mulMod(Assembler* assembler, __ movq(RBX, Address(RSP, 2 * target::kWordSize)); // digits __ movq(RAX, Address(RSP, 1 * target::kWordSize)); // i is Smi #if defined(DART_COMPRESSED_POINTERS) - __ movsxw(RAX, RAX); + __ movsxd(RAX, RAX); #endif __ movq(RAX, FieldAddress(RBX, RAX, TIMES_2, target::TypedData::data_offset())); diff --git a/tests/corelib/very_big_integer_test.dart b/tests/corelib/very_big_integer_test.dart new file mode 100644 index 00000000000..cbfc609c49d --- /dev/null +++ b/tests/corelib/very_big_integer_test.dart @@ -0,0 +1,18 @@ +// 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. + +import "package:expect/expect.dart"; + +main() { + // x and y have lengths in 32-bit digits that overflow 16 bits. + var x = new BigInt.from(13) << (65000 * 32); + var y = new BigInt.from(42) << (65000 * 32); + print(x.bitLength); + Expect.equals(x, (x + y) - y); + Expect.equals(x, -((-x + y) - y)); + Expect.equals(x, (x << 2) >> 2); + Expect.equals(x, (x >> 3) << 3); + Expect.equals(0, (x ^ x).toInt()); + Expect.equals(0, (y ^ y).toInt()); +} diff --git a/tests/corelib_2/very_big_integer_test.dart b/tests/corelib_2/very_big_integer_test.dart new file mode 100644 index 00000000000..11465f91aec --- /dev/null +++ b/tests/corelib_2/very_big_integer_test.dart @@ -0,0 +1,20 @@ +// 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. + +// @dart = 2.9 + +import "package:expect/expect.dart"; + +main() { + // x and y have lengths in 32-bit digits that overflow 16 bits. + var x = new BigInt.from(13) << (65000 * 32); + var y = new BigInt.from(42) << (65000 * 32); + print(x.bitLength); + Expect.equals(x, (x + y) - y); + Expect.equals(x, -((-x + y) - y)); + Expect.equals(x, (x << 2) >> 2); + Expect.equals(x, (x >> 3) << 3); + Expect.equals(0, (x ^ x).toInt()); + Expect.equals(0, (y ^ y).toInt()); +}