Support BigIntConstructor inlint

Co-author: Andrey Efremov <efremov.andrey@huawei-partners.com>
Signed-off-by: Chernykh Sergey <chernykh.sergey1@huawei.com>
This commit is contained in:
Chernykh Sergey 2024-04-18 19:31:50 +08:00 committed by Ishin Pavel
parent 66146b68a0
commit 93eb2a8add
22 changed files with 411 additions and 27 deletions

View File

@ -799,8 +799,8 @@ void Builtins::InitializeBigInt(const JSHandle<GlobalEnv> &env, const JSHandle<J
factory_->NewEcmaHClass(JSPrimitiveRef::SIZE, JSType::JS_PRIMITIVE_REF, bigIntFuncPrototypeValue);
// BigInt = new Function()
JSHandle<JSObject> bigIntFunction(
NewBuiltinConstructor(env, bigIntFuncPrototype,
BuiltinsBigInt::BigIntConstructor, "BigInt", FunctionLength::ONE));
NewBuiltinConstructor(env, bigIntFuncPrototype, BuiltinsBigInt::BigIntConstructor, "BigInt",
FunctionLength::ONE, kungfu::BuiltinsStubCSigns::BigIntConstructor));
JSFunction::SetFunctionPrototypeOrInstanceHClass(thread_,
JSHandle<JSFunction>(bigIntFunction),
bigIntFuncInstanceHClass.GetTaggedValue());

View File

@ -38,6 +38,13 @@ JSTaggedValue BuiltinsBigInt::BigIntConstructor(EcmaRuntimeCallInfo *argv)
THROW_TYPE_ERROR_AND_RETURN(thread, "BigInt is not a constructor", JSTaggedValue::Exception());
}
JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
return BigIntConstructorInternal(thread, value);
}
JSTaggedValue BuiltinsBigInt::BigIntConstructorInternal(JSThread *thread, JSHandle<JSTaggedValue> value)
{
BUILTINS_API_TRACE(thread, BigInt, Constructor);
[[maybe_unused]] EcmaHandleScope handleScope(thread);
// 2. Let prim be ? ToPrimitive(value).
JSHandle<JSTaggedValue> Primitive(thread, JSTaggedValue::ToPrimitive(thread, value));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);

View File

