diff options
Diffstat (limited to 'deps/v8/src/ic/binary-op-assembler.cc')
-rw-r--r-- | deps/v8/src/ic/binary-op-assembler.cc | 253 |
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); } |