summaryrefslogtreecommitdiff
path: root/deps/v8/src/ic/binary-op-assembler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/ic/binary-op-assembler.cc')
-rw-r--r--deps/v8/src/ic/binary-op-assembler.cc253
1 files changed, 198 insertions, 55 deletions
diff --git a/deps/v8/src/ic/binary-op-assembler.cc b/deps/v8/src/ic/binary-op-assembler.cc
index c364503311..a1dfbe49d8 100644
--- a/deps/v8/src/ic/binary-op-assembler.cc
+++ b/deps/v8/src/ic/binary-op-assembler.cc
@@ -9,6 +9,16 @@
namespace v8 {
namespace internal {
+namespace {
+
+inline bool IsBigInt64OpSupported(BinaryOpAssembler* assembler, Operation op) {
+ return assembler->Is64() && op != Operation::kExponentiate &&
+ op != Operation::kShiftLeft && op != Operation::kShiftRight &&
+ op != Operation::kShiftRightLogical;
+}
+
+} // namespace
+
TNode<Object> BinaryOpAssembler::Generate_AddWithFeedback(
const LazyNode<Context>& context, TNode<Object> lhs, TNode<Object> rhs,
TNode<UintPtrT> slot_id, const LazyNode<HeapObject>& maybe_feedback_vector,
@@ -412,7 +422,7 @@ TNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
{
GotoIf(TaggedIsSmi(rhs), &call_with_any_feedback);
GotoIfNot(IsBigInt(CAST(rhs)), &call_with_any_feedback);
- if (Is64()) {
+ if (IsBigInt64OpSupported(this, op)) {
GotoIfLargeBigInt(CAST(lhs), &if_both_bigint);
GotoIfLargeBigInt(CAST(rhs), &if_both_bigint);
Goto(&if_both_bigint64);
@@ -435,7 +445,7 @@ TNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
Goto(&call_stub);
}
- if (Is64()) {
+ if (IsBigInt64OpSupported(this, op)) {
BIND(&if_both_bigint64);
var_type_feedback = SmiConstant(BinaryOperationFeedback::kBigInt64);
UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector(), slot_id,
@@ -497,10 +507,6 @@ TNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
}
break;
}
- case Operation::kExponentiate: {
- Goto(&if_both_bigint);
- break;
- }
default:
UNREACHABLE();
}
@@ -513,7 +519,6 @@ TNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
update_feedback_mode);
switch (op) {
case Operation::kSubtract: {
- Label bigint_too_big(this);
var_result =
CallBuiltin(Builtin::kBigIntSubtractNoThrow, context(), lhs, rhs);
@@ -527,8 +532,7 @@ TNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
break;
}
case Operation::kMultiply: {
- Label bigint_too_big(this),
- termination_requested(this, Label::kDeferred);
+ Label termination_requested(this, Label::kDeferred);
var_result =
CallBuiltin(Builtin::kBigIntMultiplyNoThrow, context(), lhs, rhs);
@@ -549,8 +553,7 @@ TNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
break;
}
case Operation::kDivide: {
- Label bigint_div_zero(this),
- termination_requested(this, Label::kDeferred);
+ Label termination_requested(this, Label::kDeferred);
var_result =
CallBuiltin(Builtin::kBigIntDivideNoThrow, context(), lhs, rhs);
@@ -571,8 +574,7 @@ TNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
break;
}
case Operation::kModulus: {
- Label bigint_div_zero(this),
- termination_requested(this, Label::kDeferred);
+ Label termination_requested(this, Label::kDeferred);
var_result =
CallBuiltin(Builtin::kBigIntModulusNoThrow, context(), lhs, rhs);
@@ -787,35 +789,30 @@ TNode<Object> BinaryOpAssembler::Generate_BitwiseBinaryOpWithOptionalFeedback(
TVARIABLE(Word32T, var_left_word32);
TVARIABLE(Word32T, var_right_word32);
TVARIABLE(BigInt, var_left_bigint);
- TVARIABLE(BigInt, var_right_bigint);
- // These are the variables that are passed to BigIntBinaryOp. They are not
- // guaranteed to be BigInts because the Runtime call handles throwing
- // exceptions when only one side is a BigInt.
- TVARIABLE(Object, var_left_maybe_bigint, left);
- TVARIABLE(Numeric, var_right_maybe_bigint);
Label done(this);
Label if_left_number(this), do_number_op(this);
- Label if_left_bigint(this), do_bigint_op(this);
+ Label if_left_bigint(this), if_left_bigint64(this);
+ Label if_left_number_right_bigint(this, Label::kDeferred);
TaggedToWord32OrBigIntWithFeedback(
context(), left, &if_left_number, &var_left_word32, &if_left_bigint,
+ IsBigInt64OpSupported(this, bitwise_op) ? &if_left_bigint64 : nullptr,
&var_left_bigint, slot ? &var_left_feedback : nullptr);
- Label right_is_bigint(this);
BIND(&if_left_number);
- {
- TaggedToWord32OrBigIntWithFeedback(
- context(), right, &do_number_op, &var_right_word32, &right_is_bigint,
- &var_right_bigint, slot ? &var_right_feedback : nullptr);
- }
+ TaggedToWord32OrBigIntWithFeedback(
+ context(), right, &do_number_op, &var_right_word32,
+ &if_left_number_right_bigint, nullptr, nullptr,
+ slot ? &var_right_feedback : nullptr);
- BIND(&right_is_bigint);
+ BIND(&if_left_number_right_bigint);
{
- // At this point it's guaranteed that the op will fail because the RHS is a
- // BigInt while the LHS is not, but that's ok because the Runtime call will
- // throw the exception.
- var_right_maybe_bigint = var_right_bigint.value();
- Goto(&do_bigint_op);
+ if (slot) {
+ // Ensure that the feedback is updated before we throw.
+ UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny),
+ (*maybe_feedback_vector)(), *slot, update_feedback_mode);
+ }
+ ThrowTypeError(context(), MessageTemplate::kBigIntMixedTypes);
}
BIND(&do_number_op);
@@ -837,29 +834,176 @@ TNode<Object> BinaryOpAssembler::Generate_BitwiseBinaryOpWithOptionalFeedback(
}
// BigInt cases.
- BIND(&if_left_bigint);
{
- TaggedToNumericWithFeedback(context(), right, &var_right_maybe_bigint,
- &var_right_feedback);
- var_left_maybe_bigint = var_left_bigint.value();
- Goto(&do_bigint_op);
- }
+ TVARIABLE(BigInt, var_right_bigint);
+ Label if_both_bigint(this), if_both_bigint64(this);
+ Label if_bigint_mix(this, Label::kDeferred);
- BIND(&do_bigint_op);
- {
- if (slot) {
- // Ensure that the feedback is updated even if the runtime call below
- // would throw.
- TNode<Smi> feedback =
- SmiOr(var_left_feedback.value(), var_right_feedback.value());
- UpdateFeedback(feedback, (*maybe_feedback_vector)(), *slot,
- update_feedback_mode);
+ BIND(&if_left_bigint);
+ TaggedToBigInt(context(), right, &if_bigint_mix, &if_both_bigint, nullptr,
+ &var_right_bigint, slot ? &var_right_feedback : nullptr);
+
+ if (IsBigInt64OpSupported(this, bitwise_op)) {
+ BIND(&if_left_bigint64);
+ TaggedToBigInt(context(), right, &if_bigint_mix, &if_both_bigint,
+ &if_both_bigint64, &var_right_bigint,
+ slot ? &var_right_feedback : nullptr);
+
+ BIND(&if_both_bigint64);
+ if (slot) {
+ // {feedback} is Any if {left} or {right} is non-number.
+ TNode<Smi> feedback =
+ SmiOr(var_left_feedback.value(), var_right_feedback.value());
+ UpdateFeedback(feedback, (*maybe_feedback_vector)(), *slot,
+ update_feedback_mode);
+ }
+
+ TVARIABLE(UintPtrT, left_raw);
+ TVARIABLE(UintPtrT, right_raw);
+ BigIntToRawBytes(var_left_bigint.value(), &left_raw, &left_raw);
+ BigIntToRawBytes(var_right_bigint.value(), &right_raw, &right_raw);
+
+ switch (bitwise_op) {
+ case Operation::kBitwiseAnd: {
+ result = BigIntFromInt64(UncheckedCast<IntPtrT>(
+ WordAnd(left_raw.value(), right_raw.value())));
+ Goto(&done);
+ break;
+ }
+ case Operation::kBitwiseOr: {
+ result = BigIntFromInt64(UncheckedCast<IntPtrT>(
+ WordOr(left_raw.value(), right_raw.value())));
+ Goto(&done);
+ break;
+ }
+ case Operation::kBitwiseXor: {
+ result = BigIntFromInt64(UncheckedCast<IntPtrT>(
+ WordXor(left_raw.value(), right_raw.value())));
+ Goto(&done);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
}
- result = CallRuntime(
- Runtime::kBigIntBinaryOp, context(), var_left_maybe_bigint.value(),
- var_right_maybe_bigint.value(), SmiConstant(bitwise_op));
- Goto(&done);
+ BIND(&if_both_bigint);
+ {
+ if (slot) {
+ // Ensure that the feedback is updated even if the runtime call below
+ // would throw.
+ TNode<Smi> feedback =
+ SmiOr(var_left_feedback.value(), var_right_feedback.value());
+ UpdateFeedback(feedback, (*maybe_feedback_vector)(), *slot,
+ update_feedback_mode);
+ }
+
+ switch (bitwise_op) {
+ case Operation::kBitwiseAnd: {
+ result =
+ CallBuiltin(Builtin::kBigIntBitwiseAndNoThrow, context(),
+ var_left_bigint.value(), var_right_bigint.value());
+ // Check for sentinel that signals BigIntTooBig exception.
+ GotoIfNot(TaggedIsSmi(result.value()), &done);
+
+ if (slot) {
+ // Update feedback to prevent deopt loop.
+ UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny),
+ (*maybe_feedback_vector)(), *slot,
+ update_feedback_mode);
+ }
+ ThrowRangeError(context(), MessageTemplate::kBigIntTooBig);
+ break;
+ }
+ case Operation::kBitwiseOr: {
+ result =
+ CallBuiltin(Builtin::kBigIntBitwiseOrNoThrow, context(),
+ var_left_bigint.value(), var_right_bigint.value());
+ // Check for sentinel that signals BigIntTooBig exception.
+ GotoIfNot(TaggedIsSmi(result.value()), &done);
+
+ if (slot) {
+ // Update feedback to prevent deopt loop.
+ UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny),
+ (*maybe_feedback_vector)(), *slot,
+ update_feedback_mode);
+ }
+ ThrowRangeError(context(), MessageTemplate::kBigIntTooBig);
+ break;
+ }
+ case Operation::kBitwiseXor: {
+ result =
+ CallBuiltin(Builtin::kBigIntBitwiseXorNoThrow, context(),
+ var_left_bigint.value(), var_right_bigint.value());
+ // Check for sentinel that signals BigIntTooBig exception.
+ GotoIfNot(TaggedIsSmi(result.value()), &done);
+
+ if (slot) {
+ // Update feedback to prevent deopt loop.
+ UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny),
+ (*maybe_feedback_vector)(), *slot,
+ update_feedback_mode);
+ }
+ ThrowRangeError(context(), MessageTemplate::kBigIntTooBig);
+ break;
+ }
+ case Operation::kShiftLeft: {
+ result =
+ CallBuiltin(Builtin::kBigIntShiftLeftNoThrow, context(),
+ var_left_bigint.value(), var_right_bigint.value());
+ // Check for sentinel that signals BigIntTooBig exception.
+ GotoIfNot(TaggedIsSmi(result.value()), &done);
+
+ if (slot) {
+ // Update feedback to prevent deopt loop.
+ UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny),
+ (*maybe_feedback_vector)(), *slot,
+ update_feedback_mode);
+ }
+ ThrowRangeError(context(), MessageTemplate::kBigIntTooBig);
+ break;
+ }
+ case Operation::kShiftRight: {
+ result =
+ CallBuiltin(Builtin::kBigIntShiftRightNoThrow, context(),
+ var_left_bigint.value(), var_right_bigint.value());
+ // Check for sentinel that signals BigIntTooBig exception.
+ GotoIfNot(TaggedIsSmi(result.value()), &done);
+
+ if (slot) {
+ // Update feedback to prevent deopt loop.
+ UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny),
+ (*maybe_feedback_vector)(), *slot,
+ update_feedback_mode);
+ }
+ ThrowRangeError(context(), MessageTemplate::kBigIntTooBig);
+ break;
+ }
+ case Operation::kShiftRightLogical: {
+ if (slot) {
+ // Ensure that the feedback is updated before we throw.
+ UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny),
+ (*maybe_feedback_vector)(), *slot,
+ update_feedback_mode);
+ }
+ // BigInt does not support logical right shift.
+ ThrowTypeError(context(), MessageTemplate::kBigIntShr);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ BIND(&if_bigint_mix);
+ {
+ if (slot) {
+ // Ensure that the feedback is updated before we throw.
+ UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny),
+ (*maybe_feedback_vector)(), *slot, update_feedback_mode);
+ }
+ ThrowTypeError(context(), MessageTemplate::kBigIntMixedTypes);
+ }
}
BIND(&done);
@@ -905,7 +1049,7 @@ BinaryOpAssembler::Generate_BitwiseBinaryOpWithSmiOperandAndOptionalFeedback(
TNode<HeapObject> left_pointer = CAST(left);
TaggedPointerToWord32OrBigIntWithFeedback(
context(), left_pointer, &do_number_op, &var_left_word32,
- &if_bigint_mix, &var_left_bigint, &var_left_feedback);
+ &if_bigint_mix, nullptr, &var_left_bigint, &var_left_feedback);
BIND(&do_number_op);
{
result =
@@ -923,9 +1067,8 @@ BinaryOpAssembler::Generate_BitwiseBinaryOpWithSmiOperandAndOptionalFeedback(
{
if (slot) {
// Ensure that the feedback is updated before we throw.
- feedback = var_left_feedback.value();
- UpdateFeedback(feedback.value(), (*maybe_feedback_vector)(), *slot,
- update_feedback_mode);
+ UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny),
+ (*maybe_feedback_vector)(), *slot, update_feedback_mode);
}
ThrowTypeError(context(), MessageTemplate::kBigIntMixedTypes);
}