@ -45,6 +45,7 @@ class BuiltinsBigInt : public base::BuiltinsBase {
public:
// 21.2.1.1
static JSTaggedValue BigIntConstructor(EcmaRuntimeCallInfo *argv);
static JSTaggedValue BigIntConstructorInternal(JSThread *thread, JSHandle<JSTaggedValue> value);
// 21.2.2.1
static JSTaggedValue AsIntN(EcmaRuntimeCallInfo *argv);
// 21.2.2.2

View File

@ -69,6 +69,8 @@ size_t BuiltinsStubCSigns::GetGlobalEnvIndex(ID builtinId)
switch (builtinId) {
case BuiltinsStubCSigns::ID::NumberConstructor:
return static_cast<size_t>(GlobalEnvField::NUMBER_FUNCTION_INDEX);
case BuiltinsStubCSigns::ID::BigIntConstructor:
return static_cast<size_t>(GlobalEnvField::BIGINT_FUNCTION_INDEX);
default:
LOG_COMPILER(FATAL) << "this branch is unreachable";
UNREACHABLE();

View File

@ -238,6 +238,7 @@ namespace panda::ecmascript::kungfu {
V(DateNow) \
V(GlobalIsFinite) \
V(GlobalIsNan) \
V(BigIntConstructor) \
V(ArrayBufferIsView) \
V(BigIntAsIntN) \
V(BigIntAsUintN) \
@ -628,6 +629,7 @@ public:
{SetHas, "Set.has"},
{MapDelete, "Map.delete"},
{SetDelete, "Set.delete"},
{BigIntConstructor, "BigInt"},
};
if (builtinId2Str.count(id) > 0) {
return builtinId2Str.at(id);
@ -683,6 +685,7 @@ public:
{"asUintN", BigIntAsUintN},
{"mapDelete", MapDelete},
{"setDelete", SetDelete},
{"BigInt", BigIntConstructor},
};
if (str2BuiltinId.count(idStr) > 0) {
return str2BuiltinId.at(idStr);

View File

@ -194,6 +194,7 @@ GateRef BuiltinLowering::LowerCallTargetCheck(Environment *env, GateRef gate)
case BuiltinsStubCSigns::ID::TypeArrayProtoIterator: {
return LowerCallTargetCheckWithDetector(gate, id);
}
case BuiltinsStubCSigns::ID::BigIntConstructor:
case BuiltinsStubCSigns::ID::NumberConstructor: {
return LowerCallTargetCheckWithGlobalEnv(gate, id);
}

View File

@ -269,8 +269,8 @@ void LLVMIRBuilder::Build()
continue;
}
if (illegalOpHandlers_.find(acc_.GetOpCode(gate)) == illegalOpHandlers_.end()) {
LOG_COMPILER(FATAL) << "The gate below need to be translated ";
acc_.Print(gate);
LOG_COMPILER(FATAL) << "The gate below need to be translated ";
UNREACHABLE();
}
}

View File

@ -119,6 +119,9 @@ namespace panda::ecmascript::kungfu {
V(NewNumber, NEW_NUMBER, GateFlags::CHECKABLE, 1, 1, 2) \
V(GlobalIsFinite, GLOBAL_IS_FINITE, GateFlags::NO_WRITE, 1, 1, 1) \
V(GlobalIsNan, GLOBAL_IS_NAN, GateFlags::NO_WRITE, 1, 1, 1) \
V(BigIntConstructor, BIGINT_CONSTRUCTOR, GateFlags::NO_WRITE, 1, 1, 1) \
V(BigIntConstructorInt32, BIGINT_CONSTRUCTOR_INT32, GateFlags::NO_WRITE, 1, 1, 1) \
V(BigIntConstructorUint32, BIGINT_CONSTRUCTOR_UINT32, GateFlags::NO_WRITE, 1, 1, 1) \
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) \

View File

@ -274,6 +274,9 @@ void NativeInlineLowering::RunNativeInlineLowering()
case BuiltinsStubCSigns::ID::SetEntries:
InlineStubBuiltin(gate, 0U, argc, id, circuit_->SetEntries(), skipThis);
break;
case BuiltinsStubCSigns::ID::BigIntConstructor:
TryInlineBigIntConstructor(gate, argc, skipThis);
break;
default:
break;
}
@ -716,6 +719,7 @@ void NativeInlineLowering::InlineStubBuiltin(GateRef gate, size_t builtinArgc, s
if (EnableTrace()) {
AddTraceLogs(gate, id);
}
std::vector<GateRef> args {};
for (size_t i = 0; i <= builtinArgc; i++) {
args.push_back(i <= realArgc ? acc_.GetValueIn(gate, i) : builder_.Undefined());
@ -724,6 +728,50 @@ void NativeInlineLowering::InlineStubBuiltin(GateRef gate, size_t builtinArgc, s
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
}
void NativeInlineLowering::ReplaceGateWithPendingException(GateRef hirGate, GateRef value)
{
GateRef state = builder_.GetState();
// copy depend-wire of hirGate to value
GateRef depend = builder_.GetDepend();
// exception value
GateRef exceptionVal = builder_.ExceptionConstant();
// compare with trampolines result
GateRef equal = builder_.Equal(value, exceptionVal);
auto ifBranch = builder_.Branch(state, equal, 1, BranchWeight::DEOPT_WEIGHT, "checkException");
GateRef ifTrue = builder_.IfTrue(ifBranch);
GateRef ifFalse = builder_.IfFalse(ifBranch);
GateRef eDepend = builder_.DependRelay(ifTrue, depend);
GateRef sDepend = builder_.DependRelay(ifFalse, depend);
StateDepend success(ifFalse, sDepend);
StateDepend exception(ifTrue, eDepend);
acc_.ReplaceHirWithIfBranch(hirGate, success, exception, value);
}
void NativeInlineLowering::TryInlineBigIntConstructor(GateRef gate, size_t argc, bool skipThis)
{
Environment env(gate, circuit_, &builder_);
bool firstParam = skipThis ? 1 : 0;
auto id = BuiltinsStubCSigns::ID::BigIntConstructor;
if (!Uncheck()) {
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
builder_.IntPtr(static_cast<int64_t>(id)));
}
if (EnableTrace()) {
AddTraceLogs(gate, id);
}
auto param = builder_.Undefined();
if (argc > 0) {
param = acc_.GetValueIn(gate, firstParam);
}
GateRef ret = builder_.BuildControlDependOp(circuit_->BigIntConstructor(), {param});
ReplaceGateWithPendingException(gate, ret);
return;
}
void NativeInlineLowering::TryInlineDateGetTime(GateRef gate, size_t argc, bool skipThis)
{
// Always shout be "this", we can't inline this function without instance of object

View File

@ -74,6 +74,8 @@ private:
void TryInlineWhitoutParamBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
const GateMetaData* op, bool skipThis);
void TryInlineBigIntConstructor(GateRef gate, size_t argc, bool skipThis);
void ReplaceGateWithPendingException(GateRef hirGate, GateRef value);
void AddTraceLogs(GateRef gate, BuiltinsStubCSigns::ID id);
bool EnableLog() const

View File

@ -253,6 +253,8 @@ GateRef NumberSpeculativeRetype::VisitGate(GateRef gate)
return VisitOthers(gate, GateType::BooleanType());
case OpCode::DATE_NOW:
return VisitDateNow(gate);
case OpCode::BIGINT_CONSTRUCTOR:
return VisitBigIntConstructor(gate);
case OpCode::JS_BYTECODE:
case OpCode::RUNTIME_CALL:
case OpCode::PRIMITIVE_TYPE_CHECK:
@ -1855,6 +1857,44 @@ GateRef NumberSpeculativeRetype::VisitDataViewGet(GateRef gate)
return Circuit::NullGate();
}
GateRef NumberSpeculativeRetype::VisitBigIntConstructor(GateRef gate)
{
if (IsRetype()) {
return SetOutputType(gate, GateType::BigIntType());
}
GateRef input = acc_.GetValueIn(gate, 0);
TypeInfo typeInfo = GetOutputTypeInfo(input);
const GateMetaData* meta = nullptr;
switch (typeInfo) {
case TypeInfo::INT32:
meta = circuit_->BigIntConstructorInt32();
break;
case TypeInfo::UINT32:
meta = circuit_->BigIntConstructorUint32();
break;
default:
auto int32_cnst = TryConvertConstant(input, true);
if (int32_cnst != Circuit::NullGate()) {
acc_.ReplaceValueIn(gate, int32_cnst, 0);
int32_t rawValue = acc_.GetInt32FromConstant(int32_cnst);
if (rawValue < 0) {
meta = circuit_->BigIntConstructorInt32();
} else {
meta = circuit_->BigIntConstructorUint32();
}
}
break;
}
if (meta != nullptr) {
// int or uint input
acc_.SetMetaData(gate, meta);
} else {
// double, object or some other input
acc_.ReplaceValueIn(gate, ConvertToTagged(input), 0);
}
return Circuit::NullGate();
}
GateRef NumberSpeculativeRetype::VisitDataViewSet(GateRef gate)
{
if (IsRetype()) {

View File

@ -113,6 +113,7 @@ private:
GateRef VisitDataViewGet(GateRef gate);
GateRef VisitDataViewSet(GateRef gate);
GateRef VisitOthers(GateRef gate, GateType outputType = GateType::AnyType());
GateRef VisitBigIntConstructor(GateRef gate);
GateRef VisitTypeConvert(GateRef gate);
GateRef VisitFrameState(GateRef gate);
GateRef VisitIsTrueOrFalse(GateRef gate);

View File

@ -74,7 +74,8 @@ bool PostSchedule::VisitHeapAlloc(GateRef gate, ControlFlowGraph &cfg, size_t bb
{
int64_t flag = acc_.TryGetValue(gate);
ASSERT(flag == RegionSpaceFlag::IN_YOUNG_SPACE ||
flag == RegionSpaceFlag::IN_SHARED_OLD_SPACE);
flag == RegionSpaceFlag::IN_SHARED_OLD_SPACE ||
flag == RegionSpaceFlag::IN_SHARED_NON_MOVABLE);
std::vector<GateRef> currentBBGates;
std::vector<GateRef> successBBGates;
std::vector<GateRef> failBBGates;
@ -92,7 +93,7 @@ bool PostSchedule::VisitHeapAlloc(GateRef gate, ControlFlowGraph &cfg, size_t bb
ScheduleCurrentBB(currentBBGates, cfg, bbIdx, instIdx);
return true;
#endif
} else if (flag == RegionSpaceFlag::IN_SHARED_OLD_SPACE) {
} else if (flag == RegionSpaceFlag::IN_SHARED_OLD_SPACE || flag == RegionSpaceFlag::IN_SHARED_NON_MOVABLE) {
LoweringHeapAllocate(gate, currentBBGates, successBBGates, failBBGates, endBBGates, flag);
ReplaceGateDirectly(currentBBGates, cfg, bbIdx, instIdx);
return false;
@ -312,14 +313,15 @@ void PostSchedule::LoweringHeapAllocate(GateRef gate,
GateRef taggedIntMask = circuit_->GetConstantGateWithoutCache(
MachineType::I64, JSTaggedValue::TAG_INT, GateType::NJSValue());
GateRef taggedSize = builder_.Int64Or(size, taggedIntMask);
GateRef target;
if (flag == RegionSpaceFlag::IN_YOUNG_SPACE) {
target = circuit_->GetConstantGateWithoutCache(
MachineType::ARCH, RTSTUB_ID(AllocateInYoung), GateType::NJSValue());
auto id = RTSTUB_ID(AllocateInYoung);
if (flag == RegionSpaceFlag::IN_SHARED_OLD_SPACE) {
id = RTSTUB_ID(AllocateInSOld);
} else if (flag == RegionSpaceFlag::IN_SHARED_NON_MOVABLE) {
id = RTSTUB_ID(AllocateInSNonMovable);
} else {
target = circuit_->GetConstantGateWithoutCache(
MachineType::ARCH, RTSTUB_ID(AllocateInSOld), GateType::NJSValue());
ASSERT(flag == RegionSpaceFlag::IN_YOUNG_SPACE);
}
GateRef target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, id, GateType::NJSValue());
const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
ASSERT(cs->IsRuntimeStub());
GateRef reseverdFrameArgs = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());

View File

@ -256,6 +256,15 @@ GateRef TypedNativeInlineLowering::VisitGate(GateRef gate)
case OpCode::SET_ENTRIES:
LowerToCommonStub(gate, CommonStubCSigns::JSSetEntries);
break;
case OpCode::BIGINT_CONSTRUCTOR:
LowerBigIntConstructor(gate);
break;
case OpCode::BIGINT_CONSTRUCTOR_INT32:
LowerBigIntConstructorInt32<true>(gate);
break;
case OpCode::BIGINT_CONSTRUCTOR_UINT32:
LowerBigIntConstructorInt32<false>(gate);
break;
default:
break;
}
@ -1790,7 +1799,6 @@ void TypedNativeInlineLowering::LowerToCommonStub(GateRef gate, CommonStubCSigns
acc_.ReplaceGate(gate, builder_.GetStateDepend(), ret);
}
void TypedNativeInlineLowering::LowerToBuiltinStub(GateRef gate, BuiltinsStubCSigns::ID id)
{
Environment env(gate, circuit_, &builder_);
@ -1831,4 +1839,45 @@ void TypedNativeInlineLowering::LowerGeneralWithoutArgs(GateRef gate, RuntimeStu
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
}
void TypedNativeInlineLowering::LowerBigIntConstructor(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
Label hasException(&builder_);
Label exit(&builder_);
GateRef value = acc_.GetValueIn(gate, 0);
GateRef glue = acc_.GetGlueFromArgList();
auto result = builder_.CallRuntime(glue, RTSTUB_ID(BigIntConstructor), Gate::InvalidGateRef, {value}, gate);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
}
template <bool IS_SIGNED>
void TypedNativeInlineLowering::LowerBigIntConstructorInt32(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef value = acc_.GetValueIn(gate, 0);
size_t length = 1;
size_t size = AlignUp(BigInt::ComputeSize(length), static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
GateRef sizeGate = builder_.IntPtr(size);
GateRef hclass = builder_.GetGlobalConstantValue(ConstantIndex::BIGINT_CLASS_INDEX);
GateRef sign = builder_.Int32(0);
if constexpr (IS_SIGNED) {
sign = builder_.Int32LSR(value, builder_.Int32(JSTaggedValue::INT_SIGN_BIT_OFFSET));
auto temp = builder_.Int32ASR(value, builder_.Int32(JSTaggedValue::INT_SIGN_BIT_OFFSET));
value = builder_.Int32Sub(builder_.Int32Xor(value, temp), temp);
}
// looks like code from StartAllocate to FinishAllocate must be linear
builder_.StartAllocate();
GateRef object = builder_.HeapAlloc(acc_.GetGlueFromArgList(), sizeGate, GateType::TaggedValue(),
RegionSpaceFlag::IN_SHARED_NON_MOVABLE);
// initialization
builder_.StoreConstOffset(VariableType::JS_POINTER(), object, JSObject::HCLASS_OFFSET, hclass,
MemoryOrder::NeedBarrierAndAtomic());
builder_.StoreConstOffset(VariableType::INT32(), object, BigInt::LENGTH_OFFSET, builder_.Int32(length));
builder_.StoreConstOffset(VariableType::INT32(), object, BigInt::BIT_FIELD_OFFSET, sign);
builder_.StoreConstOffset(VariableType::INT32(), object, BigInt::DATA_OFFSET, value);
GateRef ret = builder_.FinishAllocate(object);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
}
}

View File

@ -72,6 +72,9 @@ private:
void LowerNumberIsNaN(GateRef gate);
void LowerNumberIsSafeInteger(GateRef gate);
void LowerDateGetTime(GateRef gate);
void LowerBigIntConstructor(GateRef gate);
template <bool IS_SIGNED>
void LowerBigIntConstructorInt32(GateRef gate);
GateRef BuiltinIdToSize(GateRef ID);
GateRef GetValueFromBuffer(GateRef bufferIndex, GateRef dataPointer, GateRef isLittleEndian, GateRef builtinId);
GateRef SetValueInBuffer(GateRef bufferIndex,

View File

@ -536,6 +536,19 @@ TaggedObject *SharedHeap::AllocateNonMovableOrHugeObject(JSThread *thread, JSHCl
return object;
}
TaggedObject *SharedHeap::AllocateNonMovableOrHugeObject(JSThread *thread, size_t size)
{
size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
if (size > MAX_REGULAR_HEAP_OBJECT_SIZE) {
return AllocateHugeObject(thread, size);
}
auto object = reinterpret_cast<TaggedObject *>(sNonMovableSpace_->Allocate(thread, size));
CHECK_SOBJ_AND_THROW_OOM_ERROR(thread, object, size, sNonMovableSpace_,
"SharedHeap::AllocateNonMovableOrHugeObject");
OnAllocateEvent(thread->GetEcmaVM(), object, size);
return object;
}
TaggedObject *SharedHeap::AllocateOldOrHugeObject(JSThread *thread, JSHClass *hclass)
{
size_t size = hclass->GetObjectSize();

View File

@ -531,6 +531,8 @@ public:
inline TaggedObject *AllocateNonMovableOrHugeObject(JSThread *thread, JSHClass *hclass, size_t size);
inline TaggedObject *AllocateNonMovableOrHugeObject(JSThread *thread, size_t size);
inline TaggedObject *AllocateOldOrHugeObject(JSThread *thread, JSHClass *hclass);
inline TaggedObject *AllocateOldOrHugeObject(JSThread *thread, JSHClass *hclass, size_t size);

View File

@ -32,6 +32,7 @@
#include "ecmascript/js_stable_array.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/base/typed_array_helper.h"
#include "ecmascript/builtins/builtins_bigint.h"
#include "ecmascript/builtins/builtins_iterator.h"
#include "ecmascript/builtins/builtins_string_iterator.h"
#include "ecmascript/compiler/builtins/containers_stub_builder.h"
@ -166,21 +167,28 @@ DEF_RUNTIME_STUBS(AllocateInYoung)
return JSTaggedValue(result).GetRawData();
}
DEF_RUNTIME_STUBS(AllocateInSOld)
{
RUNTIME_STUBS_HEADER(AllocateInSOld);
JSTaggedValue allocateSize = GetArg(argv, argc, 0); // 0: means the zeroth parameter
auto size = static_cast<size_t>(allocateSize.GetInt());
auto sharedHeap = const_cast<SharedHeap*>(SharedHeap::GetInstance());
auto result = sharedHeap->AllocateOldOrHugeObject(thread, size);
ASSERT(result != nullptr);
if (argc > 1) { // 1: means the first parameter
JSHandle<JSHClass> hclassHandle = GetHArg<JSHClass>(argv, argc, 1); // 1: means the first parameter
auto hclass = JSHClass::Cast(hclassHandle.GetTaggedValue().GetTaggedObject());
sharedHeap->SetHClassAndDoAllocateEvent(thread, result, hclass, size);
#define ALLOCATE_IN_SHARED_HEAP(SPACE) \
DEF_RUNTIME_STUBS(AllocateInS##SPACE) \
{ \
RUNTIME_STUBS_HEADER(AllocateInS##SPACE); \
JSTaggedValue allocateSize = GetArg(argv, argc, 0); \
auto size = static_cast<size_t>(allocateSize.GetInt()); \
auto sharedHeap = const_cast<SharedHeap*>(SharedHeap::GetInstance()); \
ASSERT(size <= MAX_REGULAR_HEAP_OBJECT_SIZE); \
auto result = sharedHeap->Allocate##SPACE##OrHugeObject(thread, size); \
ASSERT(result != nullptr); \
if (argc > 1) { \
JSHandle<JSHClass> hclassHandle = GetHArg<JSHClass>(argv, argc, 1); \
auto hclass = JSHClass::Cast(hclassHandle.GetTaggedValue().GetTaggedObject()); \
sharedHeap->SetHClassAndDoAllocateEvent(thread, result, hclass, size); \
} \
return JSTaggedValue(result).GetRawData(); \
}
return JSTaggedValue(result).GetRawData();
}
ALLOCATE_IN_SHARED_HEAP(Old)
ALLOCATE_IN_SHARED_HEAP(NonMovable)
#undef ALLOCATE_IN_SHARED_HEAP
DEF_RUNTIME_STUBS(TypedArraySpeciesCreate)
{
@ -970,6 +978,13 @@ DEF_RUNTIME_STUBS(DumpObject)
return JSTaggedValue::True().GetRawData();
}
DEF_RUNTIME_STUBS(BigIntConstructor)
{
RUNTIME_STUBS_HEADER(BigIntConstructor);
JSHandle<JSTaggedValue> value = GetHArg<JSTaggedValue>(argv, argc, 0);
return builtins::BuiltinsBigInt::BigIntConstructorInternal(thread, value).GetRawData();
}
DEF_RUNTIME_STUBS(CreateGeneratorObj)
{
RUNTIME_STUBS_HEADER(CreateGeneratorObj);

View File

@ -183,6 +183,7 @@ using FastCallAotEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, co
V(AddElementInternal) \
V(AllocateInYoung) \
V(AllocateInSOld) \
V(AllocateInSNonMovable) \
V(TypedArraySpeciesCreate) \
V(CallInternalGetter) \
V(CallInternalSetter) \
@ -441,7 +442,8 @@ using FastCallAotEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, co
V(HasProperty) \
V(DumpObject) \
V(TryGetInternString) \
V(TryToElementsIndexOrFindInStringTable)
V(TryToElementsIndexOrFindInStringTable) \
V(BigIntConstructor)
#define RUNTIME_STUB_LIST(V) \
RUNTIME_ASM_STUB_LIST(V) \

View File

@ -16,6 +16,7 @@ group("ark_aot_builtin_inlining_bigint_test") {
test_list = [
"AsIntN",
"AsUintN",
"Constructor"
]
deps = []

View 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("builtinBigIntConstructor") {
}

View File

@ -0,0 +1,172 @@
/*
* 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)
{
return a * 2;
}
function checkBigInt(x) {
let val = BigInt(x);
print(val);
if (typeof val !== 'bigint') {
print(typeof val);
throw new Error();
}
}
function checkNotBigInt(x) {
try {
let val = BigInt(x);
print(val);
print(typeof val);
} catch (e) {
print(e.name)
}
}
//aot: [trace] aot inline builtin: BigInt, caller function name:func_main_0@builtinBigIntConstructor
let n = BigInt(1);
print(typeof n); //: bigint
//aot: [trace] aot inline builtin: BigInt, caller function name:func_main_0@builtinBigIntConstructor
n = BigInt(1)
print(n); //: 1
//aot: [trace] aot inline builtin: BigInt, caller function name:func_main_0@builtinBigIntConstructor
n = BigInt(1, 2)
print(typeof n); //: bigint
print(n); //: 1
//aot: [trace] aot inline function name: checkBigInt@builtinBigIntConstructor caller function name: func_main_0@builtinBigIntConstructor
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt(-1); //: -1
//aot: [trace] aot inline function name: checkBigInt@builtinBigIntConstructor caller function name: func_main_0@builtinBigIntConstructor
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt(-12345); //: -12345
//aot: [trace] aot inline function name: checkBigInt@builtinBigIntConstructor caller function name: func_main_0@builtinBigIntConstructor
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt(1n); //: 1
//aot: [trace] aot inline function name: checkBigInt@builtinBigIntConstructor caller function name: func_main_0@builtinBigIntConstructor
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt(-1n); //: -1
//aot: [trace] aot inline function name: checkBigInt@builtinBigIntConstructor caller function name: func_main_0@builtinBigIntConstructor
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt(0.0); //: 0
//aot: [trace] aot inline function name: checkBigInt@builtinBigIntConstructor caller function name: func_main_0@builtinBigIntConstructor
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt(-0.0); //: 0
//aot: [trace] aot inline builtin: BigInt, caller function name:func_main_0@builtinBigIntConstructor
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt(BigInt(-1)); //: -1
// test large ints
// 2^31-1
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt(2147483647); //: 2147483647
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt(2147483647 << 1); //: -2
//-(2^32)
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt(-2147483648); //: -2147483648
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt(Number.MIN_SAFE_INTEGER); //: -9007199254740991
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt(Number.MAX_SAFE_INTEGER); //: 9007199254740991
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt(Number.MAX_SAFE_INTEGER - 0.5); //: 9007199254740990
// 1e22
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt(10000000000000000000000) //: 10000000000000000000000
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt(1e23) //: 99999999999999991611392
// also 1e23
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt(100000000000000000000000) //: 99999999999999991611392
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt("100000000000000000000000") //: 100000000000000000000000
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt("-100000000000000000000000") //: -100000000000000000000000
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt(100000000000000000000000n) //: 100000000000000000000000
//aot: [trace] aot inline builtin: BigInt, caller function name:func_main_0@builtinBigIntConstructor
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt(BigInt(100000000000000000000000n)) //: 100000000000000000000000
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt("0xf") //: 15
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt({ valueOf: () => 1 }); //: 1
//aot: [trace] aot inline builtin: BigInt, caller function name:checkBigInt@builtinBigIntConstructor
checkBigInt({ valueOf: () => "-11" }); //: -11
//aot: [trace] aot inline builtin: BigInt, caller function name:checkNotBigInt@builtinBigIntConstructor
checkNotBigInt(1.5); //: RangeError
//aot: [trace] aot inline builtin: BigInt, caller function name:checkNotBigInt@builtinBigIntConstructor
checkNotBigInt(-20.000001); //: RangeError
//aot: [trace] aot inline builtin: BigInt, caller function name:checkNotBigInt@builtinBigIntConstructor
checkNotBigInt(Number.EPSILON); //: RangeError
//aot: [trace] aot inline builtin: BigInt, caller function name:checkNotBigInt@builtinBigIntConstructor
checkNotBigInt(Number.POSITIVE_INFINITY); //: RangeError
//aot: [trace] aot inline builtin: BigInt, caller function name:checkNotBigInt@builtinBigIntConstructor
checkNotBigInt(Number.NEGATIVE_INFINITY); //: RangeError
//aot: [trace] aot inline builtin: BigInt, caller function name:checkNotBigInt@builtinBigIntConstructor
checkNotBigInt(NaN); //: RangeError
//aot: [trace] aot inline builtin: BigInt, caller function name:checkNotBigInt@builtinBigIntConstructor
checkNotBigInt(null); //: TypeError
//aot: [trace] aot inline builtin: BigInt, caller function name:checkNotBigInt@builtinBigIntConstructor
checkNotBigInt(undefined); //: TypeError
//aot: [trace] aot inline builtin: BigInt, caller function name:checkNotBigInt@builtinBigIntConstructor
checkNotBigInt("f"); //: SyntaxError
//aot: [trace] aot inline builtin: BigInt, caller function name:checkNotBigInt@builtinBigIntConstructor
checkNotBigInt({}); //: SyntaxError
try {
//NOTE: not inlined by now
//aot: [trace] aot inline builtin: BigInt, caller function name:func_main_0@builtinBigIntConstructor
n = BigInt();
} catch(e) {
print(e.name); //: TypeError
}
try {
// not inlined as expected
n = new BigInt(1);
} catch(e) {
print(e.name); //: TypeError
}
//aot: [trace] aot inline builtin: BigInt, caller function name:func_main_0@builtinBigIntConstructor
n = 2n.constructor(12);
print(typeof n); //: bigint
print(n); //: 12
//aot: [trace] aot inline builtin: BigInt, caller function name:func_main_0@builtinBigIntConstructor
n = globalThis.BigInt(12);
print(typeof n); //: bigint
print(n); //: 12
if (ArkTools.isAOTCompiled(checkBigInt)) {
BigInt = replace;
}
//aot: [trace] Check Type: NotCallTarget1
print(BigInt(2)); //pgo: 2
//aot: 4