mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 16:13:49 +00:00
Implement BigInt.asIntN and BigInt.asUintN builtins inlining
Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I9E7PU Test: build Signed-off-by: Oberman Igor <oberman.igor@huawei-partners.com> Change-Id: I7e6be18965672f80d7dc8921933953e6165834a4
This commit is contained in:
parent
db1eb53581
commit
699b8fa4e3
@ -806,13 +806,16 @@ void Builtins::InitializeBigInt(const JSHandle<GlobalEnv> &env, const JSHandle<J
|
||||
bigIntFuncInstanceHClass.GetTaggedValue());
|
||||
|
||||
// BigInt.prototype method
|
||||
SetFunction(env, bigIntFuncPrototype, "toLocaleString", BuiltinsBigInt::ToLocaleString, FunctionLength::ZERO);
|
||||
SetFunction(env, bigIntFuncPrototype, "toString", BuiltinsBigInt::ToString, FunctionLength::ZERO);
|
||||
SetFunction(env, bigIntFuncPrototype, "valueOf", BuiltinsBigInt::ValueOf, FunctionLength::ZERO);
|
||||
for (const auto &entry : BuiltinsBigInt::GetBigIntPrototypeFunctions()) {
|
||||
SetFunction(env, bigIntFuncPrototype, entry.GetName(), entry.GetEntrypoint(),
|
||||
entry.GetLength(), entry.GetBuiltinStubId());
|
||||
}
|
||||
|
||||
// BigInt method
|
||||
SetFunction(env, bigIntFunction, "asUintN", BuiltinsBigInt::AsUintN, FunctionLength::TWO);
|
||||
SetFunction(env, bigIntFunction, "asIntN", BuiltinsBigInt::AsIntN, FunctionLength::TWO);
|
||||
for (const auto &entry : BuiltinsBigInt::GetBigIntFunctions()) {
|
||||
SetFunction(env, bigIntFunction, entry.GetName(), entry.GetEntrypoint(),
|
||||
entry.GetLength(), entry.GetBuiltinStubId());
|
||||
}
|
||||
|
||||
// @@ToStringTag
|
||||
SetStringTagSymbol(env, bigIntFuncPrototype, "BigInt");
|
||||
|
@ -19,15 +19,36 @@
|
||||
#include "ecmascript/base/builtins_base.h"
|
||||
#include "ecmascript/js_tagged_value.h"
|
||||
|
||||
// List of functions in BigInt, excluding the constructor and '@@' properties.
|
||||
// V(name, func, length, stubIndex)
|
||||
// where BuiltinsBigInt::func refers to the native implementation of BigInt[name].
|
||||
// kungfu::BuiltinsStubCSigns::stubIndex refers to the builtin stub index, or INVALID if no stub available.
|
||||
#define BUILTIN_BIGINT_FUNCTIONS(V) \
|
||||
/* BigInt.asIntN (bits, bigint) */ \
|
||||
V("asIntN", AsIntN, 2, BigIntAsIntN) \
|
||||
/* BigInt.asUintN ( bits, bigint ) */ \
|
||||
V("asUintN", AsUintN, 2, BigIntAsUintN)
|
||||
// List of functions in BigInt.prototype, excluding the constructor and '@@' properties.
|
||||
// V(name, func, length, stubIndex)
|
||||
// where BuiltinsBigInt::func refers to the native implementation of BigInt.prototype[name].
|
||||
// kungfu::BuiltinsStubCSigns::stubIndex refers to the builtin stub index, or INVALID if no stub available.
|
||||
#define BUILTIN_BIGINT_PROTOTYPE_FUNCTIONS(V) \
|
||||
/* BigInt.toLocaleString ( [ reserved1 [ , reserved2 ] ] ) */ \
|
||||
V("toLocaleString", ToLocaleString, 0, INVALID) \
|
||||
/* BigInt.toString ( [radix] ) */ \
|
||||
V("toString", ToString, 0, INVALID) \
|
||||
/* BigInt.valueOf ( ) */ \
|
||||
V("valueOf", ValueOf, 0, INVALID)
|
||||
|
||||
namespace panda::ecmascript::builtins {
|
||||
class BuiltinsBigInt : public base::BuiltinsBase {
|
||||
public:
|
||||
// 21.2.1.1
|
||||
static JSTaggedValue BigIntConstructor(EcmaRuntimeCallInfo *argv);
|
||||
// 21.2.2.1
|
||||
static JSTaggedValue AsUintN(EcmaRuntimeCallInfo *argv);
|
||||
// 21.2.2.2
|
||||
static JSTaggedValue AsIntN(EcmaRuntimeCallInfo *argv);
|
||||
// 21.2.2.2
|
||||
static JSTaggedValue AsUintN(EcmaRuntimeCallInfo *argv);
|
||||
// 21.2.3.2
|
||||
static JSTaggedValue ToLocaleString(EcmaRuntimeCallInfo *argv);
|
||||
// 21.2.3.3
|
||||
@ -36,6 +57,31 @@ public:
|
||||
static JSTaggedValue ValueOf(EcmaRuntimeCallInfo *argv);
|
||||
private:
|
||||
static JSTaggedValue ThisBigIntValue(EcmaRuntimeCallInfo *argv);
|
||||
|
||||
public:
|
||||
// Excluding the constructor and '@@' internal properties.
|
||||
static Span<const base::BuiltinFunctionEntry> GetBigIntFunctions()
|
||||
{
|
||||
return Span<const base::BuiltinFunctionEntry>(BIGINT_FUNCTIONS);
|
||||
}
|
||||
|
||||
// Excluding the constructor and '@@' internal properties.
|
||||
static Span<const base::BuiltinFunctionEntry> GetBigIntPrototypeFunctions()
|
||||
{
|
||||
return Span<const base::BuiltinFunctionEntry>(BIGINT_PROTOTYPE_FUNCTIONS);
|
||||
}
|
||||
|
||||
private:
|
||||
#define BUILTIN_BIGINT_FUNCTION_ENTRY(name, func, length, builtinId) \
|
||||
base::BuiltinFunctionEntry::Create(name, BuiltinsBigInt::func, length, kungfu::BuiltinsStubCSigns::builtinId),
|
||||
|
||||
static inline std::array BIGINT_FUNCTIONS = {
|
||||
BUILTIN_BIGINT_FUNCTIONS(BUILTIN_BIGINT_FUNCTION_ENTRY)
|
||||
};
|
||||
static inline std::array BIGINT_PROTOTYPE_FUNCTIONS = {
|
||||
BUILTIN_BIGINT_PROTOTYPE_FUNCTIONS(BUILTIN_BIGINT_FUNCTION_ENTRY)
|
||||
};
|
||||
#undef BUILTIN_BIGINT_FUNCTION_ENTRY
|
||||
};
|
||||
} // namespace panda::ecmascript::builtins
|
||||
#endif // ECMASCRIPT_BUILTINS_BUILTINS_BIGINT_H
|
@ -236,6 +236,8 @@ namespace panda::ecmascript::kungfu {
|
||||
V(GlobalIsFinite) \
|
||||
V(GlobalIsNan) \
|
||||
V(ArrayBufferIsView) \
|
||||
V(BigIntAsIntN) \
|
||||
V(BigIntAsUintN) \
|
||||
V(DataViewGetFloat32) \
|
||||
V(DataViewGetFloat64) \
|
||||
V(DataViewGetInt8) \
|
||||
@ -512,6 +514,10 @@ public:
|
||||
return ConstantIndex::DATA_VIEW_SET_UINT16_INDEX;
|
||||
case BuiltinsStubCSigns::ID::DataViewSetUint32:
|
||||
return ConstantIndex::DATA_VIEW_SET_UINT32_INDEX;
|
||||
case BuiltinsStubCSigns::ID::BigIntAsIntN:
|
||||
return ConstantIndex::BIGINT_AS_INTN_INDEX;
|
||||
case BuiltinsStubCSigns::ID::BigIntAsUintN:
|
||||
return ConstantIndex::BIGINT_AS_UINTN_INDEX;
|
||||
case BuiltinsStubCSigns::ID::NumberIsFinite:
|
||||
return ConstantIndex::NUMBER_IS_FINITE_INDEX;
|
||||
case BuiltinsStubCSigns::ID::NumberIsInteger:
|
||||
@ -568,6 +574,8 @@ public:
|
||||
{DateNow, "Date.now"},
|
||||
{GlobalIsFinite, "isFinite"},
|
||||
{GlobalIsNan, "isNan"},
|
||||
{BigIntAsIntN, "BigInt.asIntN"},
|
||||
{BigIntAsUintN, "BigInt.asUintN"},
|
||||
{MapGet, "Map.get"},
|
||||
{MapHas, "Map.has"},
|
||||
{SetHas, "Set.has"},
|
||||
@ -622,6 +630,8 @@ public:
|
||||
{"now", DateNow},
|
||||
{"isFinite", GlobalIsFinite},
|
||||
{"isNan", GlobalIsNan},
|
||||
{"asIntN", BigIntAsIntN},
|
||||
{"asUintN", BigIntAsUintN},
|
||||
};
|
||||
if (str2BuiltinId.count(idStr) > 0) {
|
||||
return str2BuiltinId.at(idStr);
|
||||
|
@ -1326,6 +1326,36 @@ DEF_CALL_SIGNATURE(NumberHelperStringToDouble)
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(CallBigIntAsIntN)
|
||||
{
|
||||
// 2 : 2 input parameters
|
||||
CallSignature signature("CallBigIntAsIntN", 0, 2, ArgumentsOrder::DEFAULT_ORDER,
|
||||
VariableType::JS_POINTER());
|
||||
*callSign = signature;
|
||||
std::array<VariableType, 2> params = { // 2 : 2 input parameters
|
||||
VariableType::FLOAT64(),
|
||||
VariableType::JS_POINTER()
|
||||
};
|
||||
callSign->SetParameters(params.data());
|
||||
callSign->SetGCLeafFunction(true);
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(CallBigIntAsUintN)
|
||||
{
|
||||
// 2 : 2 input parameters
|
||||
CallSignature signature("CallBigIntAsUintN", 0, 2, ArgumentsOrder::DEFAULT_ORDER,
|
||||
VariableType::JS_POINTER());
|
||||
*callSign = signature;
|
||||
std::array<VariableType, 2> params = { // 2 : 2 input parameters
|
||||
VariableType::FLOAT64(),
|
||||
VariableType::JS_POINTER(),
|
||||
};
|
||||
callSign->SetParameters(params.data());
|
||||
callSign->SetGCLeafFunction(true);
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(GetStringToListCacheArray)
|
||||
{
|
||||
// 1 : 1 input parameters
|
||||
|
@ -432,6 +432,8 @@ private:
|
||||
V(StringsAreEquals) \
|
||||
V(BigIntEquals) \
|
||||
V(BigIntSameValueZero) \
|
||||
V(CallBigIntAsIntN) \
|
||||
V(CallBigIntAsUintN) \
|
||||
V(Dump) \
|
||||
V(DebugDump) \
|
||||
V(DumpWithHint) \
|
||||
|
@ -646,6 +646,7 @@ public:
|
||||
GateRef TypedCreateObjWithBuffer(std::vector<GateRef> &valueIn);
|
||||
template<TypedLoadOp Op>
|
||||
GateRef ConvertJSArrayHoleAsUndefined(GateRef receiver);
|
||||
GateRef BuildBigIntAsIntN(const GateMetaData* op, std::vector<GateRef> &&args);
|
||||
|
||||
// bit operation
|
||||
inline GateRef TaggedIsInt(GateRef x);
|
||||
|
@ -1780,6 +1780,19 @@ GateRef CircuitBuilder::NumberIsSafeInteger(GateRef gate)
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::BuildBigIntAsIntN(const GateMetaData* op, std::vector<GateRef> &&args)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
GateRef ret =
|
||||
GetCircuit()->NewGate(op, MachineType::I64,
|
||||
ConcatParams({std::vector{currentControl, currentDepend}, args}), GateType::TaggedValue());
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::IsASCIICharacter(GateRef gate)
|
||||
{
|
||||
return Int32UnsignedLessThan(Int32Sub(gate, Int32(1)), Int32(base::utf_helper::UTF8_1B_MAX));
|
||||
|
@ -117,6 +117,8 @@ namespace panda::ecmascript::kungfu {
|
||||
V(ArrayBufferIsView, ARRAY_BUFFER_IS_VIEW, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(DataViewGet, DATA_VIEW_GET, GateFlags::NO_WRITE, 1, 1, 5) \
|
||||
V(DataViewSet, DATA_VIEW_SET, GateFlags::NO_WRITE, 1, 1, 6) \
|
||||
V(BigIntAsIntN, BIGINT_ASINTN, GateFlags::NO_WRITE, 1, 1, 3) \
|
||||
V(BigIntAsUintN, BIGINT_ASUINTN, GateFlags::NO_WRITE, 1, 1, 3) \
|
||||
V(MapGet, MAP_GET, GateFlags::NO_WRITE, 1, 1, 2) \
|
||||
V(DateGetTime, DATE_GET_TIME, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(MapHas, MAP_HAS, GateFlags::NO_WRITE, 1, 1, 2) \
|
||||
|
@ -221,6 +221,10 @@ void NativeInlineLowering::RunNativeInlineLowering()
|
||||
case BuiltinsStubCSigns::ID::DataViewSetUint32:
|
||||
TryInlineDataViewSet(gate, argc, id);
|
||||
break;
|
||||
case BuiltinsStubCSigns::ID::BigIntAsIntN:
|
||||
case BuiltinsStubCSigns::ID::BigIntAsUintN:
|
||||
TryInlineBigIntAsIntN(gate, argc, id, skipThis);
|
||||
break;
|
||||
case BuiltinsStubCSigns::ID::MapGet:
|
||||
InlineStubBuiltin(gate, 1U, argc, id, circuit_->MapGet(), skipThis);
|
||||
break;
|
||||
@ -357,6 +361,30 @@ void NativeInlineLowering::TryInlineNumberIsSafeInteger(GateRef gate, size_t arg
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
|
||||
}
|
||||
|
||||
void NativeInlineLowering::TryInlineBigIntAsIntN(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
|
||||
bool skipThis)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
bool firstParam = skipThis ? 1 : 0;
|
||||
if (argc < 2U) {
|
||||
return;
|
||||
}
|
||||
if (!Uncheck()) {
|
||||
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
|
||||
builder_.IntPtr(static_cast<int64_t>(id)));
|
||||
}
|
||||
if (EnableTrace()) {
|
||||
AddTraceLogs(gate, id);
|
||||
}
|
||||
GateRef bits = acc_.GetValueIn(gate, firstParam);
|
||||
GateRef bigint = acc_.GetValueIn(gate, firstParam + 1);
|
||||
GateRef frameState = acc_.GetFrameState(gate);
|
||||
bool isUnsigned = (id == BuiltinsStubCSigns::ID::BigIntAsUintN);
|
||||
const auto* op = isUnsigned ? circuit_->BigIntAsUintN() : circuit_->BigIntAsIntN();
|
||||
GateRef ret = builder_.BuildBigIntAsIntN(op, {bits, bigint, frameState});
|
||||
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
|
||||
}
|
||||
|
||||
void NativeInlineLowering::TryInlineMathUnaryBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
|
||||
const GateMetaData* op, bool skipThis)
|
||||
{
|
||||
|
@ -64,6 +64,7 @@ private:
|
||||
double defaultValue, bool skipThis);
|
||||
void TryInlineMathClz32Builtin(GateRef gate, size_t argc, bool skipThis);
|
||||
void TryInlineArrayBufferIsView(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis);
|
||||
void TryInlineBigIntAsIntN(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis);
|
||||
void TryInlineDataViewGet(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id);
|
||||
void TryInlineDataViewSet(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id);
|
||||
void InlineStubBuiltin(GateRef gate, size_t builtinArgc, size_t realArgc, BuiltinsStubCSigns::ID id,
|
||||
|
@ -241,6 +241,9 @@ GateRef NumberSpeculativeRetype::VisitGate(GateRef gate)
|
||||
return VisitDataViewSet(gate);
|
||||
case OpCode::DATE_GET_TIME:
|
||||
return VisitDateGetTime(gate);
|
||||
case OpCode::BIGINT_ASINTN:
|
||||
case OpCode::BIGINT_ASUINTN:
|
||||
return VisitBigIntAsIntN(gate);
|
||||
case OpCode::MAP_HAS:
|
||||
case OpCode::SET_HAS:
|
||||
return VisitOthers(gate, GateType::BooleanType());
|
||||
@ -1722,6 +1725,22 @@ GateRef NumberSpeculativeRetype::VisitMathTrunc(GateRef gate)
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::VisitBigIntAsIntN(GateRef gate)
|
||||
{
|
||||
if (IsRetype()) {
|
||||
return SetOutputType(gate, GateType::AnyType());
|
||||
}
|
||||
ASSERT(IsConvert());
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
ASSERT(acc_.GetNumValueIn(gate) == 3U);
|
||||
GateRef bits = acc_.GetValueIn(gate, 0);
|
||||
acc_.ReplaceValueIn(gate, ConvertToTagged(CheckAndConvertToFloat64(bits, GateType::NumberType(),
|
||||
ConvertToNumber::BOOL_ONLY)), 0);
|
||||
acc_.ReplaceStateIn(gate, builder_.GetState());
|
||||
acc_.ReplaceDependIn(gate, builder_.GetDepend());
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
TypeInfo NumberSpeculativeRetype::GetNumberInputTypeInfo(GateRef gate, bool skipTagged)
|
||||
{
|
||||
TypeInfo typeInfo = GetOutputTypeInfo(gate);
|
||||
|
@ -99,6 +99,7 @@ private:
|
||||
template <bool IS_NAN>
|
||||
GateRef VisitNumberOrGlobalBuiltin(GateRef gate);
|
||||
GateRef VisitNumberIsInteger(GateRef gate);
|
||||
GateRef VisitBigIntAsIntN(GateRef gate);
|
||||
GateRef VisitBooleanJump(GateRef gate);
|
||||
GateRef VisitRangeCheckPredicate(GateRef gate);
|
||||
GateRef VisitIndexCheck(GateRef gate);
|
||||
|
@ -115,6 +115,8 @@ enum class TypedCallTargetCheckOp : uint8_t;
|
||||
V(IsUndefinedOrHole, ISUNDEFINEDORHOLE) \
|
||||
V(IsNotUndefinedOrHole, ISNOTUNDEFINEDORHOLE) \
|
||||
V(BuiltinInliningTypeGuard, BUILTIN_INLINING_TYPE_GUARD) \
|
||||
V(RangeError, RANGE_ERROR) \
|
||||
V(NotBigInt, NOT_BIG_INT) \
|
||||
V(OsrLoopExit, OSRLOOPEXIT) \
|
||||
V(IsNotEcmaObject, ISNOTECMAOBJECT) \
|
||||
V(IsNotDataView, ISNOTDATAVIEW) \
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "ecmascript/compiler/variable_type.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_arraybuffer.h"
|
||||
#include "ecmascript/js_bigint.h"
|
||||
#include "ecmascript/js_dataview.h"
|
||||
#include "ecmascript/js_hclass.h"
|
||||
#include "ecmascript/js_native_pointer.h"
|
||||
@ -185,6 +186,12 @@ GateRef TypedNativeInlineLowering::VisitGate(GateRef gate)
|
||||
case OpCode::ARRAY_BUFFER_IS_VIEW:
|
||||
LowerArrayBufferIsView(gate);
|
||||
break;
|
||||
case OpCode::BIGINT_ASINTN:
|
||||
LowerBigIntAsIntN<false>(gate);
|
||||
break;
|
||||
case OpCode::BIGINT_ASUINTN:
|
||||
LowerBigIntAsIntN<true>(gate);
|
||||
break;
|
||||
case OpCode::NUMBER_IS_FINITE:
|
||||
LowerNumberIsFinite(gate);
|
||||
break;
|
||||
@ -994,6 +1001,85 @@ void TypedNativeInlineLowering::LowerArrayBufferIsView(GateRef gate)
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
|
||||
}
|
||||
|
||||
template <bool IS_UNSIGNED>
|
||||
void TypedNativeInlineLowering::LowerBigIntAsIntN(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
Label hasException(&builder_);
|
||||
Label exit(&builder_);
|
||||
Label returnBigInt(&builder_);
|
||||
Label notZeroBigInt(&builder_);
|
||||
Label commonCase(&builder_);
|
||||
#if BIGINT_CONSTRUCTOR_IMPLEMENTED // NOTE: add fastpath after BigInt constructor implementing
|
||||
Label zeroBits(&builder_);
|
||||
Label notZeroBits(&builder_);
|
||||
#endif // BIGINT_CONSTRUCTOR_IMPLEMENTED
|
||||
|
||||
GateRef glue = acc_.GetGlueFromArgList();
|
||||
GateRef bits = acc_.GetValueIn(gate, 0);
|
||||
GateRef bigint = acc_.GetValueIn(gate, 1);
|
||||
GateRef frameState = acc_.GetValueIn(gate, 2);
|
||||
GateRef bitness = builder_.GetDoubleOfTDouble(bits);
|
||||
DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
|
||||
|
||||
// Deoptimization if bitness is negative or more than safe number
|
||||
GateRef safeNumber = builder_.Double(SAFE_NUMBER);
|
||||
GateRef positiveCheck = builder_.DoubleGreaterThanOrEqual(bitness, builder_.Double(0));
|
||||
GateRef safeCheck = builder_.DoubleLessThanOrEqual(bitness, safeNumber);
|
||||
builder_.DeoptCheck(positiveCheck, frameState, DeoptType::RANGE_ERROR);
|
||||
builder_.DeoptCheck(safeCheck, frameState, DeoptType::RANGE_ERROR);
|
||||
builder_.DeoptCheck(builder_.TaggedIsBigInt(bigint), frameState, DeoptType::NOT_BIG_INT);
|
||||
|
||||
// Return bigint(0), if bits == 0
|
||||
#if BIGINT_CONSTRUCTOR_IMPLEMENTED // NOTE: add fastpath after BigInt constructor implementing
|
||||
BRANCH_CIR(builder_.DoubleEqual(bitness, builder_.Double(0)), &zeroBits, ¬ZeroBits);
|
||||
builder_.Bind(&zeroBits);
|
||||
{
|
||||
result = builder_.BigIntConstructor(0);
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
builder_.Bind(¬ZeroBits);
|
||||
#endif // BIGINT_CONSTRUCTOR_IMPLEMENTED
|
||||
|
||||
// Return bigint, if bigint == 0
|
||||
GateRef lengthOffset = builder_.IntPtr(BigInt::LENGTH_OFFSET);
|
||||
GateRef length = builder_.Load(VariableType::INT32(), bigint, lengthOffset);
|
||||
GateRef isOneBit = builder_.Int32Equal(length, builder_.Int32(1));
|
||||
|
||||
GateRef dataOffset = builder_.IntPtr(BigInt::DATA_OFFSET);
|
||||
GateRef firstDigit = builder_.Load(VariableType::INT32(), bigint, dataOffset);
|
||||
GateRef isZero = builder_.Int32Equal(firstDigit, builder_.Int32(0));
|
||||
BRANCH_CIR(builder_.BoolAnd(isOneBit, isZero), &returnBigInt, ¬ZeroBigInt);
|
||||
|
||||
// Return bigint, if bits >= max_value
|
||||
builder_.Bind(¬ZeroBigInt);
|
||||
GateRef maxLengthBits = builder_.Double(static_cast<double>(BigInt::kMaxLengthBits));
|
||||
BRANCH_CIR(builder_.DoubleGreaterThanOrEqual(bitness, maxLengthBits), &returnBigInt, &commonCase);
|
||||
builder_.Bind(&returnBigInt);
|
||||
{
|
||||
result = bigint;
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
|
||||
// Common case
|
||||
builder_.Bind(&commonCase);
|
||||
if constexpr (IS_UNSIGNED) {
|
||||
result = builder_.CallRuntime(glue, RTSTUB_ID(CallBigIntAsUintN), Gate::InvalidGateRef,
|
||||
{bits, bigint}, gate);
|
||||
} else {
|
||||
result = builder_.CallRuntime(glue, RTSTUB_ID(CallBigIntAsIntN), Gate::InvalidGateRef,
|
||||
{bits, bigint}, gate);
|
||||
}
|
||||
BRANCH_CIR(builder_.HasPendingException(glue), &hasException, &exit);
|
||||
builder_.Bind(&hasException);
|
||||
{
|
||||
result = builder_.ExceptionConstant();
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
builder_.Bind(&exit);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
|
||||
}
|
||||
|
||||
void TypedNativeInlineLowering::LowerDataViewProtoFunc(GateRef gate, DataViewProtoFunc func)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
|
@ -60,6 +60,8 @@ private:
|
||||
void LowerClz32Int32(GateRef gate);
|
||||
void LowerMathSqrt(GateRef gate);
|
||||
void LowerNewNumber(GateRef gate);
|
||||
template <bool IS_UNSIGNED>
|
||||
void LowerBigIntAsIntN(GateRef gate);
|
||||
GateRef BuildRounding(GateRef gate, GateRef value, OpCode op);
|
||||
void LowerTaggedRounding(GateRef gate);
|
||||
void LowerDoubleRounding(GateRef gate);
|
||||
@ -125,4 +127,4 @@ private:
|
||||
bool isLiteCG_ {false};
|
||||
};
|
||||
}
|
||||
#endif // ECMASCRIPT_COMPILER_TYPED_HCR_LOWERING_H
|
||||
#endif // ECMASCRIPT_COMPILER_TYPED_HCR_LOWERING_H
|
||||
|
@ -192,6 +192,8 @@ class ObjectFactory;
|
||||
V(JSTaggedValue, MathCeil, MATH_CEIL_INDEX, ecma_roots_builtins) \
|
||||
V(JSTaggedValue, MathFloor, MATH_FLOOR_INDEX, ecma_roots_builtins) \
|
||||
V(JSTaggedValue, MathImul, MATH_IMUL_INDEX, ecma_roots_builtins) \
|
||||
V(JSTaggedValue, BigIntAsIntN, BIGINT_AS_INTN_INDEX, ecma_roots_builtins) \
|
||||
V(JSTaggedValue, BigIntAsUintN, BIGINT_AS_UINTN_INDEX, ecma_roots_builtins) \
|
||||
V(JSTaggedValue, GlobalIsFinite, GLOBAL_IS_FINITE_INDEX, ecma_roots_builtins) \
|
||||
V(JSTaggedValue, GlobalIsNan, GLOBAL_IS_NAN_INDEX, ecma_roots_builtins) \
|
||||
V(JSTaggedValue, MapGet, MAP_GET_INDEX, ecma_roots_builtins) \
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "ecmascript/js_arguments.h"
|
||||
#include "ecmascript/js_async_function.h"
|
||||
#include "ecmascript/js_async_generator_object.h"
|
||||
#include "ecmascript/js_bigint.h"
|
||||
#include "ecmascript/js_for_in_iterator.h"
|
||||
#include "ecmascript/js_generator_object.h"
|
||||
#include "ecmascript/js_iterator.h"
|
||||
@ -2480,6 +2481,20 @@ JSTaggedValue RuntimeStubs::RuntimeLdBigInt(JSThread *thread, const JSHandle<JST
|
||||
return JSTaggedValue::ToBigInt(thread, numberBigInt);
|
||||
}
|
||||
|
||||
JSTaggedValue RuntimeStubs::RuntimeCallBigIntAsIntN(JSThread *thread, JSTaggedValue bits, JSTaggedValue bigint)
|
||||
{
|
||||
auto biginteger = JSHandle<BigInt>(thread, bigint);
|
||||
JSTaggedNumber bitness = JSTaggedValue::ToNumber(thread, bits);
|
||||
return BigInt::AsintN(thread, bitness, biginteger);
|
||||
}
|
||||
|
||||
JSTaggedValue RuntimeStubs::RuntimeCallBigIntAsUintN(JSThread *thread, JSTaggedValue bits, JSTaggedValue bigint)
|
||||
{
|
||||
auto biginteger = JSHandle<BigInt>(thread, bigint);
|
||||
JSTaggedNumber bitness = JSTaggedValue::ToNumber(thread, bits);
|
||||
return BigInt::AsUintN(thread, bitness, biginteger);
|
||||
}
|
||||
|
||||
JSTaggedValue RuntimeStubs::RuntimeNewLexicalEnvWithName(JSThread *thread, uint16_t numVars, uint16_t scopeId)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include "ecmascript/interpreter/interpreter_assembly.h"
|
||||
#include "ecmascript/js_api/js_api_arraylist.h"
|
||||
#include "ecmascript/js_array_iterator.h"
|
||||
#include "ecmascript/js_bigint.h"
|
||||
#include "ecmascript/js_date.h"
|
||||
#include "ecmascript/js_function.h"
|
||||
#include "ecmascript/js_map_iterator.h"
|
||||
@ -2522,6 +2523,22 @@ DEF_RUNTIME_STUBS(LdBigInt)
|
||||
return RuntimeLdBigInt(thread, numberBigInt).GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(CallBigIntAsIntN)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(CallBigIntAsIntN);
|
||||
JSTaggedValue bits = GetArg(argv, argc, 0); // 0: means the zeroth parameter
|
||||
JSTaggedValue bigint = GetArg(argv, argc, 1); // 1: means the first parameter
|
||||
return RuntimeCallBigIntAsIntN(thread, bits, bigint).GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(CallBigIntAsUintN)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(CallBigIntAsUintN);
|
||||
JSTaggedValue bits = GetArg(argv, argc, 0); // 0: means the zeroth parameter
|
||||
JSTaggedValue bigint = GetArg(argv, argc, 1); // 1: means the first parameter
|
||||
return RuntimeCallBigIntAsUintN(thread, bits, bigint).GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(ToNumeric)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(ToNumeric);
|
||||
|
@ -354,6 +354,8 @@ using FastCallAotEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, co
|
||||
V(LdBigInt) \
|
||||
V(ToNumeric) \
|
||||
V(ToNumericConvertBigInt) \
|
||||
V(CallBigIntAsIntN) \
|
||||
V(CallBigIntAsUintN) \
|
||||
V(DynamicImport) \
|
||||
V(CreateAsyncGeneratorObj) \
|
||||
V(AsyncGeneratorResolve) \
|
||||
@ -804,6 +806,8 @@ private:
|
||||
static inline JSTaggedValue RuntimeThrowReferenceError(JSThread *thread, JSTaggedValue prop, const char *desc);
|
||||
static inline JSTaggedValue RuntimeThrowSyntaxError(JSThread *thread, const char *message);
|
||||
static inline JSTaggedValue RuntimeLdBigInt(JSThread *thread, const JSHandle<JSTaggedValue> &numberBigInt);
|
||||
static inline JSTaggedValue RuntimeCallBigIntAsIntN(JSThread *thread, JSTaggedValue bits, JSTaggedValue bigint);
|
||||
static inline JSTaggedValue RuntimeCallBigIntAsUintN(JSThread *thread, JSTaggedValue bits, JSTaggedValue bigint);
|
||||
static inline JSTaggedValue RuntimeNewLexicalEnvWithName(JSThread *thread, uint16_t numVars, uint16_t scopeId);
|
||||
static inline JSTaggedValue RuntimeOptGetUnmapedArgs(JSThread *thread, uint32_t actualNumArgs);
|
||||
static inline JSTaggedValue RuntimeGetUnmapedJSArgumentObj(JSThread *thread,
|
||||
|
@ -14,6 +14,7 @@
|
||||
group("ark_aot_builtin_inlining_test") {
|
||||
testonly = true
|
||||
deps = [
|
||||
"bigint:ark_aot_builtin_inlining_bigint_test",
|
||||
"date:ark_aot_builtin_inlining_date_test",
|
||||
"global:ark_aot_builtin_inlining_global_test",
|
||||
"map:ark_aot_builtin_inlining_map_test",
|
||||
|
17
test/aottest/builtin_inlining/bigint/AsIntN/BUILD.gn
Normal file
17
test/aottest/builtin_inlining/bigint/AsIntN/BUILD.gn
Normal file
@ -0,0 +1,17 @@
|
||||
# Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//arkcompiler/ets_runtime/test/test_helper.gni")
|
||||
|
||||
host_aot_builtin_inlining_test_action("builtinBigIntAsIntN") {
|
||||
}
|
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
declare interface ArkTools {
|
||||
isAOTCompiled(args: any): boolean;
|
||||
}
|
||||
declare function print(arg:any):string;
|
||||
function replace(a, b)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
function doAsIntN(bits: number, b : bigint) {
|
||||
return BigInt.asIntN(bits, b);
|
||||
}
|
||||
|
||||
function tryDoAsIntN(bits: number, b : bigint) {
|
||||
try {
|
||||
print(doAsIntN(bits, b));
|
||||
} catch(e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
function tryDoAsIntNEmpty() {
|
||||
try {
|
||||
print(BigInt.asIntN());
|
||||
} catch(e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
function tryDoAsIntNSingle(a) {
|
||||
try {
|
||||
print(BigInt.asIntN(a));
|
||||
} catch(e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
function printAsIntN(bits: number, b : bigint) {
|
||||
try {
|
||||
print(doAsIntN(bits, b));
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
|
||||
// Check standart behaviour
|
||||
// 25n = 00011001
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(3, 25n)); //: 1
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(4, 25n)); //: -7
|
||||
|
||||
// Check without params
|
||||
tryDoAsIntNEmpty(); //: TypeError: Cannot convert a undefine or null value to a BigInt
|
||||
|
||||
// Check with 1 param
|
||||
tryDoAsIntNSingle(16); //: TypeError: Cannot convert a undefine or null value to a BigInt
|
||||
tryDoAsIntNSingle(23n); //: TypeError: Cannot convert a BigInt value to a number
|
||||
|
||||
// Check with 2 params
|
||||
// 100n = 01100100
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(4, 100n)); //: 4
|
||||
|
||||
// Check with 3 params
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(8, 100n, undefined)); //: 100
|
||||
|
||||
// Check with 4 params
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(16, 100n, -20000, "abc")); //: 100
|
||||
|
||||
// Check some corner cases
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(0, 10000n)); //: 0
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(32, 0n)); //: 0
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:doAsIntN@builtinBigIntAsIntN
|
||||
//aot: [trace] Check Type: RangeError
|
||||
tryDoAsIntN(-2, 10000n); //: RangeError: integerIndex < 0 or integerIndex > SAFE_NUMBER
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:doAsIntN@builtinBigIntAsIntN
|
||||
//aot: [trace] Check Type: RangeError
|
||||
tryDoAsIntN(2 ** 53, 100000n); //: RangeError: integerIndex < 0 or integerIndex > SAFE_NUMBER
|
||||
|
||||
// bits > kMaxLengthBits => return bigint
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(2 ** 35, 2n ** 75n)); //: 37778931862957161709568
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(2 ** 35, 65531n)); //: 65531
|
||||
|
||||
// Check maximum and minimum values
|
||||
const max32 = 2n ** (32n - 1n) - 1n; // INT32_MAX = 2147483647
|
||||
const max32_possible_value = 2n ** 32n - 1n; // 11...11b
|
||||
const max64 = 2n ** (64n - 1n) - 1n; // INT64_MAX = 9223372036854775807
|
||||
const max64_possible_value = 2n ** 64n - 1n; // 11...11b
|
||||
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(32, max32)); //: 2147483647
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(32, max32 + 1n)); //: -2147483648
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(32, max32_possible_value)); //: -1
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(32, max32_possible_value + 1n)); //: 0
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(64, max64)); //: 9223372036854775807
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(64, max64 + 1n)); //: -9223372036854775808
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(64, max64_possible_value)); //: -1
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(64, max64_possible_value + 1n)); //: 0
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(32, -max32 - 1n)); //: -2147483648
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(32, -max32 - 2n)); //: 2147483647
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(32, -max32_possible_value)); //: 1
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(32, -max32_possible_value - 1n)); //: 0
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(64, -max64 - 1n)); //: -9223372036854775808
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(64, -max64 - 2n)); //: 9223372036854775807
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(64, -max64_possible_value)); //: 1
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(BigInt.asIntN(64, -max64_possible_value - 1n)); //: 0
|
||||
|
||||
// Replace standard builtin
|
||||
let true_asintn = BigInt.asIntN
|
||||
BigInt.asIntN = replace
|
||||
print(BigInt.asIntN(-1.001, 26n)); //: -1.001
|
||||
BigInt.asIntN = true_asintn
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:doAsIntN@builtinBigIntAsIntN
|
||||
printAsIntN(3, 25n); //: 1
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
print(true_asintn(3, 25n)); //: 1
|
||||
|
||||
// Call standard builtin with non-number param
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:doAsIntN@builtinBigIntAsIntN
|
||||
//aot: [trace] Check Type: NotNumber1
|
||||
tryDoAsIntN("abc", "abc"); //: SyntaxError: Cannot convert string to a BigInt,because not allow Infinity, decimal points, or exponents
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:doAsIntN@builtinBigIntAsIntN
|
||||
//aot: [trace] Check Type: NotNumber1
|
||||
printAsIntN("3", 25n); //: 1
|
||||
|
||||
if (ArkTools.isAOTCompiled(printAsIntN)) {
|
||||
// Replace standard builtin after call to standard builtin was profiled
|
||||
BigInt.asIntN = replace
|
||||
}
|
||||
|
||||
printAsIntN(3, 25n); //pgo: 1
|
||||
//aot: [trace] Check Type: NotCallTarget1
|
||||
//aot: 3
|
||||
|
||||
tryDoAsIntN("abc", "abc"); //pgo: SyntaxError: Cannot convert string to a BigInt,because not allow Infinity, decimal points, or exponents
|
||||
//aot: [trace] Check Type: NotCallTarget1
|
||||
//aot: abc
|
||||
|
||||
BigInt.asIntN = true_asintn
|
||||
|
||||
// Check IR correctness inside try-block
|
||||
try {
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:doAsIntN@builtinBigIntAsIntN
|
||||
printAsIntN(3, 25n); //: 1
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:doAsIntN@builtinBigIntAsIntN
|
||||
//aot: [trace] Check Type: NotNumber1
|
||||
printAsIntN("abc", "abc");
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
let obj = {
|
||||
valueOf: () => { return 5; }
|
||||
};
|
||||
|
||||
// 25n = 00011001
|
||||
//aot: [trace] aot inline builtin: BigInt.asIntN, caller function name:func_main_0@builtinBigIntAsIntN
|
||||
//aot: [trace] Check Type: NotNumber1
|
||||
print(BigInt.asIntN(obj, 25n)); //: -7
|
||||
|
||||
function Throwing() {
|
||||
this.value = 5;
|
||||
}
|
||||
Throwing.prototype.valueOf = function() {
|
||||
if (this.value < 0) {
|
||||
throw new Error("negative bitness");
|
||||
}
|
||||
return this.value;
|
||||
}
|
||||
let throwingObj = new Throwing();
|
||||
|
||||
try {
|
||||
// 42n = 00101010
|
||||
print(BigInt.asIntN(throwingObj, 42n)); //: 10
|
||||
throwingObj.value = -8;
|
||||
print(BigInt.asIntN(throwingObj, 42n));
|
||||
} catch(e) {
|
||||
print(e); //: Error: negative bitness
|
||||
} finally {
|
||||
// 15n = 00001111
|
||||
print(BigInt.asIntN(obj, 15n)); //: 15
|
||||
}
|
17
test/aottest/builtin_inlining/bigint/AsUintN/BUILD.gn
Normal file
17
test/aottest/builtin_inlining/bigint/AsUintN/BUILD.gn
Normal file
@ -0,0 +1,17 @@
|
||||
# Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//arkcompiler/ets_runtime/test/test_helper.gni")
|
||||
|
||||
host_aot_builtin_inlining_test_action("builtinBigIntAsUintN") {
|
||||
}
|
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
declare interface ArkTools {
|
||||
isAOTCompiled(args: any): boolean;
|
||||
}
|
||||
declare function print(arg:any):string;
|
||||
function replace(a, b)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
function doAsUintN(bits: number, b : bigint) {
|
||||
return BigInt.asUintN(bits, b);
|
||||
}
|
||||
|
||||
function tryDoAsUintNEmpty() {
|
||||
try {
|
||||
print(BigInt.asUintN());
|
||||
} catch(e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
function tryDoAsUintNSingle(a) {
|
||||
try {
|
||||
print(BigInt.asUintN(a));
|
||||
} catch(e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
function tryDoAsUintN(bits: number, b : bigint) {
|
||||
try {
|
||||
print(doAsUintN(bits, b));
|
||||
} catch(e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
function printAsUintN(bits: number, b : bigint) {
|
||||
try {
|
||||
print(doAsUintN(bits, b));
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
|
||||
// Check standart behaviour
|
||||
// 25n = 00011001
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(3, 25n)); //: 1
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(4, 25n)); //: 9
|
||||
|
||||
// Check without params
|
||||
tryDoAsUintNEmpty(); //: TypeError: Cannot convert a undefine or null value to a BigInt
|
||||
|
||||
// Check with 1 param
|
||||
tryDoAsUintNSingle(15); //: TypeError: Cannot convert a undefine or null value to a BigInt
|
||||
tryDoAsUintNSingle(23n); //: TypeError: Cannot convert a BigInt value to a number
|
||||
|
||||
// Check with 2 params
|
||||
// 100n = 01100100
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(4, 100n)); //: 4
|
||||
|
||||
// Check with 3 params
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(8, 100n, undefined)); //: 100
|
||||
|
||||
// Check with 4 params
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(16, 100n, -20000, "abc")); //: 100
|
||||
|
||||
// Check some corner cases
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(0, 10000n)); //: 0
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(32, 0n)); //: 0
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:doAsUintN@builtinBigIntAsUintN
|
||||
//aot: [trace] Check Type: RangeError
|
||||
tryDoAsUintN(-2, 10000n); //: RangeError: integerIndex < 0 or integerIndex > SAFE_NUMBER
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:doAsUintN@builtinBigIntAsUintN
|
||||
//aot: [trace] Check Type: RangeError
|
||||
tryDoAsUintN(2 ** 53, 100000n); //: RangeError: integerIndex < 0 or integerIndex > SAFE_NUMBER
|
||||
|
||||
// bits > kMaxLengthBits => return bigint
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(2 ** 35, 2n ** 75n)); //: 37778931862957161709568
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(2 ** 35, 65531n)); //: 65531
|
||||
|
||||
// Check maximum and minimum values
|
||||
const max32 = 2n ** 32n - 1n; // UINT32_MAX = 4294967295
|
||||
const max64 = 2n ** 64n - 1n; // UINT64_MAX = 18446744073709551615
|
||||
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(32, max32)); //: 4294967295
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(32, max32 + 1n)); //: 0
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(64, max64)); //: 18446744073709551615
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(64, max64 + 1n)); //: 0
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(32, -max32)); //: 1
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(32, -max32 - 1n)); //: 0
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(32, -max32 - 2n)); //: 4294967295
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(64, -max64)); //: 1
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(64, -max64 - 1n)); //: 0
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(BigInt.asUintN(64, -max64 - 2n)); //: 18446744073709551615
|
||||
|
||||
// Replace standard builtin
|
||||
let true_asUintN = BigInt.asUintN
|
||||
BigInt.asUintN = replace
|
||||
print(BigInt.asUintN(-1.001, 26n)); //: -1.001
|
||||
BigInt.asUintN = true_asUintN
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:doAsUintN@builtinBigIntAsUintN
|
||||
printAsUintN(3, 25n); //: 1
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
print(true_asUintN(3, 25n)); //: 1
|
||||
|
||||
// Call standard builtin with non-number param
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:doAsUintN@builtinBigIntAsUintN
|
||||
//aot: [trace] Check Type: NotNumber1
|
||||
tryDoAsUintN("abc", "abc"); //: SyntaxError: Cannot convert string to a BigInt,because not allow Infinity, decimal points, or exponents
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:doAsUintN@builtinBigIntAsUintN
|
||||
//aot: [trace] Check Type: NotNumber1
|
||||
printAsUintN("3", 25n); //: 1
|
||||
|
||||
if (ArkTools.isAOTCompiled(printAsUintN)) {
|
||||
// Replace standard builtin after call to standard builtin was profiled
|
||||
BigInt.asUintN = replace
|
||||
}
|
||||
|
||||
printAsUintN(3, 25n); //pgo: 1
|
||||
//aot: [trace] Check Type: NotCallTarget1
|
||||
//aot: 3
|
||||
|
||||
tryDoAsUintN("abc", "abc"); //pgo: SyntaxError: Cannot convert string to a BigInt,because not allow Infinity, decimal points, or exponents
|
||||
//aot: [trace] Check Type: NotCallTarget1
|
||||
//aot: abc
|
||||
|
||||
BigInt.asUintN = true_asUintN
|
||||
|
||||
// Check IR correctness inside try-block
|
||||
try {
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:doAsUintN@builtinBigIntAsUintN
|
||||
printAsUintN(3, 25n); //: 1
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:doAsUintN@builtinBigIntAsUintN
|
||||
//aot: [trace] Check Type: NotNumber1
|
||||
printAsUintN("abc", "abc");
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
let obj = {
|
||||
valueOf: () => { return 5; }
|
||||
};
|
||||
|
||||
// 25n = 00011001
|
||||
//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
|
||||
//aot: [trace] Check Type: NotNumber1
|
||||
print(BigInt.asUintN(obj, 25n)); //: 25
|
||||
|
||||
function Throwing() {
|
||||
this.value = 5;
|
||||
}
|
||||
Throwing.prototype.valueOf = function() {
|
||||
if (this.value < 0) {
|
||||
throw new Error("negative bitness");
|
||||
}
|
||||
return this.value;
|
||||
}
|
||||
let throwingObj = new Throwing();
|
||||
|
||||
try {
|
||||
// 42n = 00101010
|
||||
print(BigInt.asUintN(throwingObj, 42n)); //: 10
|
||||
throwingObj.value = -8;
|
||||
print(BigInt.asUintN(throwingObj, 42n));
|
||||
} catch(e) {
|
||||
print(e); //: Error: negative bitness
|
||||
} finally {
|
||||
// 15n = 00001111
|
||||
print(BigInt.asUintN(obj, 15n)); //: 15
|
||||
}
|
28
test/aottest/builtin_inlining/bigint/BUILD.gn
Normal file
28
test/aottest/builtin_inlining/bigint/BUILD.gn
Normal file
@ -0,0 +1,28 @@
|
||||
# Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
group("ark_aot_builtin_inlining_bigint_test") {
|
||||
testonly = true
|
||||
test_list = [
|
||||
"AsIntN",
|
||||
"AsUintN",
|
||||
]
|
||||
|
||||
deps = []
|
||||
foreach(test, test_list) {
|
||||
deps += [ "${test}:builtinBigInt${test}AotAction" ]
|
||||
if (!is_debug) {
|
||||
deps += [ "${test}:builtinBigInt${test}AotContextAction" ]
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user