Commit 350af13c authored by peterwmwong's avatar peterwmwong Committed by Commit Bot

[builtins] Fix Array.p.join overflow detection

Additionally, introduce IntPtrDiv to CodeAssembler.

Change-Id: I9396f77b90a2fadb0179028d44475e616be3d081
Reviewed-on: https://chromium-review.googlesource.com/c/1285400
Commit-Queue: Peter Wong <peter.wm.wong@gmail.com>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56776}
parent 4d0a85ee
......@@ -159,7 +159,7 @@ module array {
}
macro BufferAdd(implicit context: Context)(
initialBuffer: Buffer, str: String, nofSeparators: uintptr,
initialBuffer: Buffer, str: String, nofSeparators: intptr,
separatorLength: intptr): Buffer {
let buffer: Buffer = initialBuffer;
// Add separators if necessary (at the beginning or more than one)
......@@ -178,14 +178,15 @@ module array {
}
macro BufferAddSeparators(implicit context: Context)(
buffer: Buffer, nofSeparators: uintptr, separatorLength: intptr,
buffer: Buffer, nofSeparators: intptr, separatorLength: intptr,
write: bool): Buffer {
if (nofSeparators == 0 || separatorLength == 0) return buffer;
const nofSeparatorsInt: intptr = Signed(nofSeparators);
const nofSeparatorsInt: intptr = nofSeparators;
const sepsLen: intptr = separatorLength * nofSeparatorsInt;
// Detect integer overflow
if (nofSeparatorsInt <= 0 || sepsLen <= 0) deferred {
// TODO(tebbi): Replace with overflow-checked multiplication.
if (sepsLen / separatorLength != nofSeparatorsInt) deferred {
ThrowRangeError(context, kInvalidStringLength);
}
......@@ -225,14 +226,14 @@ module array {
const initialMap: Map = receiver.map;
const len: uintptr = Convert<uintptr>(lengthNumber);
const separatorLength: intptr = sep.length;
let nofSeparators: uintptr = 0;
let nofSeparators: intptr = 0;
let loadJoinElements: LoadJoinElementFn = initialLoadJoinElement;
let buffer: Buffer = BufferInit(estimatedNonHoleyElements, sep);
// 6. Let k be 0.
let k: uintptr = 0;
if (estimatedNonHoleyElements != 0) {
// 6. Let k be 0.
let k: uintptr = 0;
// 7. Repeat, while k < len
while (k < len) {
if (k > 0) {
......@@ -288,8 +289,7 @@ module array {
nofSeparators = 0;
}
} else {
assert(len > k);
nofSeparators = len - k - 1;
nofSeparators = Signed(len - 1);
}
// Add any separators at the end.
......
......@@ -355,6 +355,7 @@ extern operator '<<' macro SmiShl(Smi, constexpr int31): Smi;
extern operator '+' macro IntPtrAdd(intptr, intptr): intptr;
extern operator '-' macro IntPtrSub(intptr, intptr): intptr;
extern operator '*' macro IntPtrMul(intptr, intptr): intptr;
extern operator '/' macro IntPtrDiv(intptr, intptr): intptr;
extern operator '<<' macro WordShl(intptr, intptr): intptr;
extern operator '&' macro WordAnd(intptr, intptr): intptr;
extern operator '|' macro WordOr(intptr, intptr): intptr;
......
......@@ -514,6 +514,23 @@ TNode<WordT> CodeAssembler::IntPtrAdd(SloppyTNode<WordT> left,
return UncheckedCast<WordT>(raw_assembler()->IntPtrAdd(left, right));
}
TNode<IntPtrT> CodeAssembler::IntPtrDiv(TNode<IntPtrT> left,
TNode<IntPtrT> right) {
intptr_t left_constant;
bool is_left_constant = ToIntPtrConstant(left, left_constant);
intptr_t right_constant;
bool is_right_constant = ToIntPtrConstant(right, right_constant);
if (is_right_constant) {
if (is_left_constant) {
return IntPtrConstant(left_constant / right_constant);
}
if (base::bits::IsPowerOfTwo(right_constant)) {
return WordSar(left, WhichPowerOf2(right_constant));
}
}
return UncheckedCast<IntPtrT>(raw_assembler()->IntPtrDiv(left, right));
}
TNode<WordT> CodeAssembler::IntPtrSub(SloppyTNode<WordT> left,
SloppyTNode<WordT> right) {
intptr_t left_constant;
......
......@@ -884,6 +884,10 @@ class V8_EXPORT_PRIVATE CodeAssembler {
return UncheckedCast<IntPtrT>(
WordShr(static_cast<Node*>(left), static_cast<Node*>(right)));
}
TNode<IntPtrT> WordSar(TNode<IntPtrT> left, TNode<IntegralT> right) {
return UncheckedCast<IntPtrT>(
WordSar(static_cast<Node*>(left), static_cast<Node*>(right)));
}
TNode<IntPtrT> WordAnd(TNode<IntPtrT> left, TNode<IntPtrT> right) {
return UncheckedCast<IntPtrT>(
......@@ -946,6 +950,7 @@ class V8_EXPORT_PRIVATE CodeAssembler {
}
TNode<WordT> IntPtrAdd(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
TNode<IntPtrT> IntPtrDiv(TNode<IntPtrT> left, TNode<IntPtrT> right);
TNode<WordT> IntPtrSub(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
TNode<WordT> IntPtrMul(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
TNode<IntPtrT> IntPtrAdd(TNode<IntPtrT> left, TNode<IntPtrT> right) {
......@@ -975,6 +980,9 @@ class V8_EXPORT_PRIVATE CodeAssembler {
TNode<IntPtrT> WordShr(TNode<IntPtrT> value, int shift) {
return UncheckedCast<IntPtrT>(WordShr(static_cast<Node*>(value), shift));
}
TNode<IntPtrT> WordSar(TNode<IntPtrT> value, int shift) {
return UncheckedCast<IntPtrT>(WordSar(static_cast<Node*>(value), shift));
}
TNode<Word32T> Word32Shr(SloppyTNode<Word32T> value, int shift);
TNode<WordT> WordOr(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
......
......@@ -126,6 +126,44 @@ TARGET_TEST_F(CodeAssemblerTest, IntPtrMul) {
}
}
TARGET_TEST_F(CodeAssemblerTest, IntPtrDiv) {
CodeAssemblerTestState state(this);
CodeAssemblerForTest m(&state);
{
TNode<IntPtrT> a = m.UncheckedCast<IntPtrT>(m.Parameter(0));
TNode<IntPtrT> b = m.IntPtrConstant(100);
TNode<IntPtrT> div = m.IntPtrDiv(a, b);
EXPECT_THAT(div, IsIntPtrDiv(Matcher<Node*>(a), Matcher<Node*>(b)));
}
// x / 1 => x
{
TNode<IntPtrT> a = m.UncheckedCast<IntPtrT>(m.Parameter(0));
TNode<IntPtrT> b = m.IntPtrConstant(1);
TNode<IntPtrT> div = m.IntPtrDiv(a, b);
EXPECT_THAT(div, a);
}
// CONST_a / CONST_b => CONST_c
{
TNode<IntPtrT> a = m.IntPtrConstant(100);
TNode<IntPtrT> b = m.IntPtrConstant(5);
TNode<IntPtrT> div = m.IntPtrDiv(a, b);
EXPECT_THAT(div, IsIntPtrConstant(20));
}
{
TNode<IntPtrT> a = m.IntPtrConstant(100);
TNode<IntPtrT> b = m.IntPtrConstant(5);
TNode<IntPtrT> div = m.IntPtrDiv(a, b);
EXPECT_THAT(div, IsIntPtrConstant(20));
}
// x / 2^CONST => x >> CONST
{
TNode<IntPtrT> a = m.UncheckedCast<IntPtrT>(m.Parameter(0));
TNode<IntPtrT> b = m.IntPtrConstant(1 << 3);
TNode<IntPtrT> div = m.IntPtrDiv(a, b);
EXPECT_THAT(div, IsWordSar(Matcher<Node*>(a), IsIntPtrConstant(3)));
}
}
TARGET_TEST_F(CodeAssemblerTest, WordShl) {
CodeAssemblerTestState state(this);
CodeAssemblerForTest m(&state);
......
......@@ -2152,6 +2152,7 @@ IS_BINOP_MATCHER(Word64Equal)
IS_BINOP_MATCHER(Int32AddWithOverflow)
IS_BINOP_MATCHER(Int32SubWithOverflow)
IS_BINOP_MATCHER(Int32Add)
IS_BINOP_MATCHER(Int32Div)
IS_BINOP_MATCHER(Int32Sub)
IS_BINOP_MATCHER(Int32Mul)
IS_BINOP_MATCHER(Int32MulHigh)
......@@ -2159,6 +2160,7 @@ IS_BINOP_MATCHER(Int32LessThan)
IS_BINOP_MATCHER(Uint32LessThan)
IS_BINOP_MATCHER(Uint32LessThanOrEqual)
IS_BINOP_MATCHER(Int64Add)
IS_BINOP_MATCHER(Int64Div)
IS_BINOP_MATCHER(Int64Sub)
IS_BINOP_MATCHER(Int64Mul)
IS_BINOP_MATCHER(JSAdd)
......
......@@ -387,6 +387,8 @@ Matcher<Node*> IsInt32Add(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsInt32Sub(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsInt32Div(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsInt32Mul(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsInt32MulHigh(const Matcher<Node*>& lhs_matcher,
......@@ -403,6 +405,8 @@ Matcher<Node*> IsInt64Sub(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsInt64Mul(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsInt64Div(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsJSAdd(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsJSParseInt(const Matcher<Node*>& lhs_matcher,
......@@ -517,6 +521,12 @@ static inline Matcher<Node*> IsIntPtrMul(const Matcher<Node*>& lhs_matcher,
: IsInt32Mul(lhs_matcher, rhs_matcher);
}
static inline Matcher<Node*> IsIntPtrDiv(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher) {
return kPointerSize == 8 ? IsInt64Div(lhs_matcher, rhs_matcher)
: IsInt32Div(lhs_matcher, rhs_matcher);
}
static inline Matcher<Node*> IsWordShl(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher) {
return kPointerSize == 8 ? IsWord64Shl(lhs_matcher, rhs_matcher)
......
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