Commit 3b57e96c authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

[bigint] Support BigInts in +,-,*,/,% binary ops.

This CL teaches the respective bytecode handlers and standalone stubs
about BigInts, and collects "kBigInt" feedback for them. However,
Turbofan does not yet care about such feedback, so it is simply converted
to "any" for now (making TF emit stub calls for BigInt operations).

Bug: v8:6791
Change-Id: I6440c108ccd79058d77adc2a6041251db9d5f81d
Reviewed-on: https://chromium-review.googlesource.com/683758Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48173}
parent 3faea676
......@@ -57,7 +57,7 @@ class NumberBuiltinsAssembler : public CodeStubAssembler {
template <typename Descriptor>
void BinaryOp(Label* smis, Variable* var_left, Variable* var_right,
Label* doubles, Variable* var_left_double,
Variable* var_right_double);
Variable* var_right_double, Label* bigints);
};
// ES6 #sec-number.isfinite
......@@ -401,7 +401,8 @@ TF_BUILTIN(Add, AddStubAssembler) {
Variable* loop_vars[2] = {&var_left, &var_right};
Label loop(this, 2, loop_vars),
string_add_convert_left(this, Label::kDeferred),
string_add_convert_right(this, Label::kDeferred);
string_add_convert_right(this, Label::kDeferred),
do_bigint_add(this, Label::kDeferred);
Goto(&loop);
BIND(&loop);
{
......@@ -451,6 +452,7 @@ TF_BUILTIN(Add, AddStubAssembler) {
Node* right_instance_type = LoadMapInstanceType(right_map);
GotoIf(IsStringInstanceType(right_instance_type),
&string_add_convert_left);
GotoIf(IsBigIntInstanceType(right_instance_type), &do_bigint_add);
ConvertAndLoop(&var_right, right_instance_type, &loop, context);
}
} // if_right_heapobject
......@@ -477,6 +479,7 @@ TF_BUILTIN(Add, AddStubAssembler) {
Node* left_instance_type = LoadMapInstanceType(left_map);
GotoIf(IsStringInstanceType(left_instance_type),
&string_add_convert_right);
GotoIf(IsBigIntInstanceType(left_instance_type), &do_bigint_add);
// {left} is neither a Number nor a String, and {right} is a Smi.
ConvertAndLoop(&var_left, left_instance_type, &loop, context);
}
......@@ -504,6 +507,7 @@ TF_BUILTIN(Add, AddStubAssembler) {
Node* right_instance_type = LoadMapInstanceType(right_map);
GotoIf(IsStringInstanceType(right_instance_type),
&string_add_convert_left);
GotoIf(IsBigIntInstanceType(right_instance_type), &do_bigint_add);
// {left} is a HeapNumber, {right} is neither Number nor String.
ConvertAndLoop(&var_right, right_instance_type, &loop, context);
}
......@@ -517,6 +521,8 @@ TF_BUILTIN(Add, AddStubAssembler) {
Node* right_instance_type = LoadMapInstanceType(right_map);
GotoIf(IsStringInstanceType(right_instance_type),
&string_add_convert_left);
GotoIf(IsBigIntInstanceType(left_instance_type), &do_bigint_add);
GotoIf(IsBigIntInstanceType(right_instance_type), &do_bigint_add);
Label if_left_not_receiver(this, Label::kDeferred);
Label if_right_not_receiver(this, Label::kDeferred);
GotoIfNot(IsJSReceiverInstanceType(left_instance_type),
......@@ -554,6 +560,12 @@ TF_BUILTIN(Add, AddStubAssembler) {
Return(CallStub(callable, context, var_left.value(), var_right.value()));
}
BIND(&do_bigint_add);
{
Return(CallRuntime(Runtime::kBigIntBinaryOp, context, var_left.value(),
var_right.value(), SmiConstant(Token::ADD)));
}
BIND(&do_double_add);
{
Node* value = Float64Add(var_left_double.value(), var_right_double.value());
......@@ -565,7 +577,8 @@ template <typename Descriptor>
void NumberBuiltinsAssembler::BinaryOp(Label* smis, Variable* var_left,
Variable* var_right, Label* doubles,
Variable* var_left_double,
Variable* var_right_double) {
Variable* var_right_double,
Label* bigints) {
DCHECK(var_left->rep() == MachineRepresentation::kTagged);
DCHECK(var_right->rep() == MachineRepresentation::kTagged);
......@@ -610,6 +623,8 @@ void NumberBuiltinsAssembler::BinaryOp(Label* smis, Variable* var_left,
BIND(&left_not_number);
{
GotoIf(IsBigInt(var_left->value()), bigints);
// TODO(jkummerow): Here and below, this should call NonNumericToNumeric.
var_left->Bind(
CallBuiltin(Builtins::kNonNumberToNumber, context, var_left->value()));
Goto(&loop);
......@@ -617,6 +632,7 @@ void NumberBuiltinsAssembler::BinaryOp(Label* smis, Variable* var_left,
BIND(&right_not_number);
{
GotoIf(IsBigInt(var_right->value()), bigints);
var_right->Bind(
CallBuiltin(Builtins::kNonNumberToNumber, context, var_right->value()));
Goto(&loop);
......@@ -628,10 +644,10 @@ TF_BUILTIN(Subtract, NumberBuiltinsAssembler) {
VARIABLE(var_right, MachineRepresentation::kTagged);
VARIABLE(var_left_double, MachineRepresentation::kFloat64);
VARIABLE(var_right_double, MachineRepresentation::kFloat64);
Label do_smi_sub(this), do_double_sub(this);
Label do_smi_sub(this), do_double_sub(this), do_bigint_sub(this);
BinaryOp<Descriptor>(&do_smi_sub, &var_left, &var_right, &do_double_sub,
&var_left_double, &var_right_double);
&var_left_double, &var_right_double, &do_bigint_sub);
BIND(&do_smi_sub);
{
......@@ -658,6 +674,13 @@ TF_BUILTIN(Subtract, NumberBuiltinsAssembler) {
Node* value = Float64Sub(var_left_double.value(), var_right_double.value());
Return(AllocateHeapNumberWithValue(value));
}
BIND(&do_bigint_sub);
{
Node* context = Parameter(Descriptor::kContext);
Return(CallRuntime(Runtime::kBigIntBinaryOp, context, var_left.value(),
var_right.value(), SmiConstant(Token::SUB)));
}
}
TF_BUILTIN(Multiply, NumberBuiltinsAssembler) {
......@@ -665,10 +688,10 @@ TF_BUILTIN(Multiply, NumberBuiltinsAssembler) {
VARIABLE(var_right, MachineRepresentation::kTagged);
VARIABLE(var_left_double, MachineRepresentation::kFloat64);
VARIABLE(var_right_double, MachineRepresentation::kFloat64);
Label do_smi_mul(this), do_double_mul(this);
Label do_smi_mul(this), do_double_mul(this), do_bigint_mul(this);
BinaryOp<Descriptor>(&do_smi_mul, &var_left, &var_right, &do_double_mul,
&var_left_double, &var_right_double);
&var_left_double, &var_right_double, &do_bigint_mul);
BIND(&do_smi_mul);
// The result is not necessarily a smi, in case of overflow.
......@@ -677,6 +700,13 @@ TF_BUILTIN(Multiply, NumberBuiltinsAssembler) {
BIND(&do_double_mul);
Node* value = Float64Mul(var_left_double.value(), var_right_double.value());
Return(AllocateHeapNumberWithValue(value));
BIND(&do_bigint_mul);
{
Node* context = Parameter(Descriptor::kContext);
Return(CallRuntime(Runtime::kBigIntBinaryOp, context, var_left.value(),
var_right.value(), SmiConstant(Token::MUL)));
}
}
TF_BUILTIN(Divide, NumberBuiltinsAssembler) {
......@@ -684,10 +714,10 @@ TF_BUILTIN(Divide, NumberBuiltinsAssembler) {
VARIABLE(var_right, MachineRepresentation::kTagged);
VARIABLE(var_left_double, MachineRepresentation::kFloat64);
VARIABLE(var_right_double, MachineRepresentation::kFloat64);
Label do_smi_div(this), do_double_div(this);
Label do_smi_div(this), do_double_div(this), do_bigint_div(this);
BinaryOp<Descriptor>(&do_smi_div, &var_left, &var_right, &do_double_div,
&var_left_double, &var_right_double);
&var_left_double, &var_right_double, &do_bigint_div);
BIND(&do_smi_div);
{
......@@ -754,6 +784,13 @@ TF_BUILTIN(Divide, NumberBuiltinsAssembler) {
Node* value = Float64Div(var_left_double.value(), var_right_double.value());
Return(AllocateHeapNumberWithValue(value));
}
BIND(&do_bigint_div);
{
Node* context = Parameter(Descriptor::kContext);
Return(CallRuntime(Runtime::kBigIntBinaryOp, context, var_left.value(),
var_right.value(), SmiConstant(Token::DIV)));
}
}
TF_BUILTIN(Modulus, NumberBuiltinsAssembler) {
......@@ -761,10 +798,10 @@ TF_BUILTIN(Modulus, NumberBuiltinsAssembler) {
VARIABLE(var_right, MachineRepresentation::kTagged);
VARIABLE(var_left_double, MachineRepresentation::kFloat64);
VARIABLE(var_right_double, MachineRepresentation::kFloat64);
Label do_smi_mod(this), do_double_mod(this);
Label do_smi_mod(this), do_double_mod(this), do_bigint_mod(this);
BinaryOp<Descriptor>(&do_smi_mod, &var_left, &var_right, &do_double_mod,
&var_left_double, &var_right_double);
&var_left_double, &var_right_double, &do_bigint_mod);
BIND(&do_smi_mod);
Return(SmiMod(var_left.value(), var_right.value()));
......@@ -772,6 +809,13 @@ TF_BUILTIN(Modulus, NumberBuiltinsAssembler) {
BIND(&do_double_mod);
Node* value = Float64Mod(var_left_double.value(), var_right_double.value());
Return(AllocateHeapNumberWithValue(value));
BIND(&do_bigint_mod);
{
Node* context = Parameter(Descriptor::kContext);
Return(CallRuntime(Runtime::kBigIntBinaryOp, context, var_left.value(),
var_right.value(), SmiConstant(Token::MOD)));
}
}
TF_BUILTIN(ShiftLeft, NumberBuiltinsAssembler) {
......
......@@ -169,6 +169,9 @@ BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
return BinaryOperationHint::kNumberOrOddball;
case BinaryOperationFeedback::kString:
return BinaryOperationHint::kString;
case BinaryOperationFeedback::kBigInt:
// TODO(jarin/jkummerow/neis): Support BigInts in TF.
// Fall through for now.
case BinaryOperationFeedback::kAny:
default:
return BinaryOperationHint::kAny;
......
......@@ -1256,6 +1256,7 @@ inline uint32_t ObjectHash(Address address) {
// to a more generic type when we combine feedback.
// kSignedSmall -> kSignedSmallInputs -> kNumber -> kNumberOrOddball -> kAny
// kString -> kAny
// kBigInt -> kAny
// TODO(mythria): Remove kNumber type when crankshaft can handle Oddballs
// similar to Numbers. We don't need kNumber feedback for Turbofan. Extra
// information about Number might reduce few instructions but causes more
......@@ -1270,7 +1271,8 @@ class BinaryOperationFeedback {
kNumber = 0x7,
kNumberOrOddball = 0xF,
kString = 0x10,
kAny = 0x3F
kBigInt = 0x20,
kAny = 0x7F
};
};
......
......@@ -19,7 +19,7 @@ Node* BinaryOpAssembler::Generate_AddWithFeedback(Node* context, Node* lhs,
Label do_fadd(this), if_lhsisnotnumber(this, Label::kDeferred),
check_rhsisoddball(this, Label::kDeferred),
call_with_oddball_feedback(this), call_with_any_feedback(this),
call_add_stub(this), end(this);
call_add_stub(this), end(this), bigint(this, Label::kDeferred);
VARIABLE(var_fadd_lhs, MachineRepresentation::kFloat64);
VARIABLE(var_fadd_rhs, MachineRepresentation::kFloat64);
VARIABLE(var_type_feedback, MachineRepresentation::kTaggedSigned);
......@@ -148,10 +148,20 @@ Node* BinaryOpAssembler::Generate_AddWithFeedback(Node* context, Node* lhs,
BIND(&if_lhsisnotoddball);
{
// Exit unless {lhs} is a string
GotoIfNot(IsStringInstanceType(lhs_instance_type),
&call_with_any_feedback);
Label lhs_is_string(this), lhs_is_bigint(this);
GotoIf(IsStringInstanceType(lhs_instance_type), &lhs_is_string);
GotoIf(IsBigIntInstanceType(lhs_instance_type), &lhs_is_bigint);
Goto(&call_with_any_feedback);
BIND(&lhs_is_bigint);
{
// Label "bigint" handles BigInt + {anything except string}.
GotoIf(TaggedIsSmi(rhs), &bigint);
Branch(IsStringInstanceType(LoadInstanceType(rhs)),
&call_with_any_feedback, &bigint);
}
BIND(&lhs_is_string);
// Check if the {rhs} is a smi, and exit the string check early if it is.
GotoIf(TaggedIsSmi(rhs), &call_with_any_feedback);
......@@ -178,10 +188,19 @@ Node* BinaryOpAssembler::Generate_AddWithFeedback(Node* context, Node* lhs,
Node* rhs_instance_type = LoadInstanceType(rhs);
Node* rhs_is_oddball =
Word32Equal(rhs_instance_type, Int32Constant(ODDBALL_TYPE));
Branch(rhs_is_oddball, &call_with_oddball_feedback,
GotoIf(rhs_is_oddball, &call_with_oddball_feedback);
Branch(IsBigIntInstanceType(rhs_instance_type), &bigint,
&call_with_any_feedback);
}
BIND(&bigint);
{
var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kBigInt));
var_result.Bind(CallRuntime(Runtime::kBigIntBinaryOp, context, lhs, rhs,
SmiConstant(Token::ADD)));
Goto(&end);
}
BIND(&call_with_oddball_feedback);
{
var_type_feedback.Bind(
......@@ -212,7 +231,8 @@ Node* BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
Token::Value opcode, bool rhs_is_smi) {
Label do_float_operation(this), end(this), call_stub(this),
check_rhsisoddball(this, Label::kDeferred), call_with_any_feedback(this),
if_lhsisnotnumber(this, Label::kDeferred);
if_lhsisnotnumber(this, Label::kDeferred),
if_bigint(this, Label::kDeferred);
VARIABLE(var_float_lhs, MachineRepresentation::kFloat64);
VARIABLE(var_float_rhs, MachineRepresentation::kFloat64);
VARIABLE(var_type_feedback, MachineRepresentation::kTaggedSigned);
......@@ -282,7 +302,7 @@ Node* BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
}
{
// Perform a floating point subtraction.
// Perform floating point operation.
var_float_lhs.Bind(LoadHeapNumberValue(lhs));
var_float_rhs.Bind(SmiToFloat64(rhs));
Goto(&do_float_operation);
......@@ -304,6 +324,7 @@ Node* BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
// No checks on rhs are done yet. We just know lhs is not a number or Smi.
// Check if lhs is an oddball.
Node* lhs_instance_type = LoadInstanceType(lhs);
GotoIf(IsBigIntInstanceType(lhs_instance_type), &if_bigint);
Node* lhs_is_oddball =
Word32Equal(lhs_instance_type, Int32Constant(ODDBALL_TYPE));
GotoIfNot(lhs_is_oddball, &call_with_any_feedback);
......@@ -334,6 +355,7 @@ Node* BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
// Check if rhs is an oddball. At this point we know lhs is either a
// Smi or number or oddball and rhs is not a number or Smi.
Node* rhs_instance_type = LoadInstanceType(rhs);
GotoIf(IsBigIntInstanceType(rhs_instance_type), &if_bigint);
Node* rhs_is_oddball =
Word32Equal(rhs_instance_type, Int32Constant(ODDBALL_TYPE));
GotoIfNot(rhs_is_oddball, &call_with_any_feedback);
......@@ -343,6 +365,15 @@ Node* BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
Goto(&call_stub);
}
// This handles the case where at least one input is a BigInt.
BIND(&if_bigint);
{
var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kBigInt));
var_result.Bind(CallRuntime(Runtime::kBigIntBinaryOp, context, lhs, rhs,
SmiConstant(opcode)));
Goto(&end);
}
BIND(&call_with_any_feedback);
{
var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
......
......@@ -273,6 +273,8 @@ class ErrorUtils : public AllStatic {
T(AtomicsWaitNotAllowed, "Atomics.wait cannot be called in this context") \
T(BadSortComparisonFunction, \
"The comparison function must be either a function or undefined") \
T(BigIntMixedTypes, \
"Cannot mix BigInt and other types, use explicit conversions") \
T(CalledNonCallable, "% is not a function") \
T(CalledOnNonObject, "% called on non-object") \
T(CalledOnNullOrUndefined, "% called on null or undefined") \
......
......@@ -8,6 +8,7 @@
#include "src/counters.h"
#include "src/objects-inl.h"
#include "src/objects/bigint.h"
#include "src/parsing/token.h"
namespace v8 {
namespace internal {
......@@ -29,5 +30,41 @@ RUNTIME_FUNCTION(Runtime_BigIntToBoolean) {
return *isolate->factory()->ToBoolean(bigint->ToBoolean());
}
RUNTIME_FUNCTION(Runtime_BigIntBinaryOp) {
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, left_obj, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, right_obj, 1);
CONVERT_SMI_ARG_CHECKED(opcode, 2);
if (!left_obj->IsBigInt() || !right_obj->IsBigInt()) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kBigIntMixedTypes));
}
Handle<BigInt> left(Handle<BigInt>::cast(left_obj));
Handle<BigInt> right(Handle<BigInt>::cast(right_obj));
MaybeHandle<BigInt> result;
switch (opcode) {
case Token::ADD:
result = BigInt::Add(left, right);
break;
case Token::SUB:
result = BigInt::Subtract(left, right);
break;
case Token::MUL:
result = BigInt::Multiply(left, right);
break;
case Token::DIV:
result = BigInt::Divide(left, right);
break;
case Token::MOD:
result = BigInt::Remainder(left, right);
break;
default:
UNREACHABLE();
}
RETURN_RESULT_OR_FAILURE(isolate, result);
}
} // namespace internal
} // namespace v8
......@@ -70,7 +70,8 @@ namespace internal {
#define FOR_EACH_INTRINSIC_BIGINT(F) \
F(BigIntEqual, 2, 1) \
F(BigIntToBoolean, 1, 1)
F(BigIntToBoolean, 1, 1) \
F(BigIntBinaryOp, 3, 1)
#define FOR_EACH_INTRINSIC_CLASSES(F) \
F(ThrowUnsupportedSuperError, 0, 1) \
......
......@@ -428,7 +428,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(135),
B(Wide), B(LdaSmi), I16(136),
B(Star), R(18),
B(LdaConstant), U8(16),
B(Star), R(19),
......
......@@ -143,7 +143,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(135),
B(Wide), B(LdaSmi), I16(136),
B(Star), R(19),
B(LdaConstant), U8(13),
B(Star), R(20),
......@@ -432,7 +432,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(135),
B(Wide), B(LdaSmi), I16(136),
B(Star), R(19),
B(LdaConstant), U8(13),
B(Star), R(20),
......@@ -743,7 +743,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(135),
B(Wide), B(LdaSmi), I16(136),
B(Star), R(19),
B(LdaConstant), U8(13),
B(Star), R(20),
......@@ -991,7 +991,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(135),
B(Wide), B(LdaSmi), I16(136),
B(Star), R(16),
B(LdaConstant), U8(10),
B(Star), R(17),
......
......@@ -86,7 +86,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(135),
B(Wide), B(LdaSmi), I16(136),
B(Star), R(11),
B(LdaConstant), U8(8),
B(Star), R(12),
......@@ -227,7 +227,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(135),
B(Wide), B(LdaSmi), I16(136),
B(Star), R(12),
B(LdaConstant), U8(8),
B(Star), R(13),
......@@ -380,7 +380,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(135),
B(Wide), B(LdaSmi), I16(136),
B(Star), R(11),
B(LdaConstant), U8(8),
B(Star), R(12),
......@@ -523,7 +523,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(135),
B(Wide), B(LdaSmi), I16(136),
B(Star), R(10),
B(LdaConstant), U8(10),
B(Star), R(11),
......
......@@ -90,7 +90,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(135),
B(Wide), B(LdaSmi), I16(136),
B(Star), R(13),
B(LdaConstant), U8(7),
B(Star), R(14),
......@@ -268,7 +268,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(135),
B(Wide), B(LdaSmi), I16(136),
B(Star), R(13),
B(LdaConstant), U8(11),
B(Star), R(14),
......@@ -422,7 +422,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(135),
B(Wide), B(LdaSmi), I16(136),
B(Star), R(11),
B(LdaConstant), U8(9),
B(Star), R(12),
......@@ -524,7 +524,7 @@ bytecodes: [
B(JumpIfUndefined), U8(6),
B(Ldar), R(6),
B(JumpIfNotNull), U8(16),
B(LdaSmi), I8(64),
B(LdaSmi), I8(65),
B(Star), R(17),
B(LdaConstant), U8(4),
B(Star), R(18),
......@@ -580,7 +580,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(135),
B(Wide), B(LdaSmi), I16(136),
B(Star), R(16),
B(LdaConstant), U8(9),
B(Star), R(17),
......@@ -754,7 +754,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(135),
B(Wide), B(LdaSmi), I16(136),
B(Star), R(16),
B(LdaConstant), U8(10),
B(Star), R(17),
......@@ -953,7 +953,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(135),
B(Wide), B(LdaSmi), I16(136),
B(Star), R(15),
B(LdaConstant), U8(14),
B(Star), R(16),
......@@ -1116,7 +1116,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(135),
B(Wide), B(LdaSmi), I16(136),
B(Star), R(20),
B(LdaConstant), U8(7),
B(Star), R(21),
......@@ -1358,7 +1358,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(135),
B(Wide), B(LdaSmi), I16(136),
B(Star), R(20),
B(LdaConstant), U8(9),
B(Star), R(21),
......
......@@ -257,7 +257,7 @@ bytecodes: [
B(TestTypeOf), U8(5),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(135),
B(Wide), B(LdaSmi), I16(136),
B(Star), R(14),
B(LdaConstant), U8(15),
B(Star), R(15),
......
......@@ -231,7 +231,7 @@ bytecodes: [
B(JumpIfUndefined), U8(6),
B(Ldar), R(3),
B(JumpIfNotNull), U8(16),
B(LdaSmi), I8(64),
B(LdaSmi), I8(65),
B(Star), R(4),
B(LdaConstant), U8(1),
B(Star), R(5),
......
......@@ -10,6 +10,9 @@ const zero = BigInt(0);
const another_zero = BigInt(0);
const one = BigInt(1);
const another_one = BigInt(1);
const two = BigInt(2);
const three = BigInt(3);
const six = BigInt(6);
// BigInt
{
......@@ -143,3 +146,44 @@ const another_one = BigInt(1);
assertTrue(new Map([[one, 42]]).has(one));
assertTrue(new Map([[one, 42]]).has(another_one));
}
// Binary ops.
{
assertTrue(one + two === three);
assertEquals("hello1", "hello" + one);
assertEquals("2hello", two + "hello");
assertThrows("one + 2", TypeError);
assertThrows("2 + one", TypeError);
assertThrows("one + 0.5", TypeError);
assertThrows("0.5 + one", TypeError);
assertThrows("one + null", TypeError);
assertThrows("null + one", TypeError);
assertTrue(three - two === one);
assertThrows("two - 1", TypeError);
assertThrows("2 - one", TypeError);
assertThrows("two - 0.5", TypeError);
assertThrows("2.5 - one", TypeError);
assertTrue(two * three === six);
assertThrows("two * 1", TypeError);
assertThrows("1 * two", TypeError);
assertThrows("two * 1.5", TypeError);
assertThrows("1.5 * two", TypeError);
assertTrue(six / three === two);
assertThrows("six / 3", TypeError);
assertThrows("3 / three", TypeError);
assertThrows("six / 0.5", TypeError);
assertThrows("0.5 / six", TypeError);
assertThrows("zero / zero", RangeError);
assertThrows("zero / 0", TypeError);
assertTrue(three % two === one);
assertThrows("three % 2", TypeError);
assertThrows("3 % two", TypeError);
assertThrows("three % 2.5", TypeError);
assertThrows("3.5 % two", TypeError);
assertThrows("three % zero", RangeError);
assertThrows("three % 0", TypeError);
}
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