!2656 Lower number/int/double mod/shl/shr/ashr with constant check

Merge pull request !2656 from 吴璋达/ashr
This commit is contained in:
openharmony_ci 2022-10-26 04:25:12 +00:00 committed by Gitee
commit 1334d2886d
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
11 changed files with 478 additions and 5 deletions

View File

@ -759,6 +759,7 @@ BytecodeInfo BytecodeCircuitBuilder::GetBytecodeInfo(const uint8_t *pc)
case EcmaOpcode::MOD2_IMM8_V8: {
uint16_t v0 = READ_INST_8_1();
info.inputs.emplace_back(VirtualRegister(v0));
info.deopt = true;
break;
}
case EcmaOpcode::EQ_IMM8_V8: {
@ -800,16 +801,19 @@ BytecodeInfo BytecodeCircuitBuilder::GetBytecodeInfo(const uint8_t *pc)
case EcmaOpcode::SHL2_IMM8_V8: {
uint16_t v0 = READ_INST_8_1();
info.inputs.emplace_back(VirtualRegister(v0));
info.deopt = true;
break;
}
case EcmaOpcode::SHR2_IMM8_V8: {
uint16_t v0 = READ_INST_8_1();
info.inputs.emplace_back(VirtualRegister(v0));
info.deopt = true;
break;
}
case EcmaOpcode::ASHR2_IMM8_V8: {
uint16_t v0 = READ_INST_8_1();
info.inputs.emplace_back(VirtualRegister(v0));
info.deopt = true;
break;
}
case EcmaOpcode::AND2_IMM8_V8: {

View File

@ -1110,6 +1110,21 @@ DEF_CALL_SIGNATURE(InsertOldToNewRSet)
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
}
DEF_CALL_SIGNATURE(AotFloatMod)
{
// 2 : 2 input parameters
CallSignature index("AotFloatMod", 0, 2, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
*callSign = index;
// 2 : 2 input parameters
std::array<VariableType, 2> params = {
VariableType::FLOAT64(),
VariableType::FLOAT64(),
};
callSign->SetParameters(params.data());
callSign->SetGCLeafFunction(false);
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
}
DEF_CALL_SIGNATURE(FloatMod)
{
// 2 : 2 input parameters

View File

@ -369,6 +369,7 @@ private:
V(FatalPrint) \
V(InsertOldToNewRSet) \
V(DoubleToInt) \
V(AotFloatMod) \
V(FloatMod) \
V(FindElementWithCache) \
V(MarkingBarrier) \

View File

@ -94,6 +94,7 @@ void TSTypeLowering::Lower(GateRef gate)
LowerTypedDiv(gate);
break;
case EcmaOpcode::MOD2_IMM8_V8:
LowerTypedMod(gate);
break;
case EcmaOpcode::LESS_IMM8_V8:
LowerTypedLess(gate);
@ -114,13 +115,13 @@ void TSTypeLowering::Lower(GateRef gate)
LowerTypedNotEq(gate);
break;
case EcmaOpcode::SHL2_IMM8_V8:
// lower JS_SHL
LowerTypedShl(gate);
break;
case EcmaOpcode::SHR2_IMM8_V8:
// lower JS_SHR
LowerTypedShr(gate);
break;
case EcmaOpcode::ASHR2_IMM8_V8:
// lower JS_ASHR
LowerTypedAshr(gate);
break;
case EcmaOpcode::AND2_IMM8_V8:
// lower JS_AND
@ -388,6 +389,45 @@ void TSTypeLowering::LowerTypedNotEq(GateRef gate)
}
}
void TSTypeLowering::LowerTypedShl(GateRef gate)
{
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
GateType leftType = acc_.GetGateType(left);
GateType rightType = acc_.GetGateType(right);
if (leftType.IsNumberType() && rightType.IsNumberType()) {
SpeculateNumbers<TypedBinOp::TYPED_SHL>(gate);
} else {
acc_.DeleteGuardAndFrameState(gate);
}
}
void TSTypeLowering::LowerTypedShr(GateRef gate)
{
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
GateType leftType = acc_.GetGateType(left);
GateType rightType = acc_.GetGateType(right);
if (leftType.IsNumberType() && rightType.IsNumberType()) {
SpeculateNumbers<TypedBinOp::TYPED_SHR>(gate);
} else {
acc_.DeleteGuardAndFrameState(gate);
}
}
void TSTypeLowering::LowerTypedAshr(GateRef gate)
{
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
GateType leftType = acc_.GetGateType(left);
GateType rightType = acc_.GetGateType(right);
if (leftType.IsNumberType() && rightType.IsNumberType()) {
SpeculateNumbers<TypedBinOp::TYPED_ASHR>(gate);
} else {
acc_.DeleteGuardAndFrameState(gate);
}
}
void TSTypeLowering::LowerTypedInc(GateRef gate)
{
GateRef value = acc_.GetValueIn(gate, 0);

View File

@ -59,6 +59,9 @@ private:
void LowerTypedDiv(GateRef gate);
void LowerTypedEq(GateRef gate);
void LowerTypedNotEq(GateRef gate);
void LowerTypedShl(GateRef gate);
void LowerTypedShr(GateRef gate);
void LowerTypedAshr(GateRef gate);
void LowerTypedInc(GateRef gate);
void LowerTypedDec(GateRef gate);
void LowerTypeToNumeric(GateRef gate);

View File

@ -189,6 +189,18 @@ void TypeLowering::LowerTypedBinaryOp(GateRef gate)
LowerTypedNotEq(gate);
break;
}
case TypedBinOp::TYPED_SHL: {
LowerTypedShl(gate);
break;
}
case TypedBinOp::TYPED_SHR: {
LowerTypedShr(gate);
break;
}
case TypedBinOp::TYPED_ASHR: {
LowerTypedAshr(gate);
break;
}
default:
break;
}
@ -257,8 +269,14 @@ void TypeLowering::LowerTypedMul(GateRef gate)
void TypeLowering::LowerTypedMod(GateRef gate)
{
gate++;
UNREACHABLE();
auto leftType = acc_.GetLeftType(gate);
auto rightType = acc_.GetRightType(gate);
if (leftType.IsNumberType() && rightType.IsNumberType()) {
LowerNumberMod(gate);
} else {
UNREACHABLE();
}
return;
}
void TypeLowering::LowerTypedLess(GateRef gate)
@ -345,6 +363,42 @@ void TypeLowering::LowerTypedNotEq(GateRef gate)
return;
}
void TypeLowering::LowerTypedShl(GateRef gate)
{
auto leftType = acc_.GetLeftType(gate);
auto rightType = acc_.GetRightType(gate);
if (leftType.IsNumberType() && rightType.IsNumberType()) {
LowerNumberShl(gate);
} else {
UNREACHABLE();
}
return;
}
void TypeLowering::LowerTypedShr(GateRef gate)
{
auto leftType = acc_.GetLeftType(gate);
auto rightType = acc_.GetRightType(gate);
if (leftType.IsNumberType() && rightType.IsNumberType()) {
LowerNumberShr(gate);
} else {
UNREACHABLE();
}
return;
}
void TypeLowering::LowerTypedAshr(GateRef gate)
{
auto leftType = acc_.GetLeftType(gate);
auto rightType = acc_.GetRightType(gate);
if (leftType.IsNumberType() && rightType.IsNumberType()) {
LowerNumberAshr(gate);
} else {
UNREACHABLE();
}
return;
}
void TypeLowering::LowerTypedInc(GateRef gate)
{
auto value = acc_.GetLeftType(gate);
@ -411,6 +465,17 @@ void TypeLowering::LowerNumberMul(GateRef gate)
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::LowerNumberMod(GateRef gate)
{
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
GateType leftType = acc_.GetLeftType(gate);
GateType rightType = acc_.GetRightType(gate);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
result = ModNumbers(left, right, leftType, rightType);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::LowerNumberLess(GateRef gate)
{
GateRef left = acc_.GetValueIn(gate, 0);
@ -488,6 +553,39 @@ void TypeLowering::LowerNumberNotEq(GateRef gate)
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::LowerNumberShl(GateRef gate)
{
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
GateType leftType = acc_.GetLeftType(gate);
GateType rightType = acc_.GetRightType(gate);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
result = ShiftNumber<OpCode::LSL>(left, right, leftType, rightType);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::LowerNumberShr(GateRef gate)
{
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
GateType leftType = acc_.GetLeftType(gate);
GateType rightType = acc_.GetRightType(gate);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
result = ShiftNumber<OpCode::LSR>(left, right, leftType, rightType);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::LowerNumberAshr(GateRef gate)
{
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
GateType leftType = acc_.GetLeftType(gate);
GateType rightType = acc_.GetRightType(gate);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
result = ShiftNumber<OpCode::ASR>(left, right, leftType, rightType);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::LowerNumberInc(GateRef gate)
{
GateRef value = acc_.GetValueIn(gate, 0);
@ -636,6 +734,115 @@ GateRef TypeLowering::CalculateNumbers(GateRef left, GateRef right, GateType lef
return ret;
}
template<OpCode::Op Op>
GateRef TypeLowering::ShiftNumber(GateRef left, GateRef right, GateType leftType, GateType rightType)
{
auto env = builder_.GetCurrentEnvironment();
Label entry(&builder_);
env->SubCfgEntry(&entry);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
DEFVAlUE(intLeft, (&builder_), VariableType::INT32(), builder_.Int32(0));
DEFVAlUE(intRight, (&builder_), VariableType::INT32(), builder_.Int32(0));
Label exit(&builder_);
Label doIntOp(&builder_);
Label leftIsIntRightIsInt(&builder_);
Label leftIsIntRightIsDouble(&builder_);
Label rightIsInt(&builder_);
Label rightIsDouble(&builder_);
Label leftIsInt(&builder_);
Label leftIsDouble(&builder_);
auto LowerIntOpInt = [&]() -> void {
intLeft = builder_.GetInt32OfTInt(left);
intRight = builder_.GetInt32OfTInt(right);
builder_.Jump(&doIntOp);
};
auto LowerDoubleOpInt = [&]() -> void {
intLeft = TruncDoubleToInt(builder_.GetDoubleOfTDouble(left));
intRight = builder_.GetInt32OfTInt(right);
builder_.Jump(&doIntOp);
};
auto LowerIntOpDouble = [&]() -> void {
intLeft = builder_.GetInt32OfTInt(left);
intRight = TruncDoubleToInt(builder_.GetDoubleOfTDouble(right));
builder_.Jump(&doIntOp);
};
auto LowerDoubleOpDouble = [&]() -> void {
intLeft = TruncDoubleToInt(builder_.GetDoubleOfTDouble(left));
intRight = TruncDoubleToInt(builder_.GetDoubleOfTDouble(right));
builder_.Jump(&doIntOp);
};
auto LowerRightWhenLeftIsInt = [&]() -> void {
if (rightType.IsIntType()) {
LowerIntOpInt();
} else if (rightType.IsDoubleType()) {
LowerIntOpDouble();
} else {
builder_.Branch(builder_.TaggedIsInt(right), &leftIsIntRightIsInt, &leftIsIntRightIsDouble);
builder_.Bind(&leftIsIntRightIsInt);
LowerIntOpInt();
builder_.Bind(&leftIsIntRightIsDouble);
LowerIntOpDouble();
}
};
auto LowerRightWhenLeftIsDouble = [&]() -> void {
if (rightType.IsIntType()) {
LowerDoubleOpInt();
} else if (rightType.IsDoubleType()) {
LowerDoubleOpDouble();
} else {
builder_.Branch(builder_.TaggedIsInt(right), &rightIsInt, &rightIsDouble);
builder_.Bind(&rightIsInt);
LowerDoubleOpInt();
builder_.Bind(&rightIsDouble);
LowerDoubleOpDouble();
}
};
if (leftType.IsIntType()) {
// left is int
LowerRightWhenLeftIsInt();
} else if (leftType.IsDoubleType()) {
// left is double
LowerRightWhenLeftIsDouble();
} else {
// left is number and need typecheck in runtime
builder_.Branch(builder_.TaggedIsInt(left), &leftIsInt, &leftIsDouble);
builder_.Bind(&leftIsInt);
LowerRightWhenLeftIsInt();
builder_.Bind(&leftIsDouble);
LowerRightWhenLeftIsDouble();
}
builder_.Bind(&doIntOp);
{
GateRef res = Circuit::NullGate();
GateRef shift = builder_.Int32And(*intRight, builder_.Int32(0x1f));
switch (Op) {
case OpCode::LSL: {
res = builder_.Int32LSL(*intLeft, shift);
break;
}
case OpCode::LSR: {
res = builder_.Int32LSR(*intLeft, shift);
break;
}
case OpCode::ASR: {
res = builder_.Int32ASR(*intLeft, shift);
break;
}
default:
break;
}
result = IntToTaggedIntPtr(res);
builder_.Jump(&exit);
}
builder_.Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
template<OpCode::Op Op>
GateRef TypeLowering::FastAddOrSubOrMul(GateRef left, GateRef right)
{
@ -1080,6 +1287,11 @@ GateRef TypeLowering::ChangeInt32ToFloat64(GateRef gate)
return builder_.ChangeInt32ToFloat64(gate);
}
GateRef TypeLowering::TruncDoubleToInt(GateRef gate)
{
return builder_.ChangeInt64ToInt32(builder_.TruncFloatToInt64(gate));
}
GateRef TypeLowering::Int32Mod(GateRef left, GateRef right)
{
return BinaryOp<OpCode::SMOD, MachineType::I32>(left, right);
@ -1387,6 +1599,166 @@ GateRef TypeLowering::FastDiv(GateRef left, GateRef right)
return ret;
}
GateRef TypeLowering::ModNumbers(GateRef left, GateRef right, GateType leftType, GateType rightType)
{
auto env = builder_.GetCurrentEnvironment();
Label entry(&builder_);
env->SubCfgEntry(&entry);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
DEFVAlUE(intLeft, (&builder_), VariableType::INT32(), builder_.Int32(0));
DEFVAlUE(intRight, (&builder_), VariableType::INT32(), builder_.Int32(0));
DEFVAlUE(doubleLeft, (&builder_), VariableType::FLOAT64(), builder_.Double(0));
DEFVAlUE(doubleRight, (&builder_), VariableType::FLOAT64(), builder_.Double(0));
Label exit(&builder_);
Label doFloatOp(&builder_);
Label doIntOp(&builder_);
Label leftIsIntRightIsDouble(&builder_);
Label rightIsInt(&builder_);
Label rightIsDouble(&builder_);
Label leftIsInt(&builder_);
Label leftIsDouble(&builder_);
bool intOptAccessed = false;
auto LowerIntOpInt = [&]() -> void {
builder_.Jump(&doIntOp);
intOptAccessed = true;
};
auto LowerDoubleOpInt = [&]() -> void {
doubleLeft = builder_.GetDoubleOfTDouble(left);
doubleRight = ChangeInt32ToFloat64(builder_.GetInt32OfTInt(right));
builder_.Jump(&doFloatOp);
};
auto LowerIntOpDouble = [&]() -> void {
doubleLeft = ChangeInt32ToFloat64(builder_.GetInt32OfTInt(left));
doubleRight = builder_.GetDoubleOfTDouble(right);
builder_.Jump(&doFloatOp);
};
auto LowerDoubleOpDouble = [&]() -> void {
doubleLeft = builder_.GetDoubleOfTDouble(left);
doubleRight = builder_.GetDoubleOfTDouble(right);
builder_.Jump(&doFloatOp);
};
auto LowerRightWhenLeftIsInt = [&]() -> void {
if (rightType.IsIntType()) {
LowerIntOpInt();
} else if (rightType.IsDoubleType()) {
LowerIntOpDouble();
} else {
builder_.Branch(builder_.TaggedIsInt(right), &doIntOp, &leftIsIntRightIsDouble);
intOptAccessed = true;
builder_.Bind(&leftIsIntRightIsDouble);
LowerIntOpDouble();
}
};
auto LowerRightWhenLeftIsDouble = [&]() -> void {
if (rightType.IsIntType()) {
LowerDoubleOpInt();
} else if (rightType.IsDoubleType()) {
LowerDoubleOpDouble();
} else {
builder_.Branch(builder_.TaggedIsInt(right), &rightIsInt, &rightIsDouble);
builder_.Bind(&rightIsInt);
LowerDoubleOpInt();
builder_.Bind(&rightIsDouble);
LowerDoubleOpDouble();
}
};
if (leftType.IsIntType()) {
// left is int
LowerRightWhenLeftIsInt();
} else if (leftType.IsDoubleType()) {
// left is double
LowerRightWhenLeftIsDouble();
} else {
// left is number and need typecheck in runtime
builder_.Branch(builder_.TaggedIsInt(left), &leftIsInt, &leftIsDouble);
builder_.Bind(&leftIsInt);
LowerRightWhenLeftIsInt();
builder_.Bind(&leftIsDouble);
LowerRightWhenLeftIsDouble();
}
if (intOptAccessed) {
builder_.Bind(&doIntOp);
{
intLeft = builder_.GetInt32OfTInt(left);
intRight = builder_.GetInt32OfTInt(right);
doubleLeft = ChangeInt32ToFloat64(builder_.GetInt32OfTInt(left));
doubleRight = ChangeInt32ToFloat64(builder_.GetInt32OfTInt(right));
Label leftGreaterZero(&builder_);
builder_.Branch(builder_.Int32GreaterThan(*intLeft, builder_.Int32(0)),
&leftGreaterZero, &doFloatOp);
builder_.Bind(&leftGreaterZero);
{
Label rightGreaterZero(&builder_);
builder_.Branch(builder_.Int32GreaterThan(*intRight, builder_.Int32(0)),
&rightGreaterZero, &doFloatOp);
builder_.Bind(&rightGreaterZero);
{
result = IntToTaggedIntPtr(Int32Mod(*intLeft, *intRight));
builder_.Jump(&exit);
}
}
}
}
builder_.Bind(&doFloatOp);
{
Label rightNotZero(&builder_);
Label rightIsZeroOrNanOrLeftIsNanOrInf(&builder_);
Label rightNotZeroAndNanAndLeftNotNanAndInf(&builder_);
builder_.Branch(builder_.Equal(*doubleRight, builder_.Double(0.0)), &rightIsZeroOrNanOrLeftIsNanOrInf,
&rightNotZero);
builder_.Bind(&rightNotZero);
{
Label rightNotNan(&builder_);
builder_.Branch(builder_.DoubleIsNAN(*doubleRight), &rightIsZeroOrNanOrLeftIsNanOrInf, &rightNotNan);
builder_.Bind(&rightNotNan);
{
Label leftNotNan(&builder_);
builder_.Branch(builder_.DoubleIsNAN(*doubleLeft), &rightIsZeroOrNanOrLeftIsNanOrInf, &leftNotNan);
builder_.Bind(&leftNotNan);
builder_.Branch(DoubleIsINF(*doubleLeft), &rightIsZeroOrNanOrLeftIsNanOrInf,
&rightNotZeroAndNanAndLeftNotNanAndInf);
}
}
builder_.Bind(&rightIsZeroOrNanOrLeftIsNanOrInf);
{
result = DoubleToTaggedDoublePtr(builder_.Double(base::NAN_VALUE));
builder_.Jump(&exit);
}
builder_.Bind(&rightNotZeroAndNanAndLeftNotNanAndInf);
{
Label leftNotZero(&builder_);
Label leftIsZeroOrRightIsInf(&builder_);
builder_.Branch(builder_.Equal(*doubleLeft, builder_.Double(0.0)), &leftIsZeroOrRightIsInf,
&leftNotZero);
builder_.Bind(&leftNotZero);
{
Label rightNotInf(&builder_);
builder_.Branch(DoubleIsINF(*doubleRight), &leftIsZeroOrRightIsInf, &rightNotInf);
builder_.Bind(&rightNotInf);
{
ArgumentAccessor argAcc(circuit_);
auto glue = argAcc.GetCommonArgGate(CommonArgIdx::GLUE);
result = builder_.CallNGCRuntime(
glue, RTSTUB_ID(AotFloatMod), Gate::InvalidGateRef, { *doubleLeft, *doubleRight });
builder_.Jump(&exit);
}
}
builder_.Bind(&leftIsZeroOrRightIsInf);
{
result = DoubleToTaggedDoublePtr(*doubleLeft);
builder_.Jump(&exit);
}
}
}
builder_.Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef TypeLowering::DivNumbers(GateRef left, GateRef right, GateType leftType, GateType rightType)
{
auto env = builder_.GetCurrentEnvironment();

View File

@ -135,6 +135,9 @@ private:
void LowerTypedDiv(GateRef gate);
void LowerTypedEq(GateRef gate);
void LowerTypedNotEq(GateRef gate);
void LowerTypedShl(GateRef gate);
void LowerTypedShr(GateRef gate);
void LowerTypedAshr(GateRef gate);
void LowerTypedInc(GateRef gate);
void LowerTypedDec(GateRef gate);
void LowerTypedNot(GateRef gate);
@ -153,6 +156,9 @@ private:
void LowerNumberDiv(GateRef gate);
void LowerNumberEq(GateRef gate);
void LowerNumberNotEq(GateRef gate);
void LowerNumberShl(GateRef gate);
void LowerNumberShr(GateRef gate);
void LowerNumberAshr(GateRef gate);
void LowerNumberInc(GateRef gate);
void LowerNumberDec(GateRef gate);
void LowerNumberNot(GateRef gate);
@ -161,6 +167,8 @@ private:
GateRef FastAddOrSubOrMul(GateRef left, GateRef right);
template<OpCode::Op Op>
GateRef CalculateNumbers(GateRef left, GateRef right, GateType leftType, GateType rightType);
template<OpCode::Op Op>
GateRef ShiftNumber(GateRef left, GateRef right, GateType leftType, GateType rightType);
template<TypedBinOp Op>
GateRef CompareNumbers(GateRef left, GateRef right, GateType leftType, GateType rightType);
template<TypedBinOp Op>
@ -173,6 +181,7 @@ private:
GateRef BinaryOp(GateRef x, GateRef y);
GateRef DoubleToTaggedDoublePtr(GateRef gate);
GateRef ChangeInt32ToFloat64(GateRef gate);
GateRef TruncDoubleToInt(GateRef gate);
GateRef Int32Mod(GateRef left, GateRef right);
GateRef DoubleMod(GateRef left, GateRef right);
GateRef IntToTaggedIntPtr(GateRef x);
@ -180,6 +189,7 @@ private:
GateRef Less(GateRef left, GateRef right);
GateRef LessEq(GateRef left, GateRef right);
GateRef FastDiv(GateRef left, GateRef right);
GateRef ModNumbers(GateRef left, GateRef right, GateType leftType, GateType rightType);
GateRef DivNumbers(GateRef left, GateRef right, GateType leftType, GateType rightType);
GateRef FastEqual(GateRef left, GateRef right);

View File

@ -2074,6 +2074,12 @@ int32_t RuntimeStubs::FindElementWithCache(uintptr_t argGlue, JSTaggedType hclas
return index;
}
JSTaggedType RuntimeStubs::AotFloatMod(double x, double y)
{
double result = std::fmod(x, y);
return JSTaggedValue(result).GetRawData();
}
JSTaggedType RuntimeStubs::FloatMod(double x, double y)
{
double result = std::fmod(x, y);

View File

@ -91,6 +91,7 @@ using JSFunctionEntryType = JSTaggedValue (*)(uintptr_t glue, uintptr_t prevFp,
V(MarkingBarrier) \
V(StoreBarrier) \
V(DoubleToInt) \
V(AotFloatMod) \
V(FloatMod) \
V(FindElementWithCache) \
V(CreateArrayFromList) \
@ -340,6 +341,7 @@ public:
static JSTaggedType CreateArrayFromList([[maybe_unused]]uintptr_t argGlue, int32_t argc, JSTaggedValue *argv);
static void InsertOldToNewRSet([[maybe_unused]]uintptr_t argGlue, uintptr_t object, size_t offset);
static int32_t DoubleToInt(double x);
static JSTaggedType AotFloatMod(double x, double y);
static JSTaggedType FloatMod(double x, double y);
static int32_t FindElementWithCache(uintptr_t argGlue, JSTaggedType hclass,
JSTaggedType key, int32_t num);

View File

@ -13,3 +13,11 @@
1
4.5
0
NaN
NaN
45.5
45.5
NaN
NaN
NaN

View File

@ -23,3 +23,15 @@ print(res)
var num3: number = 50
var num4: number = 45.5
print(num3 % num4)
var num5:number = Number.NaN;
var num6:number = Number.NEGATIVE_INFINITY;
var num7:number = Number.POSITIVE_INFINITY;
var num8:number = 0.0;
print(num8 % num4)
print(num4 % num8)
print(num4 % num5)
print(num4 % num6)
print(num4 % num7)
print(num5 % num4)
print(num6 % num4)
print(num7 % num4)