Commit 3ce52ca3 authored by Théotime Grohens's avatar Théotime Grohens Committed by Commit Bot

[dataview][cleanup] Encapsulate BigInt allocation logic in data-view.tq

This CL separates the BigInt allocation code in the DataView BigInt
getters from the logic of the getters themselves.

This makes the code much easier to read and understand.

Change-Id: I9f7ee3fb819f0606dc631bac89e386f6fec43655
Reviewed-on: https://chromium-review.googlesource.com/1107632
Commit-Queue: Théotime Grohens <theotime@google.com>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54036}
parent 6b810dad
...@@ -353,6 +353,7 @@ extern macro IntPtrConstant(constexpr int31): intptr; ...@@ -353,6 +353,7 @@ extern macro IntPtrConstant(constexpr int31): intptr;
extern macro IntPtrConstant(constexpr int32): intptr; extern macro IntPtrConstant(constexpr int32): intptr;
extern macro Int32Constant(constexpr int31): int32; extern macro Int32Constant(constexpr int31): int32;
extern macro Int32Constant(constexpr int32): int32; extern macro Int32Constant(constexpr int32): int32;
extern macro Float64Constant(constexpr int31): float64;
extern macro SmiConstant(constexpr int31): Smi; extern macro SmiConstant(constexpr int31): Smi;
extern macro BoolConstant(constexpr bool): bool; extern macro BoolConstant(constexpr bool): bool;
extern macro StringConstant(constexpr String): String; extern macro StringConstant(constexpr String): String;
...@@ -378,6 +379,9 @@ from_constexpr<Smi>(i: constexpr int31): Smi { ...@@ -378,6 +379,9 @@ from_constexpr<Smi>(i: constexpr int31): Smi {
from_constexpr<Number>(i: constexpr int31): Number { from_constexpr<Number>(i: constexpr int31): Number {
return SmiConstant(i); return SmiConstant(i);
} }
from_constexpr<float64>(i: constexpr int31): float64 {
return Float64Constant(i);
}
macro from_constexpr<A : type>(o: constexpr int32): A; macro from_constexpr<A : type>(o: constexpr int32): A;
from_constexpr<intptr>(i: constexpr int32): intptr { from_constexpr<intptr>(i: constexpr int32): intptr {
return IntPtrConstant(i); return IntPtrConstant(i);
......
...@@ -225,53 +225,78 @@ module data_view { ...@@ -225,53 +225,78 @@ module data_view {
let b5: uint32 = LoadUint8(data_pointer, offset + 5); let b5: uint32 = LoadUint8(data_pointer, offset + 5);
let b6: uint32 = LoadUint8(data_pointer, offset + 6); let b6: uint32 = LoadUint8(data_pointer, offset + 6);
let b7: uint32 = LoadUint8(data_pointer, offset + 7); let b7: uint32 = LoadUint8(data_pointer, offset + 7);
let result: float64 = convert<float64>(0); let low_word: uint32;
let high_word: uint32;
if (requested_little_endian) { if (requested_little_endian) {
let low_word: uint32 = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; low_word = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
let high_word: uint32 = (b7 << 24) | (b6 << 16) | (b5 << 8) | b4; high_word = (b7 << 24) | (b6 << 16) | (b5 << 8) | b4;
result = Float64InsertLowWord32(result, low_word);
result = Float64InsertHighWord32(result, high_word);
} else { } else {
let high_word: uint32 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3; high_word = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
let low_word: uint32 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7; low_word = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
result = Float64InsertLowWord32(result, low_word);
result = Float64InsertHighWord32(result, high_word);
} }
let result: float64 = 0;
result = Float64InsertLowWord32(result, low_word);
result = Float64InsertHighWord32(result, high_word);
return convert<Number>(result); return convert<Number>(result);
} }
extern macro AllocateBigInt(intptr): BigInt; extern macro AllocateBigInt(intptr): BigInt;
extern macro AllocateRawBigInt(intptr): BigInt;
extern macro StoreBigIntBitfield(BigInt, intptr): void; extern macro StoreBigIntBitfield(BigInt, intptr): void;
extern macro StoreBigIntDigit(BigInt, constexpr int31, uintptr): void; extern macro StoreBigIntDigit(BigInt, constexpr int31, uintptr): void;
extern macro DataViewEncodeBigIntBits(constexpr bool, extern macro DataViewEncodeBigIntBits(constexpr bool,
constexpr int31): intptr; constexpr int31): intptr;
const kPositiveBigInt: constexpr bool generates 'false';
const kNegativeBigInt: constexpr bool generates 'true';
const kZeroDigitBigInt: constexpr int31 generates '0';
const kOneDigitBigInt: constexpr int31 generates '1';
const kTwoDigitBigInt: constexpr int31 generates '2';
macro CreateEmptyBigInt(is_positive: bool, length: constexpr int31): BigInt {
// Allocate a BigInt with the desired length (number of digits).
let result: BigInt = AllocateBigInt(length);
// Write the desired sign and length to the BigInt bitfield.
if (is_positive) {
StoreBigIntBitfield(result,
DataViewEncodeBigIntBits(kPositiveBigInt, length));
} else {
StoreBigIntBitfield(result,
DataViewEncodeBigIntBits(kNegativeBigInt, length));
}
return result;
}
// Create a BigInt on a 64-bit architecture from two 32-bit values. // Create a BigInt on a 64-bit architecture from two 32-bit values.
macro MakeBigIntOn64Bit(low_word: uint32, high_word: uint32, macro MakeBigIntOn64Bit(low_word: uint32, high_word: uint32,
signed: constexpr bool): BigInt { signed: constexpr bool): BigInt {
// TODO(theotime): Replace magic numbers for the number of digits in
// AllocateRawBigInt and DataViewEncodeBigIntBits with constants. // 0n is represented by a zero-length BigInt.
let result: BigInt = AllocateRawBigInt(1); if (low_word == 0 && high_word == 0) {
return AllocateBigInt(kZeroDigitBigInt);
}
let is_positive: bool = true;
let high_part: intptr = Signed(convert<uintptr>(high_word)); let high_part: intptr = Signed(convert<uintptr>(high_word));
let low_part: intptr = Signed(convert<uintptr>(low_word)); let low_part: intptr = Signed(convert<uintptr>(low_word));
let value: intptr = (high_part << 32) + low_part; let raw_value: intptr = (high_part << 32) + low_part;
if constexpr (signed) { if constexpr (signed) {
if (value < 0) { if (raw_value < 0) {
StoreBigIntBitfield(result, DataViewEncodeBigIntBits(true, 1)); is_positive = false;
// We have to store the absolute value in the digits. // We have to store the absolute value of raw_value in the digit.
value = 0 - value; raw_value = 0 - raw_value;
} else {
StoreBigIntBitfield(result, DataViewEncodeBigIntBits(false, 1));
} }
} else {
StoreBigIntBitfield(result, DataViewEncodeBigIntBits(false, 1));
} }
StoreBigIntDigit(result, 0, Unsigned(value)); // Allocate the BigInt and store the absolute value.
let result: BigInt = CreateEmptyBigInt(is_positive, kOneDigitBigInt);
StoreBigIntDigit(result, 0, Unsigned(raw_value));
return result; return result;
} }
...@@ -279,28 +304,31 @@ module data_view { ...@@ -279,28 +304,31 @@ module data_view {
// Create a BigInt on a 32-bit architecture from two 32-bit values. // Create a BigInt on a 32-bit architecture from two 32-bit values.
macro MakeBigIntOn32Bit(low_word: uint32, high_word: uint32, macro MakeBigIntOn32Bit(low_word: uint32, high_word: uint32,
signed: constexpr bool): BigInt { signed: constexpr bool): BigInt {
// TODO(theotime): Replace magic numbers for the number of digits in
// AllocateRawBigInt and DataViewEncodeBigIntBits with constants.
let result: BigInt; // 0n is represented by a zero-length BigInt.
if (low_word == 0 && high_word == 0) {
return AllocateBigInt(kZeroDigitBigInt);
}
// On a 32-bit platform, we might need 1 or 2 digits to store the number. // On a 32-bit platform, we might need 1 or 2 digits to store the number.
let two_digits: bool = false; let need_two_digits: bool = false;
let is_positive: bool = true;
// We need to do some math on low_word and high_word, // We need to do some math on low_word and high_word,
// so convert them to int32. // so convert them to int32.
let low_part: int32 = Signed(low_word); let low_part: int32 = Signed(low_word);
let high_part: int32 = Signed(high_word); let high_part: int32 = Signed(high_word);
// If high_word == 0, the number is positive, so we only need 1 digit. // If high_word == 0, the number is positive, and we only need 1 digit,
if (high_word == 0) { // so we don't have anything to do.
result = AllocateRawBigInt(1); // Otherwise, all cases are possible.
StoreBigIntBitfield(result, DataViewEncodeBigIntBits(false, 1)); if (high_word != 0) {
} else {
if constexpr (signed) { if constexpr (signed) {
// If high_part < 0, the number is always negative. // If high_part < 0, the number is always negative.
if (high_part < 0) { if (high_part < 0) {
is_positive = false;
// We have to compute the absolute value by hand. // We have to compute the absolute value by hand.
// There will be a negative carry from the low word // There will be a negative carry from the low word
// to the high word iff low != 0. // to the high word iff low != 0.
...@@ -310,48 +338,58 @@ module data_view { ...@@ -310,48 +338,58 @@ module data_view {
} }
low_part = 0 - low_part; low_part = 0 - low_part;
// Here, high_part can be 0 again so we might have 1 or 2 digits. // Here, high_part could be 0 again so we might have 1 or 2 digits.
if (high_part == 0) { if (high_part != 0) {
result = AllocateRawBigInt(1); need_two_digits = true;
StoreBigIntBitfield(result, DataViewEncodeBigIntBits(true, 1));
} else {
result = AllocateRawBigInt(2);
StoreBigIntBitfield(result, DataViewEncodeBigIntBits(true, 2));
two_digits = true;
} }
} else { } else {
// In this case, the number is positive, and we need 2 digits. // In this case, the number is positive, and we need 2 digits.
result = AllocateRawBigInt(2); need_two_digits = true;
StoreBigIntBitfield(result, DataViewEncodeBigIntBits(false, 2));
two_digits = true;
} }
} else { } else {
// In this case, the number is positive (unsigned), // In this case, the number is positive (unsigned),
// and we need 2 digits. // and we need 2 digits.
result = AllocateRawBigInt(2); need_two_digits = true;
StoreBigIntBitfield(result, DataViewEncodeBigIntBits(false, 2));
two_digits = true;
} }
} }
// Allocate the BigInt with the right sign and length.
let result: BigInt;
if (need_two_digits) {
result = CreateEmptyBigInt(is_positive, kTwoDigitBigInt);
} else {
result = CreateEmptyBigInt(is_positive, kOneDigitBigInt);
}
// Finally, write the digit(s) to the BigInt. // Finally, write the digit(s) to the BigInt.
StoreBigIntDigit(result, 0, Unsigned(convert<intptr>(low_part))); StoreBigIntDigit(result, 0, Unsigned(convert<intptr>(low_part)));
if (two_digits) {
if (need_two_digits) {
StoreBigIntDigit(result, 1, Unsigned(convert<intptr>(high_part))); StoreBigIntDigit(result, 1, Unsigned(convert<intptr>(high_part)));
} }
return result; return result;
} }
macro MakeBigInt(low_word: uint32, high_word: uint32,
signed: constexpr bool): BigInt {
// A BigInt digit has the platform word size, so we only need one digit
// on 64-bit platforms but may need two on 32-bit.
if constexpr (Is64()) {
return MakeBigIntOn64Bit(low_word, high_word, signed);
} else {
return MakeBigIntOn32Bit(low_word, high_word, signed);
}
}
macro LoadDataViewBigInt(buffer: JSArrayBuffer, offset: intptr, macro LoadDataViewBigInt(buffer: JSArrayBuffer, offset: intptr,
requested_little_endian: bool, requested_little_endian: bool,
signed: constexpr bool): BigInt { signed: constexpr bool): BigInt {
let data_pointer: RawPtr = buffer.backing_store; let data_pointer: RawPtr = buffer.backing_store;
let low_word: uint32; let low_word: uint32;
let high_word: uint32; let high_word: uint32;
let result: BigInt;
// If endiannesses match and the pointer is aligned, we can // If endiannesses match and the pointer is aligned, we can
// directly load the words. // directly load the words.
...@@ -384,19 +422,7 @@ module data_view { ...@@ -384,19 +422,7 @@ module data_view {
} }
} }
// 0 is a special case (0 BigInt digits), we handle it separately here. return MakeBigInt(low_word, high_word, signed);
if (low_word == 0 && high_word == 0) {
result = AllocateBigInt(0);
} else {
// A BigInt digit has the platform word size, so we only need one digit
// on 64-bit platforms but may need two on 32-bit.
if constexpr (Is64()) {
result = MakeBigIntOn64Bit(low_word, high_word, signed);
} else {
result = MakeBigIntOn32Bit(low_word, high_word, signed);
}
}
return result;
} }
extern macro ToSmiIndex(Object, Context): Smi labels RangeError; extern macro ToSmiIndex(Object, Context): Smi labels RangeError;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment