/* * Copyright (c) 2021-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. */ #include "ecmascript/base/config.h" #include "ecmascript/js_object.h" #include "ecmascript/stubs/runtime_optimized_stubs-inl.h" #include "ecmascript/stubs/runtime_stubs-inl.h" #include "ecmascript/base/gc_helper.h" #include "ecmascript/base/json_stringifier.h" #include "ecmascript/base/typed_array_helper-inl.h" #include "ecmascript/builtins/builtins_array.h" #include "ecmascript/js_stable_array.h" #include "ecmascript/builtins/builtins_bigint.h" #include "ecmascript/builtins/builtins_function.h" #include "ecmascript/builtins/builtins_iterator.h" #include "ecmascript/builtins/builtins_reflect.h" #include "ecmascript/builtins/builtins_string_iterator.h" #include "ecmascript/compiler/builtins/containers_stub_builder.h" #include "ecmascript/builtins/builtins_array.h" #include "ecmascript/dfx/cpu_profiler/cpu_profiler.h" #include "ecmascript/dfx/stackinfo/js_stackinfo.h" #include "ecmascript/dfx/vmstat/function_call_timer.h" #include "ecmascript/dfx/vmstat/opt_code_profiler.h" #include "ecmascript/ic/ic_runtime_stub-inl.h" #include "ecmascript/interpreter/interpreter_assembly.h" #include "ecmascript/interpreter/slow_runtime_stub.h" #include "ecmascript/jit/jit.h" #include "ecmascript/js_map_iterator.h" #include "ecmascript/js_set_iterator.h" #include "ecmascript/js_string_iterator.h" #include "ecmascript/js_stable_array.h" #include "ecmascript/jspandafile/js_pandafile_executor.h" #include "ecmascript/stubs/runtime_stubs.h" #include "ecmascript/linked_hash_table.h" #include "ecmascript/builtins/builtins_object.h" #include "ecmascript/module/module_value_accessor.h" #include "ecmascript/module/module_path_helper.h" #include "common_components/heap/allocator/region_desc.h" #include "common_components/mutator/mutator.h" #ifdef ARK_SUPPORT_INTL #include "ecmascript/js_collator.h" #include "ecmascript/js_locale.h" #else #ifndef ARK_NOT_SUPPORT_INTL_GLOBAL #include "ecmascript/intl/global_intl_helper.h" #endif #endif namespace panda::ecmascript { #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-parameter" #elif defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #endif #define DEF_RUNTIME_STUBS(name) \ JSTaggedType RuntimeStubs::name(uintptr_t argGlue, uint32_t argc, uintptr_t argv) #define RUNTIME_STUBS_HEADER(name) \ auto thread = JSThread::GlueToJSThread(argGlue); \ RUNTIME_TRACE(thread, name); \ [[maybe_unused]] EcmaHandleScope handleScope(thread) \ #define GET_ASM_FRAME(CurrentSp) \ (reinterpret_cast(CurrentSp) - 1) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) DEF_RUNTIME_STUBS(InitializeGeneratorFunction) { RUNTIME_STUBS_HEADER(InitializeGeneratorFunction); FunctionKind kind = static_cast(GetTArg(argv, argc, 0)); // 1: means the first parameter JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle objFun(env->GetObjectFunction()); JSHandle initialGeneratorFuncPrototype = factory->NewJSObjectByConstructor(objFun); if (kind == FunctionKind::ASYNC_GENERATOR_FUNCTION) { JSObject::SetPrototype(thread, initialGeneratorFuncPrototype, env->GetAsyncGeneratorPrototype()); } else if (kind == FunctionKind::GENERATOR_FUNCTION) { JSObject::SetPrototype(thread, initialGeneratorFuncPrototype, env->GetGeneratorPrototype()); } return initialGeneratorFuncPrototype.GetTaggedType(); } DEF_RUNTIME_STUBS(FunctionDefineOwnProperty) { RUNTIME_STUBS_HEADER(FunctionDefineOwnProperty); JSHandle func(GetHArg(argv, argc, 0)); JSHandle accessor = GetHArg(argv, argc, 1); // 1: means the first parameter FunctionKind kind = static_cast(GetTArg(argv, argc, 2)); // 2: means the second parameter PropertyDescriptor desc(thread, accessor, kind != FunctionKind::BUILTIN_CONSTRUCTOR, false, false); JSObject::DefineOwnProperty(thread, JSHandle(func), thread->GlobalConstants()->GetHandledPrototypeString(), desc); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(HeapAlloc) { RUNTIME_STUBS_HEADER(HeapAlloc); JSTaggedValue allocateSize = GetArg(argv, argc, 0); // 0: means the zeroth parameter auto size = static_cast(allocateSize.GetLargeUInt()); JSHandle hclassHandle = GetHArg(argv, argc, 1); // 1: means the first parameter auto type = static_cast(GetArg(argv, argc, 2).GetInt()); MemSpaceType mtype; switch (type) { case RegionSpaceFlag::IN_YOUNG_SPACE: mtype = MemSpaceType::SEMI_SPACE; break; case RegionSpaceFlag::IN_OLD_SPACE: mtype = MemSpaceType::OLD_SPACE; break; case RegionSpaceFlag::IN_NON_MOVABLE_SPACE: mtype = MemSpaceType::NON_MOVABLE; break; case RegionSpaceFlag::IN_SHARED_OLD_SPACE: mtype = MemSpaceType::SHARED_OLD_SPACE; break; case RegionSpaceFlag::IN_SHARED_NON_MOVABLE: mtype = MemSpaceType::SHARED_NON_MOVABLE; break; default: LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); } auto hclass = JSHClass::Cast(hclassHandle.GetTaggedValue().GetTaggedObject()); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); auto result = factory->AllocObjectWithSpaceType(size, hclass, mtype); return JSTaggedValue(result).GetRawData(); } DEF_RUNTIME_STUBS(AllocateInYoung) { RUNTIME_STUBS_HEADER(AllocateInYoung); JSTaggedValue allocateSize = GetArg(argv, argc, 0); // 0: means the zeroth parameter auto size = static_cast(allocateSize.GetLargeUInt()); auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); auto result = heap->AllocateYoungOrHugeObject(size); ASSERT(result != nullptr); if (argc > 1) { // 1: means the first parameter JSHandle hclassHandle = GetHArg(argv, argc, 1); // 1: means the first parameter auto hclass = JSHClass::Cast(hclassHandle.GetTaggedValue().GetTaggedObject()); heap->SetHClassAndDoAllocateEvent(thread, result, hclass, size); } return JSTaggedValue(result).GetRawData(); } DEF_RUNTIME_STUBS(AllocateInOld) { RUNTIME_STUBS_HEADER(AllocateInOld); JSTaggedValue allocateSize = GetArg(argv, argc, 0); // 0: means the zeroth parameter auto size = static_cast(allocateSize.GetLargeUInt()); auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); auto result = heap->AllocateOldOrHugeObject(size); ASSERT(result != nullptr); if (argc > 1) { // 1: means the first parameter JSHandle hclassHandle = GetHArg(argv, argc, 1); // 1: means the first parameter auto hclass = JSHClass::Cast(hclassHandle.GetTaggedValue().GetTaggedObject()); heap->SetHClassAndDoAllocateEvent(thread, result, hclass, size); } return JSTaggedValue(result).GetRawData(); } #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(allocateSize.GetInt()); \ auto sharedHeap = const_cast(SharedHeap::GetInstance()); \ ASSERT(size <= g_maxRegularHeapObjectSize); \ auto result = sharedHeap->Allocate##SPACE##OrHugeObject(thread, size); \ ASSERT(result != nullptr); \ if (argc > 1) { \ JSHandle hclassHandle = GetHArg(argv, argc, 1); \ auto hclass = JSHClass::Cast(hclassHandle.GetTaggedValue().GetTaggedObject()); \ sharedHeap->SetHClassAndDoAllocateEvent(thread, result, hclass, size); \ } \ return JSTaggedValue(result).GetRawData(); \ } #undef ALLOCATE_IN_SHARED_HEAP DEF_RUNTIME_STUBS(AllocateInSNonMovable) { RUNTIME_STUBS_HEADER(AllocateInSNonMovable); JSTaggedValue allocateSize = GetArg(argv, argc, 0); // 0: means the zeroth parameter auto size = static_cast(allocateSize.GetInt()); auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); auto result = heap->AllocateSharedNonMovableSpaceFromTlab(thread, size); if (result != nullptr) { return JSTaggedValue(result).GetRawData(); } auto sharedHeap = const_cast(SharedHeap::GetInstance()); result = sharedHeap->AllocateNonMovableOrHugeObject(thread, size); ASSERT(result != nullptr); if (argc > 1) { // 1: means the first parameter JSHandle hclassHandle = GetHArg(argv, argc, 1); // 1: means the first parameter auto hclass = JSHClass::Cast(hclassHandle.GetTaggedValue().GetTaggedObject()); sharedHeap->SetHClassAndDoAllocateEvent(thread, result, hclass, size); } return JSTaggedValue(result).GetRawData(); } DEF_RUNTIME_STUBS(DefineOwnProperty) { RUNTIME_STUBS_HEADER(DefineOwnProperty); JSHandle obj = GetHArg(argv, argc, 0); JSHandle key = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle value = GetHArg(argv, argc, 2); // 2: means the second parameter PropertyDescriptor desc(thread, value, true, true, true); bool res = JSTaggedValue::DefineOwnProperty(thread, obj, key, desc); return JSTaggedValue(res).GetRawData(); } DEF_RUNTIME_STUBS(AllocateInSOld) { RUNTIME_STUBS_HEADER(AllocateInSOld); JSTaggedValue allocateSize = GetArg(argv, argc, 0); // 0: means the zeroth parameter auto size = static_cast(allocateSize.GetInt()); auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); auto result = heap->AllocateSharedOldSpaceFromTlab(thread, size); if (result != nullptr) { return JSTaggedValue(result).GetRawData(); } auto sharedHeap = const_cast(SharedHeap::GetInstance()); result = sharedHeap->AllocateOldOrHugeObject(thread, size); ASSERT(result != nullptr); if (argc > 1) { // 1: means the first parameter JSHandle hclassHandle = GetHArg(argv, argc, 1); // 1: means the first parameter auto hclass = JSHClass::Cast(hclassHandle.GetTaggedValue().GetTaggedObject()); sharedHeap->SetHClassAndDoAllocateEvent(thread, result, hclass, size); } return JSTaggedValue(result).GetRawData(); } DEF_RUNTIME_STUBS(TypedArraySpeciesCreate) { RUNTIME_STUBS_HEADER(TypedArraySpeciesCreate); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle thisObj(obj); JSTaggedValue indexValue = GetArg(argv, argc, 1); // 1: means the first parameter uint32_t index = static_cast(indexValue.GetInt()); JSTaggedValue arrayLen = GetArg(argv, argc, 2); // 2: means the second parameter uint32_t length = static_cast(arrayLen.GetInt()); JSTaggedType args[1] = {JSTaggedValue(length).GetRawData()}; JSHandle newArr = base::TypedArrayHelper::TypedArraySpeciesCreate(thread, thisObj, index, args); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); return newArr.GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(TypedArrayCreateSameType) { RUNTIME_STUBS_HEADER(TypedArrayCreateSameType); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle thisObj(obj); JSTaggedValue indexValue = GetArg(argv, argc, 1); // 1: means the first parameter uint32_t index = static_cast(indexValue.GetInt()); JSTaggedValue arrayLen = GetArg(argv, argc, 2); // 2: means the second parameter uint32_t length = static_cast(arrayLen.GetInt()); JSTaggedType args[1] = {JSTaggedValue(length).GetRawData()}; JSHandle newArr = base::TypedArrayHelper::TypedArrayCreateSameType(thread, thisObj, index, args); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); return newArr.GetTaggedValue().GetRawData(); } void RuntimeStubs::CopyTypedArrayBuffer(uintptr_t argGlue, JSTypedArray *srcArray, JSTypedArray *targetArray, int32_t srcStartPos, int32_t tarStartPos, int32_t count) { DISALLOW_GARBAGE_COLLECTION; if (count <= 0) { return; } JSType srcType = srcArray->GetClass()->GetObjectType(); JSType tarType = targetArray->GetClass()->GetObjectType(); uint32_t srcElementSize = base::TypedArrayHelper::GetElementSize(srcType); uint32_t uSrcStartPos = static_cast(srcStartPos); uint32_t uTarStartPos = static_cast(tarStartPos); uint32_t uCount = static_cast(count); if (LIKELY(srcType == tarType)) { auto thread = JSThread::GlueToJSThread(argGlue); JSTaggedValue srcBuffer = srcArray->GetViewedArrayBufferOrByteArray(thread); JSTaggedValue targetBuffer = targetArray->GetViewedArrayBufferOrByteArray(thread); uint32_t srcByteIndex = uSrcStartPos * srcElementSize + srcArray->GetByteOffset(); uint32_t targetByteIndex = uTarStartPos * srcElementSize + targetArray->GetByteOffset(); uint8_t *srcBuf = (uint8_t *)builtins::BuiltinsArrayBuffer::GetDataPointFromBuffer(thread, srcBuffer, srcByteIndex); uint8_t *targetBuf = (uint8_t *)builtins::BuiltinsArrayBuffer::GetDataPointFromBuffer(thread, targetBuffer, targetByteIndex); if (memmove_s(targetBuf, srcElementSize * uCount, srcBuf, srcElementSize * uCount) != EOK) { LOG_FULL(FATAL) << "memmove_s failed"; UNREACHABLE(); } } else { auto thread = JSThread::GlueToJSThread(argGlue); for (uint32_t i = 0; i < uCount; ++i) { JSTaggedValue curElement = JSTypedArray::FastGetPropertyByIndex(thread, JSTaggedValue::Cast(srcArray), uSrcStartPos + i, srcType); JSTypedArray::FastSetPropertyByIndex(thread, JSTaggedValue::Cast(targetArray), uTarStartPos + i, curElement, tarType); } } } DEF_RUNTIME_STUBS(CallInternalGetter) { RUNTIME_STUBS_HEADER(CallInternalGetter); JSTaggedType argAccessor = GetTArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle argReceiver = GetHArg(argv, argc, 1); // 1: means the first parameter auto accessor = AccessorData::Cast(reinterpret_cast(argAccessor)); return accessor->CallInternalGet(thread, argReceiver).GetRawData(); } DEF_RUNTIME_STUBS(CallInternalSetter) { RUNTIME_STUBS_HEADER(CallInternalSetter); JSHandle receiver = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedType argSetter = GetTArg(argv, argc, 1); // 1: means the first parameter JSHandle value = GetHArg(argv, argc, 2); // 2: means the second parameter auto setter = AccessorData::Cast((reinterpret_cast(argSetter))); auto result = setter->CallInternalSet(thread, receiver, value, true); if (!result) { return JSTaggedValue::Exception().GetRawData(); } return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(CallInternalSetterNoThrow) { RUNTIME_STUBS_HEADER(CallInternalSetterNoThrow); JSHandle receiver = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedType argSetter = GetTArg(argv, argc, 1); // 1: means the first parameter JSHandle value = GetHArg(argv, argc, 2); // 2: means the second parameter auto setter = AccessorData::Cast((reinterpret_cast(argSetter))); bool result = setter->CallInternalSet(thread, receiver, value, false); return result ? JSTaggedValue::Undefined().GetRawData() : JSTaggedValue::False().GetRawData(); } DEF_RUNTIME_STUBS(GetHash32) { JSTaggedValue argKey = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue len = GetArg(argv, argc, 1); // 1: means the first parameter int key = argKey.GetInt(); auto pkey = reinterpret_cast(&key); uint32_t result = panda::GetHash32(pkey, len.GetInt()); return JSTaggedValue(static_cast(result)).GetRawData(); } DEF_RUNTIME_STUBS(NewInternalString) { RUNTIME_STUBS_HEADER(NewInternalString); JSHandle keyHandle = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return JSTaggedValue(thread->GetEcmaVM()->GetFactory()->InternString(keyHandle)).GetRawData(); } DEF_RUNTIME_STUBS(NewTaggedArray) { RUNTIME_STUBS_HEADER(NewTaggedArray); JSTaggedValue length = GetArg(argv, argc, 0); // 0: means the zeroth parameter ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); return factory->NewTaggedArray(length.GetInt()).GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(CopyArray) { RUNTIME_STUBS_HEADER(CopyArray); JSHandle array = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue length = GetArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue capacity = GetArg(argv, argc, 2); // 2: means the second parameter ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); return factory->CopyArray(array, length.GetInt(), capacity.GetInt()).GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(RTSubstitution) { RUNTIME_STUBS_HEADER(RTSubstitution); JSHandle matched = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle srcString = GetHArg(argv, argc, 1); // 1: means the first parameter int position = GetArg(argv, argc, 2).GetInt(); // 2: means the second parameter ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle captureList = factory->EmptyArray(); JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); JSHandle replacement = GetHArg(argv, argc, 3); // 3: means the third parameter JSTaggedValue result = builtins::BuiltinsString::GetSubstitution(thread, matched, srcString, position, captureList, undefined, replacement); return result.GetRawData(); } DEF_RUNTIME_STUBS(NameDictPutIfAbsent) { RUNTIME_STUBS_HEADER(NameDictPutIfAbsent); JSTaggedType receiver = GetTArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedType array = GetTArg(argv, argc, 1); // 1: means the first parameter JSHandle keyHandle = GetHArg(argv, argc, 2); // 2: means the second parameter JSHandle valueHandle = GetHArg(argv, argc, 3); // 3: means the third parameter JSTaggedValue attr = GetArg(argv, argc, 4); // 4: means the fourth parameter JSTaggedValue needTransToDict = GetArg(argv, argc, 5); // 5: means the fifth parameter PropertyAttributes propAttr(attr); if (needTransToDict.IsTrue()) { JSHandle objHandle(thread, JSTaggedValue(reinterpret_cast(receiver))); JSHandle dictHandle(JSObject::TransitionToDictionary(thread, objHandle)); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); return NameDictionary:: PutIfAbsent(thread, dictHandle, keyHandle, valueHandle, propAttr).GetTaggedValue().GetRawData(); } else { JSHandle dictHandle(thread, JSTaggedValue(reinterpret_cast(array))); return NameDictionary:: PutIfAbsent(thread, dictHandle, keyHandle, valueHandle, propAttr).GetTaggedValue().GetRawData(); } } DEF_RUNTIME_STUBS(NumberDictionaryPut) { RUNTIME_STUBS_HEADER(NumberDictionaryPut); JSTaggedType receiver = GetTArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedType array = GetTArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue key = GetArg(argv, argc, 2); // 2: means the second parameter JSHandle valueHandle = GetHArg(argv, argc, 3); // 3: means the third parameter JSTaggedValue attr = GetArg(argv, argc, 4); // 4: means the fourth parameter JSTaggedValue needTransToDict = GetArg(argv, argc, 5); // 5: means the fifth parameter JSHandle keyHandle(thread, key); PropertyAttributes propAttr(attr); JSHandle objHandle(thread, JSTaggedValue(reinterpret_cast(receiver))); if (needTransToDict.IsTrue()) { JSObject::ElementsToDictionary(thread, objHandle); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); JSHandle dict(thread, objHandle->GetElements(thread)); return NumberDictionary::Put(thread, dict, keyHandle, valueHandle, propAttr).GetTaggedValue().GetRawData(); } else { JSHandle dict(thread, JSTaggedValue(reinterpret_cast(array))); return NumberDictionary::Put(thread, dict, keyHandle, valueHandle, propAttr).GetTaggedValue().GetRawData(); } } DEF_RUNTIME_STUBS(PropertiesSetValue) { RUNTIME_STUBS_HEADER(PropertiesSetValue); JSHandle objHandle = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle valueHandle = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle arrayHandle = GetHArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue taggedCapacity = GetArg(argv, argc, 3); JSTaggedValue taggedIndex = GetArg(argv, argc, 4); int capacity = taggedCapacity.GetInt(); int index = taggedIndex.GetInt(); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle properties; if (capacity == 0) { properties = factory->NewTaggedArray(JSObject::MIN_PROPERTIES_LENGTH); } else { uint32_t maxNonInlinedFastPropsCapacity = objHandle->GetNonInlinedFastPropsCapacity(); uint32_t newLen = JSObject::ComputeNonInlinedFastPropsCapacity(thread, capacity, maxNonInlinedFastPropsCapacity); properties = factory->CopyArray(arrayHandle, capacity, newLen); } properties->Set(thread, index, valueHandle); objHandle->SetProperties(thread, properties); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(CheckAndCopyArray) { RUNTIME_STUBS_HEADER(CheckAndCopyArray); JSTaggedType argReceiver = GetTArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle receiverHandle(thread, reinterpret_cast(argReceiver)); JSArray::CheckAndCopyArray(thread, receiverHandle); return receiverHandle->GetElements(thread).GetRawData(); } DEF_RUNTIME_STUBS(JSArrayReduceUnStable) { RUNTIME_STUBS_HEADER(JSArrayReduceUnStable); JSHandle thisHandle = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle thisObjVal = GetHArg(argv, argc, 1); // 1: means the one parameter JSTaggedType taggedValueK = GetTArg(argv, argc, 2); // 2: means the two parameter int64_t k = JSTaggedNumber(JSTaggedValue(taggedValueK)).GetNumber(); JSTaggedType taggedValueLen = GetTArg(argv, argc, 3); // 3: means the three parameter int64_t len = JSTaggedNumber(JSTaggedValue(taggedValueLen)).GetNumber(); JSMutableHandle accumulator = JSMutableHandle(thread, GetHArg(argv, argc, 4)); // 4: means the four parameter JSHandle callbackFnHandle = GetHArg(argv, argc, 5); // 5: means the five parameter JSTaggedValue ret = builtins::BuiltinsArray::ReduceUnStableJSArray(thread, thisHandle, thisObjVal, k, len, accumulator, callbackFnHandle); return ret.GetRawData(); } DEF_RUNTIME_STUBS(JSObjectGrowElementsCapacity) { RUNTIME_STUBS_HEADER(JSObjectGrowElementsCapacity); JSHandle elements = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue length = GetArg(argv, argc, 1); // 1: means the zeroth parameter uint32_t newLength = static_cast(length.GetInt()); JSHandle newElements = JSObject::GrowElementsCapacity(thread, elements, newLength, true); return newElements.GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(NewEcmaHClass) { RUNTIME_STUBS_HEADER(NewEcmaHClass); JSTaggedValue size = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue type = GetArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue inlinedProps = GetArg(argv, argc, 2); // 2: means the second parameter return (thread->GetEcmaVM()->GetFactory()->NewEcmaHClass( size.GetInt(), JSType(type.GetInt()), inlinedProps.GetInt())).GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(JSArrayFilterUnStable) { RUNTIME_STUBS_HEADER(JSArrayFilterUnStable); JSHandle thisArgHandle = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle thisObjVal = GetHArg(argv, argc, 1); // 1: means the one parameter JSTaggedType taggedValueK = GetTArg(argv, argc, 2); // 2: means the two parameter int64_t k = JSTaggedNumber(JSTaggedValue(taggedValueK)).GetNumber(); JSTaggedType taggedValueLen = GetTArg(argv, argc, 3); // 3: means the three parameter int64_t len = JSTaggedNumber(JSTaggedValue(taggedValueLen)).GetNumber(); JSTaggedType toIndexValue = GetTArg(argv, argc, 4); // 4: means the three parameter int32_t toIndex = JSTaggedNumber(JSTaggedValue(toIndexValue)).GetNumber(); JSHandle newArrayHandle = JSMutableHandle(thread, GetHArg(argv, argc, 5)); // 5: means the four parameter JSHandle callbackFnHandle = GetHArg(argv, argc, 6); // 6: means the five parameter JSTaggedValue ret = builtins::BuiltinsArray::FilterUnStableJSArray(thread, thisArgHandle, thisObjVal, k, len, toIndex, newArrayHandle, callbackFnHandle); return ret.GetRawData(); } DEF_RUNTIME_STUBS(JSArrayMapUnStable) { RUNTIME_STUBS_HEADER(JSArrayMapUnStable); JSHandle thisArgHandle = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle thisObjVal = GetHArg(argv, argc, 1); // 1: means the one parameter JSTaggedType taggedValueK = GetTArg(argv, argc, 2); // 2: means the two parameter int64_t k = JSTaggedNumber(JSTaggedValue(taggedValueK)).GetNumber(); JSTaggedType taggedValueLen = GetTArg(argv, argc, 3); // 3: means the three parameter int64_t len = JSTaggedNumber(JSTaggedValue(taggedValueLen)).GetNumber(); JSHandle newArrayHandle = JSMutableHandle(thread, GetHArg(argv, argc, 4)); // 4: means the four parameter JSHandle callbackFnHandle = GetHArg(argv, argc, 5); // 5: means the five parameter JSTaggedValue ret = builtins::BuiltinsArray::MapUnStableJSArray(thread, thisArgHandle, thisObjVal, k, len, newArrayHandle, callbackFnHandle); return ret.GetRawData(); } DEF_RUNTIME_STUBS(UpdateLayOutAndAddTransition) { RUNTIME_STUBS_HEADER(UpdateLayOutAndAddTransition); JSHandle oldHClassHandle = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle newHClassHandle = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle keyHandle = GetHArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue attr = GetArg(argv, argc, 3); // 3: means the third parameter PropertyAttributes attrValue(attr); JSHClass::AddPropertyToNewHClass(thread, oldHClassHandle, newHClassHandle, keyHandle, attrValue); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(CopyAndUpdateObjLayout) { RUNTIME_STUBS_HEADER(CopyAndUpdateObjLayout); JSHandle newHClassHandle = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle keyHandle = GetHArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue attr = GetArg(argv, argc, 3); // 3: means the third parameter auto factory = thread->GetEcmaVM()->GetFactory(); PropertyAttributes attrValue(attr); // 1. Copy JSHandle oldLayout(thread, newHClassHandle->GetLayout(thread)); JSHandle newLayout(factory->CopyLayoutInfo(oldLayout)); newHClassHandle->SetLayout(thread, newLayout); // 2. Update attr auto hclass = JSHClass::Cast(newHClassHandle.GetTaggedValue().GetTaggedObject()); int entry = JSHClass::FindPropertyEntry(thread, hclass, keyHandle.GetTaggedValue()); ASSERT(entry != -1); newLayout->SetNormalAttr(thread, entry, attrValue); // 3. Maybe Transition And Maintain subtypeing check return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(UpdateHClassForElementsKind) { RUNTIME_STUBS_HEADER(UpdateHClassForElementsKind); JSHandle receiver = GetHArg(argv, argc, 0); // 0: means the first parameter ElementsKind elementsKind = static_cast(GetTArg(argv, argc, 1)); // 1: means the first parameter // 1: means the first parameter ASSERT(receiver->IsJSArray()); auto array = JSHandle(receiver); ASSERT(JSHClass::IsInitialArrayHClassWithElementsKind(thread, receiver->GetTaggedObject()->GetClass(), receiver->GetTaggedObject()->GetClass()->GetElementsKind())); if (!JSHClass::TransitToElementsKindUncheck(thread, JSHandle(array), elementsKind)) { return JSTaggedValue::Hole().GetRawData(); } if (thread->IsEnableElementsKind() || thread->IsPGOProfilerEnable()) { // Update TrackInfo JSHandle(receiver)->UpdateTrackInfo(thread); } if (!thread->IsPGOProfilerEnable()) { return JSTaggedValue::Hole().GetRawData(); } JSTaggedValue trackInfoVal = JSHandle(receiver)->GetTrackInfo(thread); if (trackInfoVal.IsHeapObject() && trackInfoVal.IsWeak()) { TrackInfo *trackInfo = TrackInfo::Cast(trackInfoVal.GetWeakReferentUnChecked()); thread->GetEcmaVM()->GetPGOProfiler()->UpdateTrackInfo(JSTaggedValue(trackInfo)); } return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(NewMutantTaggedArray) { RUNTIME_STUBS_HEADER(NewMutantTaggedArray); JSTaggedValue length = GetArg(argv, argc, 0); // 0: means the zeroth parameter ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); return factory->NewMutantTaggedArray(length.GetInt()).GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(NewCOWMutantTaggedArray) { RUNTIME_STUBS_HEADER(NewCOWMutantTaggedArray); JSTaggedValue length = GetArg(argv, argc, 0); // 0: means the zeroth parameter ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); return factory->NewCOWMutantTaggedArray(length.GetInt()).GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(NewCOWTaggedArray) { RUNTIME_STUBS_HEADER(NewCOWTaggedArray); JSTaggedValue length = GetArg(argv, argc, 0); // 0: means the zeroth parameter ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); return factory->NewCOWMutantTaggedArray(length.GetInt()).GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(ForceGC) { RUNTIME_STUBS_HEADER(ForceGC); if (!thread->GetEcmaVM()->GetJSOptions().EnableForceGC()) { return JSTaggedValue::Hole().GetRawData(); } if (g_isEnableCMCGC) { common::BaseRuntime::RequestGC(common::GC_REASON_USER, true, common::GC_TYPE_FULL); } else { thread->GetEcmaVM()->CollectGarbage(TriggerGCType::FULL_GC); } return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(RuntimeDump) { RUNTIME_STUBS_HEADER(RuntimeDump); JSHandle obj = JSHandle(GetHArg(argv, argc, 0)); { std::ostringstream oss; obj->Dump(thread, oss); LOG_ECMA(ERROR) << "RuntimeDump: " << oss.str(); } LOG_ECMA(ERROR) << "---------- before force gc ---------------"; { thread->GetEcmaVM()->CollectGarbage(TriggerGCType::FULL_GC); } LOG_ECMA(ERROR) << "---------- end force gc ---------------"; return JSTaggedValue::Hole().GetRawData(); } void RuntimeStubs::Dump(JSTaggedType rawValue) { DISALLOW_GARBAGE_COLLECTION; std::ostringstream oss; auto value = JSTaggedValue(rawValue); value.Dump(THREAD_ARG_PLACEHOLDER, oss); LOG_ECMA(INFO) << "dump log for read-only crash " << oss.str(); } void RuntimeStubs::DebugDump(JSTaggedType rawValue) { DISALLOW_GARBAGE_COLLECTION; DebugDumpWithHint(reinterpret_cast(nullptr), rawValue); } void RuntimeStubs::DumpWithHint(uintptr_t hintStrAddress, JSTaggedType rawValue) { DISALLOW_GARBAGE_COLLECTION; const char *origHintStr = reinterpret_cast(hintStrAddress); // May be nullptr const char *hintStr = (origHintStr == nullptr) ? "" : origHintStr; DumpToStreamWithHint(std::cout, hintStr, JSTaggedValue(rawValue)); std::cout << std::endl; // New line } void RuntimeStubs::DebugDumpWithHint(uintptr_t hintStrAddress, JSTaggedType rawValue) { DISALLOW_GARBAGE_COLLECTION; const char *origHintStr = reinterpret_cast(hintStrAddress); // May be nullptr const char *hintStr = (origHintStr == nullptr) ? "" : origHintStr; // The immediate lambda expression call is not evaluated when the logger is unabled. LOG_ECMA(DEBUG) << [](const char *hintStr, JSTaggedType rawValue) { std::ostringstream out; DumpToStreamWithHint(out, hintStr, JSTaggedValue(rawValue)); return out.str(); }(hintStr, rawValue); } void RuntimeStubs::DumpToStreamWithHint(std::ostream &out, std::string_view hint, JSTaggedValue value) { constexpr std::string_view dumpDelimiterLine = "================"; // Begin line out << dumpDelimiterLine << " Begin dump: " << hint << ' ' << dumpDelimiterLine << std::endl; // Dumps raw data out << "(Raw value = 0x" << std::setw(base::INT64_HEX_DIGITS) << std::hex << std::setfill('0') << value.GetRawData() << ") "; out << std::dec << std::setfill(' '); // Recovers integer radix & fill character // Dumps tagged value value.Dump(THREAD_ARG_PLACEHOLDER, out); // End line out << dumpDelimiterLine << " End dump: " << hint << ' ' << dumpDelimiterLine; } void RuntimeStubs::DebugPrint(int fmtMessageId, ...) { std::string format = MessageString::GetMessageString(fmtMessageId); va_list args; va_start(args, fmtMessageId); std::string result = base::StringHelper::Vformat(format.c_str(), args); if (MessageString::IsBuiltinsStubMessageString(fmtMessageId)) { LOG_BUILTINS(DEBUG) << result; } else { LOG_ECMA(DEBUG) << result; } va_end(args); } void RuntimeStubs::DebugPrintCustom(uintptr_t fmt, ...) { va_list args; va_start(args, fmt); std::string result = base::StringHelper::Vformat(reinterpret_cast(fmt), args); LOG_ECMA(DEBUG) << result; va_end(args); } void RuntimeStubs::DebugPrintInstruction([[maybe_unused]] uintptr_t argGlue, const uint8_t *pc) { BytecodeInstruction inst(pc); LOG_INTERPRETER(DEBUG) << inst; } void RuntimeStubs::CollectingOpcodes([[maybe_unused]] uintptr_t argGlue, const uint8_t *pc) { #if ECMASCRIPT_ENABLE_COLLECTING_OPCODES BytecodeInstruction inst(pc); auto thread = JSThread::GlueToJSThread(argGlue); auto vm = thread->GetEcmaVM(); auto opcode = inst.GetOpcode(); std::stack> &bytecodeStatsStack_ = vm->GetBytecodeStatsStack(); if (bytecodeStatsStack_.empty()) { return; } std::unordered_map &bytecodeStatsMap_ = bytecodeStatsStack_.top(); auto foundInst = bytecodeStatsMap_.find(opcode); if (foundInst != bytecodeStatsMap_.end()) { ++foundInst->second; } else { bytecodeStatsMap_[opcode] = 1; } LOG_INTERPRETER(DEBUG) << inst; #endif } void RuntimeStubs::DebugOsrEntry([[maybe_unused]] uintptr_t argGlue, const uint8_t *codeEntry) { LOG_JIT(DEBUG) << "[OSR]: Enter OSR Code: " << reinterpret_cast(codeEntry); } void RuntimeStubs::Comment(uintptr_t argStr) { std::string str(reinterpret_cast(argStr)); LOG_ECMA(DEBUG) << str; } void RuntimeStubs::FatalPrint(int fmtMessageId, ...) { std::string format = MessageString::GetMessageString(fmtMessageId); va_list args; va_start(args, fmtMessageId); std::string result = base::StringHelper::Vformat(format.c_str(), args); LOG_FULL(FATAL) << result; va_end(args); LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); } void RuntimeStubs::FatalPrintCustom(uintptr_t fmt, ...) { va_list args; va_start(args, fmt); std::string result = base::StringHelper::Vformat(reinterpret_cast(fmt), args); LOG_FULL(FATAL) << result; va_end(args); LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); } DEF_RUNTIME_STUBS(NoticeThroughChainAndRefreshUser) { RUNTIME_STUBS_HEADER(NoticeThroughChainAndRefreshUser); JSHandle oldHClassHandle = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle newHClassHandle = GetHArg(argv, argc, 1); // 1: means the first parameter JSHClass::NotifyHClassNotPrototypeChanged(thread, newHClassHandle); JSHClass::NoticeThroughChain(thread, oldHClassHandle); JSHClass::RefreshUsers(thread, oldHClassHandle, newHClassHandle); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(GetNativePcOfstForBaseline) { RUNTIME_STUBS_HEADER(GetNativePcOfstForBaseline); JSHandle func = GetHArg(argv, argc, 0); // 0: means the zeroth parameter uint64_t bytecodePc = static_cast(GetTArg(argv, argc, 1)); // 1: means the first parameter return RuntimeGetNativePcOfstForBaseline(thread, func, bytecodePc); } DEF_RUNTIME_STUBS(Inc) { RUNTIME_STUBS_HEADER(Inc); JSHandle value = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeInc(thread, value).GetRawData(); } DEF_RUNTIME_STUBS(Dec) { RUNTIME_STUBS_HEADER(Dec); JSHandle value = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeDec(thread, value).GetRawData(); } DEF_RUNTIME_STUBS(CallGetPrototype) { RUNTIME_STUBS_HEADER(CallGetPrototype); JSHandle proxy = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return JSProxy::GetPrototype(thread, proxy).GetRawData(); } DEF_RUNTIME_STUBS(RegularJSObjDeletePrototype) { RUNTIME_STUBS_HEADER(RegularJSObjDeletePrototype); JSHandle tagged = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue value = GetArg(argv, argc, 1); uint32_t index = 0; if (value.IsString()) { auto string = JSHandle(thread, value); if (EcmaStringAccessor(string).ToElementIndex(thread, &index)) { value = JSTaggedValue(index); } else if (!EcmaStringAccessor(string).IsInternString()) { JSTaggedValue key(RuntimeTryGetInternString(argGlue, string)); if (key.IsHole()) { return JSTaggedValue::True().GetRawData(); } else { value = key; } } } auto result = JSObject::DeleteProperty(thread, tagged, JSHandle(thread, value)); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); if (!result) { auto factory = thread->GetEcmaVM()->GetFactory(); JSHandle error = factory->GetJSError(ErrorType::TYPE_ERROR, "Cannot delete property", StackCheck::NO); thread->SetException(error.GetTaggedValue()); return JSTaggedValue::Exception().GetRawData(); } return JSTaggedValue::True().GetRawData(); } DEF_RUNTIME_STUBS(CallJSObjDeletePrototype) { RUNTIME_STUBS_HEADER(CallJSObjDeletePrototype); JSHandle tagged = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle value = GetHArg(argv, argc, 1); auto result = JSTaggedValue::DeleteProperty(thread, tagged, value); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); if (!result) { auto factory = thread->GetEcmaVM()->GetFactory(); JSHandle error = factory->GetJSError(ErrorType::TYPE_ERROR, "Cannot delete property", StackCheck::NO); thread->SetException(error.GetTaggedValue()); return JSTaggedValue::Exception().GetRawData(); } return JSTaggedValue::True().GetRawData(); } DEF_RUNTIME_STUBS(ToPropertyKey) { RUNTIME_STUBS_HEADER(ToPropertyKey); JSHandle key = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue res = JSTaggedValue::ToPropertyKey(thread, key).GetTaggedValue(); return res.GetRawData(); } DEF_RUNTIME_STUBS(Exp) { RUNTIME_STUBS_HEADER(Exp); JSTaggedValue baseValue = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue exponentValue = GetArg(argv, argc, 1); // 1: means the first parameter if (baseValue.IsNumber() && exponentValue.IsNumber()) { // fast path double doubleBase = baseValue.IsInt() ? baseValue.GetInt() : baseValue.GetDouble(); double doubleExponent = exponentValue.IsInt() ? exponentValue.GetInt() : exponentValue.GetDouble(); if ((std::abs(doubleBase) == 1 && std::isinf(doubleExponent)) || std::isnan(doubleExponent)) { return JSTaggedValue(base::NAN_VALUE).GetRawData(); } if ((doubleBase == 0 && ((base::bit_cast(doubleBase)) & base::DOUBLE_SIGN_MASK) == base::DOUBLE_SIGN_MASK) && std::isfinite(doubleExponent) && base::NumberHelper::TruncateDouble(doubleExponent) == doubleExponent && base::NumberHelper::TruncateDouble(doubleExponent / 2) + base::HALF == // 2 : half (doubleExponent / 2)) { // 2 : half if (doubleExponent > 0) { return JSTaggedValue(-0.0).GetRawData(); } if (doubleExponent < 0) { return JSTaggedValue(-base::POSITIVE_INFINITY).GetRawData(); } } return JSTaggedValue(std::pow(doubleBase, doubleExponent)).GetRawData(); } // Slow path JSTaggedValue res = RuntimeExp(thread, baseValue, exponentValue); return res.GetRawData(); } DEF_RUNTIME_STUBS(IsIn) { RUNTIME_STUBS_HEADER(IsIn); JSHandle prop = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle obj = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeIsIn(thread, prop, obj).GetRawData(); } DEF_RUNTIME_STUBS(InstanceOf) { RUNTIME_STUBS_HEADER(InstanceOf); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle target = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeInstanceof(thread, obj, target).GetRawData(); } DEF_RUNTIME_STUBS(DumpObject) { RUNTIME_STUBS_HEADER(DumpObject); JSHandle target = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle targetId = GetHArg(argv, argc, 1); // 1: means the first parameter LOG_ECMA(INFO) << "InstanceOf Stability Testing Num: " << targetId->GetInt(); std::ostringstream oss; target->Dump(thread, oss); LOG_ECMA(INFO) << "dump log for instance of target: " << oss.str(); return JSTaggedValue::True().GetRawData(); } DEF_RUNTIME_STUBS(DumpHeapObjectAddress) { RUNTIME_STUBS_HEADER(DumpHeapObjectAddress); JSHandle target = GetHArg(argv, argc, 0); // 0: means the zeroth parameter std::ostringstream oss; target->DumpHeapObjAddress(thread, oss); LOG_ECMA(INFO) << "dump log for instance of target: " << oss.str(); return JSTaggedValue::True().GetRawData(); } DEF_RUNTIME_STUBS(BigIntConstructor) { RUNTIME_STUBS_HEADER(BigIntConstructor); JSHandle value = GetHArg(argv, argc, 0); return builtins::BuiltinsBigInt::BigIntConstructorInternal(thread, value).GetRawData(); } DEF_RUNTIME_STUBS(CreateGeneratorObj) { RUNTIME_STUBS_HEADER(CreateGeneratorObj); JSHandle genFunc = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeCreateGeneratorObj(thread, genFunc).GetRawData(); } DEF_RUNTIME_STUBS(CreateAsyncGeneratorObj) { RUNTIME_STUBS_HEADER(CreateAsyncGeneratorObj); JSHandle genFunc = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeCreateAsyncGeneratorObj(thread, genFunc).GetRawData(); } DEF_RUNTIME_STUBS(GetTemplateObject) { RUNTIME_STUBS_HEADER(GetTemplateObject); JSHandle literal = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeGetTemplateObject(thread, literal).GetRawData(); } DEF_RUNTIME_STUBS(CreateStringIterator) { RUNTIME_STUBS_HEADER(CreateStringIterator); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return JSStringIterator::CreateStringIterator(thread, JSHandle(obj)).GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(NewJSArrayIterator) { RUNTIME_STUBS_HEADER(NewJSArrayIterator); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); return factory->NewJSArrayIterator(obj, IterationKind::VALUE).GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(NewJSTypedArrayIterator) { RUNTIME_STUBS_HEADER(NewJSArrayIterator); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter base::TypedArrayHelper::ValidateTypedArray(thread, obj); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle iter(factory->NewJSArrayIterator(JSHandle(obj), IterationKind::VALUE)); return iter.GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(StringIteratorNext) { RUNTIME_STUBS_HEADER(StringIteratorNext); JSHandle thisObj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return builtins::BuiltinsStringIterator::NextInternal(thread, thisObj).GetRawData(); } DEF_RUNTIME_STUBS(ArrayIteratorNext) { RUNTIME_STUBS_HEADER(ArrayIteratorNext); JSHandle thisObj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return JSArrayIterator::NextInternal(thread, thisObj).GetRawData(); } DEF_RUNTIME_STUBS(IteratorReturn) { RUNTIME_STUBS_HEADER(IteratorReturn); JSHandle thisObj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return builtins::BuiltinsIterator::ReturnInternal(thread, thisObj).GetRawData(); } DEF_RUNTIME_STUBS(GetNextPropNameSlowpath) { RUNTIME_STUBS_HEADER(GetNextPropNameSlowpath); JSHandle iter = GetHArg(argv, argc, 0); // 0: means the zeroth parameter ASSERT(iter->IsForinIterator()); JSTaggedValue res = JSForInIterator::NextInternalSlowpath(thread, JSHandle::Cast(iter)); return res.GetRawData(); } DEF_RUNTIME_STUBS(CloseIterator) { RUNTIME_STUBS_HEADER(CloseIterator); JSHandle iter = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeCloseIterator(thread, iter).GetRawData(); } DEF_RUNTIME_STUBS(SuperCallSpread) { RUNTIME_STUBS_HEADER(SuperCallSpread); JSHandle func = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle array = GetHArg(argv, argc, 1); // 1: means the first parameter auto sp = const_cast(thread->GetCurrentInterpretedFrame()); JSTaggedValue function = InterpreterAssembly::GetNewTarget(thread, sp); return RuntimeSuperCallSpread(thread, func, JSHandle(thread, function), array).GetRawData(); } DEF_RUNTIME_STUBS(OptSuperCallSpread) { RUNTIME_STUBS_HEADER(OptSuperCallSpread); JSHandle func = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle newTarget = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle taggedArray = GetHArg(argv, argc, 2); // 2: means the second parameter return RuntimeOptSuperCallSpread(thread, func, newTarget, taggedArray).GetRawData(); } DEF_RUNTIME_STUBS(SuperCallForwardAllArgs) { RUNTIME_STUBS_HEADER(SuperCallForwardAllArgs); auto sp = const_cast(thread->GetCurrentInterpretedFrame()); JSHandle func = GetHArg(argv, argc, 0); // 0: index of child constructor JSHandle superFunc(thread, JSTaggedValue::GetPrototype(thread, func)); auto newTarget = JSHandle(thread, InterpreterAssembly::GetNewTarget(thread, sp)); uint32_t startIdx = 0; uint32_t restNumArgs = InterpreterAssembly::GetNumArgs(thread, sp, 0, startIdx); // 0: rest args start idx return RuntimeSuperCallForwardAllArgs(thread, sp, superFunc, newTarget, restNumArgs, startIdx).GetRawData(); } DEF_RUNTIME_STUBS(OptSuperCallForwardAllArgs) { RUNTIME_STUBS_HEADER(OptSuperCallForwardAllArgs); JSTaggedType *sp = reinterpret_cast(GetActualArgv(thread)); JSHandle superFunc = GetHArg(argv, argc, 0); // 0: index of super constructor JSHandle newTarget = GetHArg(argv, argc, 1); // 1: index of newTarget int actualArgc = GetArg(argv, argc, 2).GetInt(); // 2: index of actual argc ASSERT(actualArgc >= 0); uint32_t convertedActualArgc = static_cast(actualArgc); ASSERT(convertedActualArgc >= NUM_MANDATORY_JSFUNC_ARGS); uint32_t restNumArgs = convertedActualArgc - NUM_MANDATORY_JSFUNC_ARGS; uint32_t startIdx = NUM_MANDATORY_JSFUNC_ARGS; return RuntimeSuperCallForwardAllArgs(thread, sp, superFunc, newTarget, restNumArgs, startIdx).GetRawData(); } DEF_RUNTIME_STUBS(GetCallSpreadArgs) { RUNTIME_STUBS_HEADER(GetCallSpreadArgs); JSHandle jsArray = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeGetCallSpreadArgs(thread, jsArray).GetRawData(); } DEF_RUNTIME_STUBS(DelObjProp) { RUNTIME_STUBS_HEADER(DelObjProp); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle prop = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeDelObjProp(thread, obj, prop).GetRawData(); } DEF_RUNTIME_STUBS(NewObjApply) { RUNTIME_STUBS_HEADER(NewObjApply); JSHandle func = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle array = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeNewObjApply(thread, func, array).GetRawData(); } DEF_RUNTIME_STUBS(CreateIterResultObj) { RUNTIME_STUBS_HEADER(CreateIterResultObj); JSHandle value = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue flag = GetArg(argv, argc, 1); // 1: means the first parameter return RuntimeCreateIterResultObj(thread, value, flag).GetRawData(); } DEF_RUNTIME_STUBS(AsyncFunctionAwaitUncaught) { RUNTIME_STUBS_HEADER(AsyncFunctionAwaitUncaught); JSHandle asyncFuncObj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle value = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeAsyncFunctionAwaitUncaught(thread, asyncFuncObj, value).GetRawData(); } DEF_RUNTIME_STUBS(AsyncFunctionResolveOrReject) { RUNTIME_STUBS_HEADER(AsyncFunctionResolveOrReject); JSHandle asyncFuncObj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle value = GetHArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue isResolve = GetArg(argv, argc, 2); // 2: means the second parameter return RuntimeAsyncFunctionResolveOrReject(thread, asyncFuncObj, value, isResolve.IsTrue()).GetRawData(); } DEF_RUNTIME_STUBS(AsyncGeneratorResolve) { RUNTIME_STUBS_HEADER(AsyncGeneratorResolve); JSHandle asyncGenerator = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle value = GetHArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue flag = GetArg(argv, argc, 2); // 2: means the second parameter return RuntimeAsyncGeneratorResolve(thread, asyncGenerator, value, flag).GetRawData(); } DEF_RUNTIME_STUBS(AsyncGeneratorReject) { RUNTIME_STUBS_HEADER(AsyncGeneratorReject); JSHandle asyncGenerator = GetHArg(argv, argc, 0); JSHandle value = GetHArg(argv, argc, 1); return RuntimeAsyncGeneratorReject(thread, asyncGenerator, value).GetRawData(); } DEF_RUNTIME_STUBS(SetGeneratorState) { RUNTIME_STUBS_HEADER(SetGeneratorState); JSHandle asyncGenerator = GetHArg(argv, argc, 0); JSTaggedValue index = GetArg(argv, argc, 1); RuntimeSetGeneratorState(thread, asyncGenerator, index.GetInt()); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(CopyDataProperties) { RUNTIME_STUBS_HEADER(CopyDataProperties); JSHandle dst = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle src = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeCopyDataProperties(thread, dst, src).GetRawData(); } DEF_RUNTIME_STUBS(StArraySpread) { RUNTIME_STUBS_HEADER(StArraySpread); JSHandle dst = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue index = GetArg(argv, argc, 1); // 1: means the first parameter JSHandle src = GetHArg(argv, argc, 2); // 2: means the second parameter return RuntimeStArraySpread(thread, dst, index, src).GetRawData(); } DEF_RUNTIME_STUBS(GetIteratorNext) { RUNTIME_STUBS_HEADER(GetIteratorNext); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle method = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeGetIteratorNext(thread, obj, method).GetRawData(); } DEF_RUNTIME_STUBS(SetObjectWithProto) { RUNTIME_STUBS_HEADER(SetObjectWithProto); JSHandle proto = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle obj = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeSetObjectWithProto(thread, proto, obj).GetRawData(); } DEF_RUNTIME_STUBS(LoadICByValue) { RUNTIME_STUBS_HEADER(LoadICByValue); JSHandle profileTypeInfo = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle receiver = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle key = GetHArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue slotId = GetArg(argv, argc, 3); // 3: means the third parameter JSTaggedValue::RequireObjectCoercible(thread, receiver, "Cannot load property of null or undefined"); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); if (profileTypeInfo->IsUndefined()) { return RuntimeLdObjByValue(thread, receiver, key, false, JSTaggedValue::Undefined()).GetRawData(); } JSHandle propKey = JSTaggedValue::ToPropertyKey(thread, key); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); LoadICRuntime icRuntime(thread, JSHandle::Cast(profileTypeInfo), slotId.GetInt(), ICKind::LoadIC); return icRuntime.LoadValueMiss(receiver, propKey).GetRawData(); } DEF_RUNTIME_STUBS(StoreICByValue) { RUNTIME_STUBS_HEADER(StoreICByValue); JSHandle profileTypeInfo = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle receiver = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle key = GetHArg(argv, argc, 2); // 2: means the second parameter JSHandle value = GetHArg(argv, argc, 3); // 3: means the third parameter JSTaggedValue slotId = GetArg(argv, argc, 4); // 4: means the fourth parameter if (profileTypeInfo->IsUndefined()) { return RuntimeStObjByValue(thread, receiver, key, value).GetRawData(); } JSHandle propKey = JSTaggedValue::ToPropertyKey(thread, key); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); StoreICRuntime icRuntime(thread, JSHandle::Cast(profileTypeInfo), slotId.GetInt(), ICKind::StoreIC); return icRuntime.StoreMiss(receiver, propKey, value).GetRawData(); } DEF_RUNTIME_STUBS(StoreOwnICByValue) { RUNTIME_STUBS_HEADER(StoreOwnICByValue); JSHandle profileTypeInfo = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle receiver = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle key = GetHArg(argv, argc, 2); // 2: means the second parameter JSHandle value = GetHArg(argv, argc, 3); // 3: means the third parameter JSTaggedValue slotId = GetArg(argv, argc, 4); // 4: means the fourth parameter if (profileTypeInfo->IsUndefined()) { return RuntimeStOwnByIndex(thread, receiver, key, value).GetRawData(); } JSHandle propKey = JSTaggedValue::ToPropertyKey(thread, key); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); StoreICRuntime icRuntime(thread, JSHandle::Cast(profileTypeInfo), slotId.GetInt(), ICKind::StoreIC); return icRuntime.StoreMiss(receiver, propKey, value, true).GetRawData(); } DEF_RUNTIME_STUBS(StOwnByValue) { RUNTIME_STUBS_HEADER(StOwnByValue); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle key = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle value = GetHArg(argv, argc, 2); // 2: means the second parameter return RuntimeStOwnByValue(thread, obj, key, value).GetRawData(); } DEF_RUNTIME_STUBS(LdSuperByValue) { RUNTIME_STUBS_HEADER(LdSuperByValue); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle key = GetHArg(argv, argc, 1); // 1: means the first parameter auto sp = const_cast(thread->GetCurrentInterpretedFrame()); JSTaggedValue thisFunc = InterpreterAssembly::GetFunction(sp); return RuntimeLdSuperByValue(thread, obj, key, thisFunc).GetRawData(); } DEF_RUNTIME_STUBS(OptLdSuperByValue) { RUNTIME_STUBS_HEADER(OptLdSuperByValue); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle key = GetHArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue thisFunc = GetArg(argv, argc, 2); // 2: means the second parameter return RuntimeLdSuperByValue(thread, obj, key, thisFunc).GetRawData(); } DEF_RUNTIME_STUBS(StSuperByValue) { RUNTIME_STUBS_HEADER(StSuperByValue); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle key = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle value = GetHArg(argv, argc, 2); // 2: means the second parameter auto sp = const_cast(thread->GetCurrentInterpretedFrame()); JSTaggedValue thisFunc = InterpreterAssembly::GetFunction(sp); return RuntimeStSuperByValue(thread, obj, key, value, thisFunc).GetRawData(); } DEF_RUNTIME_STUBS(OptStSuperByValue) { RUNTIME_STUBS_HEADER(OptStSuperByValue); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle key = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle value = GetHArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue thisFunc = GetArg(argv, argc, 3); // 3: means the third parameter return RuntimeStSuperByValue(thread, obj, key, value, thisFunc).GetRawData(); } DEF_RUNTIME_STUBS(GetMethodFromCache) { RUNTIME_STUBS_HEADER(GetMethodFromCache); JSHandle constpool = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue index = GetArg(argv, argc, 1); // 1: means the first parameter return ConstantPool::GetMethodFromCache( thread, constpool.GetTaggedValue(), index.GetInt()).GetRawData(); } DEF_RUNTIME_STUBS(GetStringFromCache) { RUNTIME_STUBS_HEADER(GetStringFromCache); JSHandle constpool = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue index = GetArg(argv, argc, 1); // 1: means the first parameter return ConstantPool::GetStringFromCache( thread, constpool.GetTaggedValue(), index.GetInt()).GetRawData(); } DEF_RUNTIME_STUBS(GetObjectLiteralFromCache) { RUNTIME_STUBS_HEADER(GetObjectLiteralFromCache); JSHandle constpool = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue index = GetArg(argv, argc, 1); // 1: means the first parameter JSHandle module = GetHArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue cp = thread->GetEcmaVM()->FindOrCreateUnsharedConstpool(constpool.GetTaggedValue()); return ConstantPool::GetLiteralFromCache( thread, cp, index.GetInt(), module.GetTaggedValue()).GetRawData(); } DEF_RUNTIME_STUBS(GetArrayLiteralFromCache) { RUNTIME_STUBS_HEADER(GetArrayLiteralFromCache); JSHandle constpool = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue index = GetArg(argv, argc, 1); // 1: means the first parameter JSHandle module = GetHArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue cp = thread->GetEcmaVM()->FindOrCreateUnsharedConstpool(constpool.GetTaggedValue()); return ConstantPool::GetLiteralFromCache( thread, cp, index.GetInt(), module.GetTaggedValue()).GetRawData(); } DEF_RUNTIME_STUBS(StObjByValue) { RUNTIME_STUBS_HEADER(StObjByValue); JSHandle receiver = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle key = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle value = GetHArg(argv, argc, 2); // 2: means the second parameter return RuntimeStObjByValue(thread, receiver, key, value).GetRawData(); } DEF_RUNTIME_STUBS(LdObjByIndex) { RUNTIME_STUBS_HEADER(LdObjByIndex); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue idx = GetArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue callGetter = GetArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue receiver = GetArg(argv, argc, 3); // 3: means the third parameter return RuntimeLdObjByIndex(thread, obj, idx.GetInt(), callGetter.IsTrue(), receiver).GetRawData(); } DEF_RUNTIME_STUBS(StObjByIndex) { RUNTIME_STUBS_HEADER(StObjByIndex); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue idx = GetArg(argv, argc, 1); // 1: means the first parameter JSHandle value = GetHArg(argv, argc, 2); // 2: means the second parameter return RuntimeStObjByIndex(thread, obj, idx.GetInt(), value).GetRawData(); } DEF_RUNTIME_STUBS(StOwnByIndex) { RUNTIME_STUBS_HEADER(StOwnByIndex); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle idx = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle value = GetHArg(argv, argc, 2); // 2: means the second parameter return RuntimeStOwnByIndex(thread, obj, idx, value).GetRawData(); } DEF_RUNTIME_STUBS(StGlobalRecord) { RUNTIME_STUBS_HEADER(StGlobalRecord); JSHandle prop = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle value = GetHArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue isConst = GetArg(argv, argc, 2); return RuntimeStGlobalRecord(thread, prop, value, isConst.IsTrue()).GetRawData(); } DEF_RUNTIME_STUBS(Neg) { RUNTIME_STUBS_HEADER(Neg); JSHandle value = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeNeg(thread, value).GetRawData(); } DEF_RUNTIME_STUBS(Not) { RUNTIME_STUBS_HEADER(Not); JSHandle value = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeNot(thread, value).GetRawData(); } DEF_RUNTIME_STUBS(Shl2) { RUNTIME_STUBS_HEADER(Shl2); JSTaggedValue left = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue right = GetArg(argv, argc, 1); // 1: means the first parameter auto res = SlowRuntimeStub::Shl2(thread, left, right); return JSTaggedValue(res).GetRawData(); } DEF_RUNTIME_STUBS(Shr2) { RUNTIME_STUBS_HEADER(Shr2); JSTaggedValue left = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue right = GetArg(argv, argc, 1); // 1: means the first parameter auto res = SlowRuntimeStub::Shr2(thread, left, right); return JSTaggedValue(res).GetRawData(); } DEF_RUNTIME_STUBS(Ashr2) { RUNTIME_STUBS_HEADER(Ashr2); JSTaggedValue left = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue right = GetArg(argv, argc, 1); // 1: means the first parameter auto res = SlowRuntimeStub::Ashr2(thread, left, right); return JSTaggedValue(res).GetRawData(); } DEF_RUNTIME_STUBS(And2) { RUNTIME_STUBS_HEADER(And2); JSTaggedValue left = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue right = GetArg(argv, argc, 1); // 1: means the first parameter auto res = SlowRuntimeStub::And2(thread, left, right); return JSTaggedValue(res).GetRawData(); } DEF_RUNTIME_STUBS(Xor2) { RUNTIME_STUBS_HEADER(Xor2); JSTaggedValue left = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue right = GetArg(argv, argc, 1); // 1: means the first parameter auto res = SlowRuntimeStub::Xor2(thread, left, right); return JSTaggedValue(res).GetRawData(); } DEF_RUNTIME_STUBS(Or2) { RUNTIME_STUBS_HEADER(Or2); JSTaggedValue left = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue right = GetArg(argv, argc, 1); // 1: means the first parameter auto res = SlowRuntimeStub::Or2(thread, left, right); return JSTaggedValue(res).GetRawData(); } DEF_RUNTIME_STUBS(CreateClassWithBuffer) { RUNTIME_STUBS_HEADER(CreateClassWithBuffer); JSHandle base = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle lexenv = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle constpool = GetHArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue methodId = GetArg(argv, argc, 3); // 3: means the third parameter JSTaggedValue literalId = GetArg(argv, argc, 4); // 4: means the four parameter JSHandle module = GetHArg(argv, argc, 5); // 5: means the fifth parameter JSHandle length = GetHArg(argv, argc, 6); // 6: means the sixth parameter auto res = RuntimeCreateClassWithBuffer(thread, base, lexenv, constpool, static_cast(methodId.GetInt()), static_cast(literalId.GetInt()), module, length); #if ECMASCRIPT_ENABLE_IC const uint32_t INDEX_OF_SLOT_ID = 7; // 7: index of slotId in argv if (argc > INDEX_OF_SLOT_ID) { RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); uint16_t slotId = static_cast(GetArg(argv, argc, INDEX_OF_SLOT_ID).GetInt()); const uint32_t INDEX_OF_JS_FUNC = 8; // 8: index of jsFunc in argv ASSERT(argc > INDEX_OF_JS_FUNC); JSHandle jsFuncHandle = GetHArg(argv, argc, INDEX_OF_JS_FUNC); JSHandle resHandle(thread, res); SetProfileTypeInfoCellToFunction(thread, jsFuncHandle, resHandle, slotId); res = resHandle.GetTaggedValue(); } #endif return res.GetRawData(); } DEF_RUNTIME_STUBS(CreateSharedClass) { RUNTIME_STUBS_HEADER(CreateSharedClass); JSHandle base = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle constpool = GetHArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue methodId = GetArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue literalId = GetArg(argv, argc, 3); // 3: means the third parameter JSTaggedValue length = GetArg(argv, argc, 4); // 4: means the fourth parameter JSHandle module = GetHArg(argv, argc, 5); // 5: means the fifth parameter return RuntimeCreateSharedClass(thread, base, constpool, static_cast(methodId.GetInt()), static_cast(literalId.GetInt()), static_cast(length.GetInt()), module).GetRawData(); } DEF_RUNTIME_STUBS(LdSendableClass) { RUNTIME_STUBS_HEADER(LdSendableClass); JSHandle env = GetHArg(argv, argc, 0); // 0: means the zeroth parameter uint16_t level = static_cast(GetArg(argv, argc, 1).GetInt()); // 1: means the first parameter return RuntimeLdSendableClass(thread, env, level).GetRawData(); } DEF_RUNTIME_STUBS(SetClassConstructorLength) { RUNTIME_STUBS_HEADER(SetClassConstructorLength); JSTaggedValue ctor = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue length = GetArg(argv, argc, 1); // 1: means the first parameter return RuntimeSetClassConstructorLength(thread, ctor, length).GetRawData(); } DEF_RUNTIME_STUBS(UpdateHotnessCounter) { RUNTIME_STUBS_HEADER(UpdateHotnessCounter); JSHandle thisFunc = GetHArg(argv, argc, 0); // 0: means the zeroth parameter thread->CheckSafepoint(); JSHandle method(thread, thisFunc->GetMethod(thread)); auto profileTypeInfo = thisFunc->GetProfileTypeInfo(thread); if (profileTypeInfo.IsUndefined()) { uint32_t slotSize = method->GetSlotSize(); auto res = RuntimeNotifyInlineCache(thread, thisFunc, slotSize); return res.GetRawData(); } return profileTypeInfo.GetRawData(); } DEF_RUNTIME_STUBS(PGODump) { RUNTIME_STUBS_HEADER(PGODump); JSHandle thisFunc = GetHArg(argv, argc, 0); // 0: means the zeroth parameter thread->GetEcmaVM()->GetPGOProfiler()->PGODump(thisFunc.GetTaggedType()); return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(PGOPreDump) { RUNTIME_STUBS_HEADER(PGOPreDump); JSHandle thisFunc = GetHArg(argv, argc, 0); // 0: means the zeroth parameter thread->GetEcmaVM()->GetPGOProfiler()->PGOPreDump(thisFunc.GetTaggedType()); return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(UpdateHotnessCounterWithProf) { RUNTIME_STUBS_HEADER(UpdateHotnessCounterWithProf); JSHandle thisFunc = GetHArg(argv, argc, 0); // 0: means the zeroth parameter thread->CheckSafepoint(); auto profileTypeInfo = thisFunc->GetProfileTypeInfo(thread); if (profileTypeInfo.IsUndefined()) { uint32_t slotSize = thisFunc->GetCallTarget(thread)->GetSlotSize(); auto res = RuntimeNotifyInlineCache(thread, thisFunc, slotSize); return res.GetRawData(); } return profileTypeInfo.GetRawData(); } DEF_RUNTIME_STUBS(JitCompile) { RUNTIME_STUBS_HEADER(JitCompile); JSHandle thisFunc = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue offset = GetArg(argv, argc, 1); // 1: means the first parameter Jit::Compile(thread->GetEcmaVM(), thisFunc, CompilerTier::Tier::FAST, offset.GetInt(), JitCompileMode::Mode::ASYNC); return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(BaselineJitCompile) { RUNTIME_STUBS_HEADER(BaselineJitCompile); JSHandle thisFunc = GetHArg(argv, argc, 0); // 0: means the zeroth parameter Jit::Compile(thread->GetEcmaVM(), thisFunc, CompilerTier::Tier::BASELINE, MachineCode::INVALID_OSR_OFFSET, JitCompileMode::Mode::ASYNC); return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(CountInterpExecFuncs) { RUNTIME_STUBS_HEADER(CountInterpExecFuncs); JSHandle thisFunc = GetHArg(argv, argc, 0); // 0: means the zeroth parameter Jit::CountInterpExecFuncs(thread, thisFunc); return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(CheckSafePoint) { auto thread = JSThread::GlueToJSThread(argGlue); thread->CheckSafepoint(); return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(LoadICByName) { RUNTIME_STUBS_HEADER(LoadICByName); JSHandle profileHandle = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle receiverHandle = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle keyHandle = GetHArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue slotId = GetArg(argv, argc, 3); // 3: means the third parameter if (profileHandle->IsUndefined()) { auto res = JSTaggedValue::GetProperty(thread, receiverHandle, keyHandle).GetValue().GetTaggedValue(); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); return res.GetRawData(); } LoadICRuntime icRuntime( thread, JSHandle::Cast(profileHandle), slotId.GetInt(), ICKind::NamedLoadIC); return icRuntime.LoadMiss(receiverHandle, keyHandle).GetRawData(); } DEF_RUNTIME_STUBS(TryLdGlobalICByName) { RUNTIME_STUBS_HEADER(TryLdGlobalICByName); JSHandle profileHandle = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle keyHandle = GetHArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue slotId = GetArg(argv, argc, 2); // 2: means the third parameter EcmaVM *ecmaVm = thread->GetEcmaVM(); JSHandle globalEnv = ecmaVm->GetGlobalEnv(); JSHandle globalObj(thread, globalEnv->GetGlobalObject()); if (profileHandle->IsUndefined()) { auto res = RuntimeTryLdGlobalByName(thread, globalObj, keyHandle); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); return res.GetRawData(); } LoadICRuntime icRuntime( thread, JSHandle::Cast(profileHandle), slotId.GetInt(), ICKind::NamedGlobalTryLoadIC); return icRuntime.LoadMiss(globalObj, keyHandle).GetRawData(); } DEF_RUNTIME_STUBS(StoreICByName) { RUNTIME_STUBS_HEADER(StoreICByName); JSHandle profileHandle = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle receiverHandle = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle keyHandle = GetHArg(argv, argc, 2); // 2: means the second parameter JSHandle valueHandle = GetHArg(argv, argc, 3); // 3: means the third parameter JSTaggedValue slotId = GetArg(argv, argc, 4); // 4: means the fourth parameter if (profileHandle->IsUndefined()) { JSTaggedValue::SetProperty(thread, receiverHandle, keyHandle, valueHandle, true); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); return JSTaggedValue::True().GetRawData(); } StoreICRuntime icRuntime( thread, JSHandle::Cast(profileHandle), slotId.GetInt(), ICKind::NamedStoreIC); return icRuntime.StoreMiss(receiverHandle, keyHandle, valueHandle).GetRawData(); } DEF_RUNTIME_STUBS(StoreOwnICByName) { RUNTIME_STUBS_HEADER(StoreOwnICByName); JSHandle profileHandle = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle receiverHandle = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle keyHandle = GetHArg(argv, argc, 2); // 2: means the second parameter JSHandle valueHandle = GetHArg(argv, argc, 3); // 3: means the third parameter JSTaggedValue slotId = GetArg(argv, argc, 4); // 4: means the fourth parameter if (profileHandle->IsUndefined()) { JSTaggedValue::SetProperty(thread, receiverHandle, keyHandle, valueHandle, true); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); return JSTaggedValue::True().GetRawData(); } StoreICRuntime icRuntime( thread, JSHandle::Cast(profileHandle), slotId.GetInt(), ICKind::NamedStoreIC); return icRuntime.StoreMiss(receiverHandle, keyHandle, valueHandle, true, true).GetRawData(); } DEF_RUNTIME_STUBS(SetFunctionNameNoPrefix) { RUNTIME_STUBS_HEADER(SetFunctionNameNoPrefix); JSTaggedType argFunc = GetTArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue argName = GetArg(argv, argc, 1); // 1: means the first parameter JSFunction::SetFunctionNameNoPrefix(thread, reinterpret_cast(argFunc), argName); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(StOwnByValueWithNameSet) { RUNTIME_STUBS_HEADER(StOwnByValueWithNameSet); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle prop = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle value = GetHArg(argv, argc, 2); // 2: means the second parameter return RuntimeStOwnByValueWithNameSet(thread, obj, prop, value).GetRawData(); } DEF_RUNTIME_STUBS(StOwnByName) { RUNTIME_STUBS_HEADER(StOwnByName); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle prop = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle value = GetHArg(argv, argc, 2); // 2: means the second parameter return RuntimeStOwnByName(thread, obj, prop, value).GetRawData(); } DEF_RUNTIME_STUBS(StOwnByNameWithNameSet) { RUNTIME_STUBS_HEADER(StOwnByNameWithNameSet); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle prop = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle value = GetHArg(argv, argc, 2); // 2: means the second parameter return RuntimeStOwnByValueWithNameSet(thread, obj, prop, value).GetRawData(); } DEF_RUNTIME_STUBS(SuspendGenerator) { RUNTIME_STUBS_HEADER(SuspendGenerator); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle value = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeSuspendGenerator(thread, obj, value).GetRawData(); } DEF_RUNTIME_STUBS(OptSuspendGenerator) { RUNTIME_STUBS_HEADER(OptSuspendGenerator); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle value = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeOptSuspendGenerator(thread, obj, value).GetRawData(); } DEF_RUNTIME_STUBS(OptAsyncGeneratorResolve) { RUNTIME_STUBS_HEADER(OptAsyncGeneratorResolve); JSHandle asyncGenerator = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle value = GetHArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue flag = GetArg(argv, argc, 2); // 2: means the second parameter return RuntimeOptAsyncGeneratorResolve(thread, asyncGenerator, value, flag).GetRawData(); } DEF_RUNTIME_STUBS(OptCreateObjectWithExcludedKeys) { RUNTIME_STUBS_HEADER(OptCreateObjectWithExcludedKeys); return RuntimeOptCreateObjectWithExcludedKeys(thread, argv, argc).GetRawData(); } DEF_RUNTIME_STUBS(UpFrame) { RUNTIME_STUBS_HEADER(UpFrame); FrameHandler frameHandler(thread); uint32_t pcOffset = panda_file::INVALID_OFFSET; for (; frameHandler.HasFrame(); frameHandler.PrevJSFrame()) { if (frameHandler.IsEntryFrame() || frameHandler.IsBuiltinFrame()) { thread->SetCurrentFrame(frameHandler.GetSp()); thread->SetLastFp(frameHandler.GetFp()); return JSTaggedValue(static_cast(0)).GetRawData(); } auto method = frameHandler.GetMethod(); uint32_t curBytecodePcOfst = INVALID_INDEX; if (reinterpret_cast(frameHandler.GetPc()) == std::numeric_limits::max()) { // For baselineJit uintptr_t curNativePc = frameHandler.GetBaselineNativePc(); ASSERT(curNativePc != 0); LOG_BASELINEJIT(DEBUG) << "current native pc in UpFrame: " << std::hex << reinterpret_cast(curNativePc); JSHandle funcVal = JSHandle(thread, frameHandler.GetFunction()); JSHandle func = JSHandle::Cast(funcVal); curBytecodePcOfst = RuntimeGetBytecodePcOfstForBaseline(thread, func, curNativePc); } else { curBytecodePcOfst = frameHandler.GetBytecodeOffset(); } pcOffset = method->FindCatchBlock(thread, curBytecodePcOfst); if (pcOffset != INVALID_INDEX) { thread->SetCurrentFrame(frameHandler.GetSp()); thread->SetLastFp(frameHandler.GetFp()); uintptr_t pc = reinterpret_cast(method->GetBytecodeArray() + pcOffset); return JSTaggedValue(static_cast(pc)).GetRawData(); } if (!method->IsNativeWithCallField()) { auto *debuggerMgr = thread->GetEcmaVM()->GetJsDebuggerManager(); debuggerMgr->GetNotificationManager()->MethodExitEvent(thread, method); } } LOG_FULL(FATAL) << "EXCEPTION: EntryFrame Not Found"; UNREACHABLE(); } DEF_RUNTIME_STUBS(GetModuleNamespaceByIndex) { RUNTIME_STUBS_HEADER(GetModuleNamespaceByIndex); JSTaggedValue index = GetArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeGetModuleNamespace(thread, index.GetInt()).GetRawData(); } DEF_RUNTIME_STUBS(GetModuleNamespaceByIndexOnJSFunc) { RUNTIME_STUBS_HEADER(GetModuleNamespaceByIndexOnJSFunc); JSTaggedValue index = GetArg(argv, argc, 0); JSTaggedValue jsFunc = GetArg(argv, argc, 1); return RuntimeGetModuleNamespace(thread, index.GetInt(), jsFunc).GetRawData(); } DEF_RUNTIME_STUBS(GetModuleNamespace) { RUNTIME_STUBS_HEADER(GetModuleNamespace); JSTaggedValue localName = GetArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeGetModuleNamespace(thread, localName).GetRawData(); } DEF_RUNTIME_STUBS(StModuleVarByIndex) { RUNTIME_STUBS_HEADER(StModuleVar); JSTaggedValue index = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue value = GetArg(argv, argc, 1); // 1: means the first parameter RuntimeStModuleVar(thread, index.GetInt(), value); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(StModuleVarByIndexOnJSFunc) { RUNTIME_STUBS_HEADER(StModuleVarByIndexOnJSFunc); JSTaggedValue index = GetArg(argv, argc, 0); JSTaggedValue value = GetArg(argv, argc, 1); JSTaggedValue jsFunc = GetArg(argv, argc, 2); RuntimeStModuleVar(thread, index.GetInt(), value, jsFunc); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(StModuleVar) { RUNTIME_STUBS_HEADER(StModuleVar); JSTaggedValue key = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue value = GetArg(argv, argc, 1); // 1: means the first parameter RuntimeStModuleVar(thread, key, value); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(LdLocalModuleVarByIndex) { RUNTIME_STUBS_HEADER(LdLocalModuleVarByIndex); JSTaggedValue index = GetArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeLdLocalModuleVar(thread, index.GetInt()).GetRawData(); } DEF_RUNTIME_STUBS(LdLocalModuleVarByIndexWithModule) { RUNTIME_STUBS_HEADER(LdLocalModuleVarByIndexWithModule); JSTaggedValue index = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle module = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeLdLocalModuleVarWithModule(thread, index.GetInt(), module).GetRawData(); } DEF_RUNTIME_STUBS(LdExternalModuleVarByIndex) { RUNTIME_STUBS_HEADER(LdExternalModuleVarByIndex); JSTaggedValue index = GetArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeLdExternalModuleVar(thread, index.GetInt()).GetRawData(); } DEF_RUNTIME_STUBS(LdExternalModuleVarByIndexWithModule) { RUNTIME_STUBS_HEADER(LdExternalModuleVarByIndexWithModule); JSTaggedValue index = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle module = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeLdExternalModuleVarWithModule(thread, index.GetInt(), module).GetRawData(); } DEF_RUNTIME_STUBS(LdSendableExternalModuleVarByIndex) { RUNTIME_STUBS_HEADER(LdSendableExternalModuleVarByIndex); JSTaggedValue index = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue jsFunc = GetArg(argv, argc, 1); // 1: means the first parameter return RuntimeLdSendableExternalModuleVar(thread, index.GetInt(), jsFunc).GetRawData(); } DEF_RUNTIME_STUBS(LdSendableLocalModuleVarByIndex) { RUNTIME_STUBS_HEADER(LdSendableLocalModuleVarByIndex); JSTaggedValue index = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue jsFunc = GetArg(argv, argc, 1); // 1: means the first parameter return RuntimeLdSendableLocalModuleVar(thread, index.GetInt(), jsFunc).GetRawData(); } DEF_RUNTIME_STUBS(LdLazyExternalModuleVarByIndex) { RUNTIME_STUBS_HEADER(LdLazyExternalModuleVarByIndex); JSTaggedValue index = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue jsFunc = GetArg(argv, argc, 1); // 1: means the first parameter return RuntimeLdLazyExternalModuleVar(thread, index.GetInt(), jsFunc).GetRawData(); } DEF_RUNTIME_STUBS(LdLazySendableExternalModuleVarByIndex) { RUNTIME_STUBS_HEADER(LdLazySendableExternalModuleVarByIndex); JSTaggedValue index = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue jsFunc = GetArg(argv, argc, 1); // 1: means the first parameter return RuntimeLdLazySendableExternalModuleVar(thread, index.GetInt(), jsFunc).GetRawData(); } DEF_RUNTIME_STUBS(LdLocalModuleVarByIndexOnJSFunc) { RUNTIME_STUBS_HEADER(LdLocalModuleVarByIndexOnJSFunc); JSTaggedValue index = GetArg(argv, argc, 0); JSTaggedValue jsFunc = GetArg(argv, argc, 1); return RuntimeLdLocalModuleVar(thread, index.GetInt(), jsFunc).GetRawData(); } DEF_RUNTIME_STUBS(LdExternalModuleVarByIndexOnJSFunc) { RUNTIME_STUBS_HEADER(LdExternalModuleVarByIndexOnJSFunc); JSTaggedValue index = GetArg(argv, argc, 0); JSTaggedValue jsFunc = GetArg(argv, argc, 1); return RuntimeLdExternalModuleVar(thread, index.GetInt(), jsFunc).GetRawData(); } DEF_RUNTIME_STUBS(LdModuleVar) { RUNTIME_STUBS_HEADER(LdModuleVar); JSTaggedValue key = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue taggedFlag = GetArg(argv, argc, 1); // 1: means the first parameter bool innerFlag = taggedFlag.GetInt() != 0; return RuntimeLdModuleVar(thread, key, innerFlag).GetRawData(); } DEF_RUNTIME_STUBS(GetModuleValueOuterInternal) { RUNTIME_STUBS_HEADER(GetModuleValueOuterInternal); JSTaggedValue curModule = GetArg(argv, argc, 0); // 0: means the zeroth parameter int32_t index = JSTaggedValue::ToInt32(thread, GetHArg(argv, argc, 1)); // 2: means the second parameter return ModuleValueAccessor::GetModuleValueOuterInternal(thread, index, curModule).GetRawData(); } DEF_RUNTIME_STUBS(GetModuleName) { RUNTIME_STUBS_HEADER(GetModuleName); JSTaggedValue curModule = GetArg(argv, argc, 0); // 0: means the zeroth parameter CString cjsModuleName = SourceTextModule::GetModuleName(curModule); JSHandle moduleNameHandle(thread->GetEcmaVM()->GetFactory()->NewFromUtf8(cjsModuleName)); return moduleNameHandle.GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(ThrowExportsIsHole) { RUNTIME_STUBS_HEADER(ThrowExportsIsHole); JSTaggedValue curModule = GetArg(argv, argc, 0); // 0: means the zeroth parameter CString errorMsg = "Loading cjs module:" + SourceTextModule::GetModuleName(curModule) + ", failed"; THROW_NEW_ERROR_WITH_MSG_AND_RETURN_VALUE(thread, ErrorType::SYNTAX_ERROR, errorMsg.c_str(), JSTaggedValue::Exception().GetRawData()); } DEF_RUNTIME_STUBS(NewResolvedIndexBindingRecord) { RUNTIME_STUBS_HEADER(NewResolvedIndexBindingRecord); JSHandle module = GetHArg(argv, argc, 0); // 0: means the zeroth parameter int32_t index = JSTaggedValue::ToInt32(thread, GetHArg(argv, argc, 1)); // 1: means the first parameter ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); return JSHandle::Cast(factory->NewResolvedIndexBindingRecord(module, index))->GetRawData(); } DEF_RUNTIME_STUBS(HandleResolutionIsNullOrString) { RUNTIME_STUBS_HEADER(HandleResolutionIsNullOrString); JSHandle module = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle requiredModule = GetHArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue bindingName = GetArg(argv, argc, 2); // 2: means the second parameter JSHandle resolution = GetHArg(argv, argc, 3); // 3: means the third parameter CString requestMod = ModulePathHelper::ReformatPath(SourceTextModule::GetModuleName(requiredModule.GetTaggedValue())); CString recordStr = ModulePathHelper::ReformatPath(SourceTextModule::GetModuleName(module.GetTaggedValue())); CString msg = "the requested module '" + requestMod + SourceTextModule::GetResolveErrorReason(resolution) + ModulePathHelper::Utf8ConvertToString(thread, bindingName) + "' which imported by '" + recordStr + "'"; THROW_NEW_ERROR_WITH_MSG_AND_RETURN_VALUE( thread, ErrorType::SYNTAX_ERROR, msg.c_str(), JSTaggedValue::Exception().GetRawData()); } DEF_RUNTIME_STUBS(CheckAndThrowModuleError) { RUNTIME_STUBS_HEADER(CheckAndThrowModuleError); JSHandle module = GetHArg(argv, argc, 0); // 0: means the zeroth parameter bool isThrow = GetArg(argv, argc, 1).ToBoolean(); // 1: means the first parameter module->CheckAndThrowModuleError(thread); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); if (isThrow) { CString errorMsg = module->GetEcmaModuleRecordNameString(); errorMsg = errorMsg.empty() ? module->GetEcmaModuleFilenameString() : errorMsg; errorMsg.append(" environment is undefined"); THROW_REFERENCE_ERROR_AND_RETURN(thread, errorMsg.c_str(), JSTaggedValue::Exception().GetRawData()); } return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(GetResolvedRecordIndexBindingModule) { RUNTIME_STUBS_HEADER(GetResolvedRecordIndexBindingModule); JSHandle module = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle binding = GetHArg(argv, argc, 1); // 1: means the first parameter JSTaggedType argModuleManager = GetTArg(argv, argc, 2); // 2: means the second parameter ModuleManager *moduleManager = reinterpret_cast(argModuleManager); JSTaggedValue recordName = GetArg(argv, argc, 3); // 3: means the third parameter CString recordNameStr = ModulePathHelper::Utf8ConvertToString(thread, recordName); if (!moduleManager->IsEvaluatedModule(recordNameStr)) { auto isMergedAbc = !module->GetEcmaModuleRecordNameString().empty(); CString fileName = ModulePathHelper::Utf8ConvertToString(thread, (binding->GetAbcFileName(thread))); if (!JSPandaFileExecutor::LazyExecuteModule(thread, recordNameStr, fileName, isMergedAbc)) { // LCOV_EXCL_BR_LINE LOG_ECMA(FATAL) << "LazyExecuteModule failed"; } } return moduleManager->HostGetImportedModule(recordNameStr).GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(GetResolvedRecordBindingModule) { RUNTIME_STUBS_HEADER(GetResolvedRecordBindingModule); JSHandle module = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedType argModuleManager = GetTArg(argv, argc, 1); // 1: means the first parameter ModuleManager *moduleManager = reinterpret_cast(argModuleManager); JSTaggedValue recordName = GetArg(argv, argc, 2); // 2: means the second parameter CString recordNameStr = ModulePathHelper::Utf8ConvertToString(thread, recordName); if (!moduleManager->IsEvaluatedModule(recordNameStr)) { auto isMergedAbc = !module->GetEcmaModuleRecordNameString().empty(); CString fileName = module->GetEcmaModuleFilenameString(); if (!JSPandaFileExecutor::LazyExecuteModule(thread, recordNameStr, fileName, isMergedAbc)) { // LCOV_EXCL_BR_LINE LOG_ECMA(FATAL) << "LazyExecuteModule failed"; } } return moduleManager->HostGetImportedModule(recordNameStr).GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(GetPropIteratorSlowpath) { RUNTIME_STUBS_HEADER(GetPropIteratorSlowpath); JSHandle value = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return JSObject::LoadEnumerateProperties(thread, value).GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(PrimitiveStringCreate) { RUNTIME_STUBS_HEADER(PrimitiveStringCreate); JSHandle str = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle newTarget = thread->GlobalConstants()->GetHandledUndefined(); return JSPrimitiveRef::StringCreate(thread, str, newTarget).GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(AsyncFunctionEnter) { RUNTIME_STUBS_HEADER(AsyncFunctionEnter); return RuntimeAsyncFunctionEnter(thread).GetRawData(); } DEF_RUNTIME_STUBS(GetAsyncIterator) { RUNTIME_STUBS_HEADER(GetAsyncIterator); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeGetAsyncIterator(thread, obj).GetRawData(); } DEF_RUNTIME_STUBS(LdPrivateProperty) { RUNTIME_STUBS_HEADER(LdPrivateProperty); JSTaggedValue lexicalEnv = GetArg(argv, argc, 0); // 0: means the zeroth parameter uint32_t levelIndex = static_cast(GetArg(argv, argc, 1).GetInt()); // 1: means the first parameter uint32_t slotIndex = static_cast(GetArg(argv, argc, 2).GetInt()); // 2: means the second parameter JSTaggedValue obj = GetArg(argv, argc, 3); // 3: means the third parameter return RuntimeLdPrivateProperty(thread, lexicalEnv, levelIndex, slotIndex, obj).GetRawData(); } DEF_RUNTIME_STUBS(StPrivateProperty) { RUNTIME_STUBS_HEADER(StPrivateProperty); JSTaggedValue lexicalEnv = GetArg(argv, argc, 0); // 0: means the zeroth parameter uint32_t levelIndex = static_cast(GetArg(argv, argc, 1).GetInt()); // 1: means the first parameter uint32_t slotIndex = static_cast(GetArg(argv, argc, 2).GetInt()); // 2: means the second parameter JSTaggedValue obj = GetArg(argv, argc, 3); // 3: means the third parameter JSTaggedValue value = GetArg(argv, argc, 4); // 4: means the fourth parameter return RuntimeStPrivateProperty(thread, lexicalEnv, levelIndex, slotIndex, obj, value).GetRawData(); } DEF_RUNTIME_STUBS(TestIn) { RUNTIME_STUBS_HEADER(TestIn); JSTaggedValue lexicalEnv = GetArg(argv, argc, 0); // 0: means the zeroth parameter uint32_t levelIndex = static_cast(GetArg(argv, argc, 1).GetInt()); // 1: means the first parameter uint32_t slotIndex = static_cast(GetArg(argv, argc, 2).GetInt()); // 2: means the second parameter JSTaggedValue obj = GetArg(argv, argc, 3); // 3: means the third parameter return RuntimeTestIn(thread, lexicalEnv, levelIndex, slotIndex, obj).GetRawData(); } DEF_RUNTIME_STUBS(Throw) { RUNTIME_STUBS_HEADER(Throw); JSTaggedValue value = GetArg(argv, argc, 0); // 0: means the zeroth parameter RuntimeThrow(thread, value); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(ThrowThrowNotExists) { RUNTIME_STUBS_HEADER(ThrowThrowNotExists); RuntimeThrowThrowNotExists(thread); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(ThrowPatternNonCoercible) { RUNTIME_STUBS_HEADER(ThrowPatternNonCoercible); RuntimeThrowPatternNonCoercible(thread); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(ThrowDeleteSuperProperty) { RUNTIME_STUBS_HEADER(ThrowDeleteSuperProperty); RuntimeThrowDeleteSuperProperty(thread); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(ThrowUndefinedIfHole) { RUNTIME_STUBS_HEADER(ThrowUndefinedIfHole); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter RuntimeThrowUndefinedIfHole(thread, obj); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(ThrowIfNotObject) { RUNTIME_STUBS_HEADER(ThrowIfNotObject); RuntimeThrowIfNotObject(thread); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(ThrowConstAssignment) { RUNTIME_STUBS_HEADER(ThrowConstAssignment); JSHandle value = GetHArg(argv, argc, 0); // 0: means the zeroth parameter RuntimeThrowConstAssignment(thread, value); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(ThrowTypeError) { RUNTIME_STUBS_HEADER(ThrowTypeError); JSTaggedValue argMessageStringId = GetArg(argv, argc, 0); // 0: means the zeroth parameter std::string message = MessageString::GetMessageString(argMessageStringId.GetInt()); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle error = factory->GetJSError(ErrorType::TYPE_ERROR, message.c_str(), StackCheck::NO); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error.GetTaggedValue(), JSTaggedValue::Hole().GetRawData()); } DEF_RUNTIME_STUBS(MismatchError) { RUNTIME_STUBS_HEADER(MismatchError); JSTaggedValue shareFieldType = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue value = GetArg(argv, argc, 1); // 1: means the first parameter std::stringstream oss; value.DumpTaggedValueType(oss); LOG_ECMA(ERROR) << "Sendable obj Match field type fail. expected type: " << ClassHelper::StaticFieldTypeToString(shareFieldType.GetInt()) << ", actual type: " << oss.str(); return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(ThrowRangeError) { RUNTIME_STUBS_HEADER(ThrowRangeError); JSTaggedValue argMessageStringId = GetArg(argv, argc, 0); std::string message = MessageString::GetMessageString(argMessageStringId.GetInt()); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle error = factory->GetJSError(ErrorType::RANGE_ERROR, message.c_str(), StackCheck::NO); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error.GetTaggedValue(), JSTaggedValue::Hole().GetRawData()); } DEF_RUNTIME_STUBS(LoadMiss) { RUNTIME_STUBS_HEADER(LoadMiss); JSTaggedType profileTypeInfo = GetTArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue receiver = GetArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue key = GetArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue slotId = GetArg(argv, argc, 3); // 3: means the third parameter JSTaggedValue kind = GetArg(argv, argc, 4); // 4: means the fourth parameter return ICRuntimeStub::LoadMiss(thread, reinterpret_cast(profileTypeInfo), receiver, key, slotId.GetInt(), static_cast(kind.GetInt())).GetRawData(); } DEF_RUNTIME_STUBS(StoreMiss) { RUNTIME_STUBS_HEADER(StoreMiss); JSTaggedType profileTypeInfo = GetTArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue receiver = GetArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue key = GetArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue value = GetArg(argv, argc, 3); // 3: means the third parameter JSTaggedValue slotId = GetArg(argv, argc, 4); // 4: means the fourth parameter JSTaggedValue kind = GetArg(argv, argc, 5); // 5: means the fifth parameter return ICRuntimeStub::StoreMiss(thread, reinterpret_cast(profileTypeInfo), receiver, key, value, slotId.GetInt(), static_cast(kind.GetInt())).GetRawData(); } DEF_RUNTIME_STUBS(TryUpdateGlobalRecord) { RUNTIME_STUBS_HEADER(TryUpdateGlobalRecord); JSTaggedValue prop = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue value = GetArg(argv, argc, 1); // 1: means the first parameter return RuntimeTryUpdateGlobalRecord(thread, prop, value).GetRawData(); } DEF_RUNTIME_STUBS(ThrowReferenceError) { RUNTIME_STUBS_HEADER(ThrowReferenceError); JSHandle prop = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeThrowReferenceError(thread, prop, " is not defined").GetRawData(); } DEF_RUNTIME_STUBS(LdGlobalICVar) { RUNTIME_STUBS_HEADER(LdGlobalICVar); JSHandle global = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle prop = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle profileHandle = GetHArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue slotId = GetArg(argv, argc, 3); // 3: means the third parameter if (profileHandle->IsUndefined()) { return RuntimeLdGlobalVarFromProto(thread, global, prop).GetRawData(); } LoadICRuntime icRuntime( thread, JSHandle::Cast(profileHandle), slotId.GetInt(), ICKind::NamedGlobalLoadIC); return icRuntime.LoadMiss(global, prop).GetRawData(); } DEF_RUNTIME_STUBS(StGlobalVar) { RUNTIME_STUBS_HEADER(StGlobalVar); JSHandle prop = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle value = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeStGlobalVar(thread, prop, value).GetRawData(); } DEF_RUNTIME_STUBS(ToIndex) { RUNTIME_STUBS_HEADER(ToIndex); JSHandle value = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return JSTaggedValue::ToIndex(thread, value).GetRawData(); } DEF_RUNTIME_STUBS(NewJSObjectByConstructor) { RUNTIME_STUBS_HEADER(NewJSObjectByConstructor); JSHandle constructor = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle newTarget = GetHArg(argv, argc, 1); // 1: means the first parameter ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle obj = factory->NewJSObjectByConstructor(constructor, newTarget); return obj.GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(CloneHclass) { RUNTIME_STUBS_HEADER(CloneHclass); JSHandle objHclass = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return JSHClass::Clone(thread, objHclass).GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(AllocateTypedArrayBuffer) { RUNTIME_STUBS_HEADER(AllocateTypedArrayBuffer); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue length = GetArg(argv, argc, 1); // 1: means the first parameter return base::TypedArrayHelper::AllocateTypedArrayBuffer(thread, obj, length.GetNumber(), base::TypedArrayHelper::GetType(JSHandle(obj))).GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(ToNumber) { RUNTIME_STUBS_HEADER(ToNumber); JSHandle value = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeToNumber(thread, value).GetRawData(); } DEF_RUNTIME_STUBS(ToBoolean) { RUNTIME_STUBS_HEADER(ToBoolean); JSTaggedValue value = GetArg(argv, argc, 0); // 0: means the zeroth parameter bool result = value.ToBoolean(); return JSTaggedValue(result).GetRawData(); } DEF_RUNTIME_STUBS(Eq) { RUNTIME_STUBS_HEADER(Eq); JSHandle left = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle right = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeEq(thread, left, right).GetRawData(); } DEF_RUNTIME_STUBS(NotEq) { RUNTIME_STUBS_HEADER(NotEq); JSHandle left = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle right = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeNotEq(thread, left, right).GetRawData(); } DEF_RUNTIME_STUBS(Less) { RUNTIME_STUBS_HEADER(Less); JSHandle left = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle right = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeLess(thread, left, right).GetRawData(); } DEF_RUNTIME_STUBS(LessEq) { RUNTIME_STUBS_HEADER(LessEq); JSHandle left = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle right = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeLessEq(thread, left, right).GetRawData(); } DEF_RUNTIME_STUBS(Greater) { RUNTIME_STUBS_HEADER(Greater); JSHandle left = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle right = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeGreater(thread, left, right).GetRawData(); } DEF_RUNTIME_STUBS(GreaterEq) { RUNTIME_STUBS_HEADER(GreaterEq); JSHandle left = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle right = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeGreaterEq(thread, left, right).GetRawData(); } DEF_RUNTIME_STUBS(Add2) { RUNTIME_STUBS_HEADER(Add2); JSHandle left = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle right = GetHArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue res = RuntimeAdd2(thread, left, right); return res.GetRawData(); } DEF_RUNTIME_STUBS(Sub2) { RUNTIME_STUBS_HEADER(Sub2); JSHandle left = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle right = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeSub2(thread, left, right).GetRawData(); } DEF_RUNTIME_STUBS(Mul2) { RUNTIME_STUBS_HEADER(Mul2); JSHandle left = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle right = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeMul2(thread, left, right).GetRawData(); } DEF_RUNTIME_STUBS(Div2) { RUNTIME_STUBS_HEADER(Div2); JSHandle left = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle right = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeDiv2(thread, left, right).GetRawData(); } DEF_RUNTIME_STUBS(Mod2) { RUNTIME_STUBS_HEADER(Mod2); JSHandle left = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle right = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeMod2(thread, left, right).GetRawData(); } DEF_RUNTIME_STUBS(JumpToCInterpreter) { #ifndef EXCLUDE_C_INTERPRETER RUNTIME_STUBS_HEADER(JumpToCInterpreter); JSTaggedValue constpool = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue profileTypeInfo = GetArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue acc = GetArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue hotnessCounter = GetArg(argv, argc, 3); // 3: means the third parameter auto sp = const_cast(thread->GetCurrentInterpretedFrame()); const uint8_t *currentPc = reinterpret_cast(GET_ASM_FRAME(sp)->pc); uint8_t opcode = currentPc[0]; asmDispatchTable[opcode](thread, currentPc, sp, constpool, profileTypeInfo, acc, hotnessCounter.GetInt()); sp = const_cast(thread->GetCurrentInterpretedFrame()); return JSTaggedValue(reinterpret_cast(sp)).GetRawData(); #else return JSTaggedValue::Hole().GetRawData(); #endif } DEF_RUNTIME_STUBS(NotifyBytecodePcChanged) { RUNTIME_STUBS_HEADER(NotifyBytecodePcChanged); FrameHandler frameHandler(thread); for (; frameHandler.HasFrame(); frameHandler.PrevJSFrame()) { if (frameHandler.IsEntryFrame() || frameHandler.IsBuiltinFrame()) { continue; } Method *method = frameHandler.GetMethod(); // Skip builtins method if (method->IsNativeWithCallField()) { continue; } auto bcOffset = frameHandler.GetBytecodeOffset(); auto *debuggerMgr = thread->GetEcmaVM()->GetJsDebuggerManager(); debuggerMgr->GetNotificationManager()->BytecodePcChangedEvent(thread, method, bcOffset); return JSTaggedValue::Hole().GetRawData(); } return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(NotifyDebuggerStatement) { RUNTIME_STUBS_HEADER(NotifyDebuggerStatement); return RuntimeNotifyDebuggerStatement(thread).GetRawData(); } DEF_RUNTIME_STUBS(MethodEntry) { RUNTIME_STUBS_HEADER(MethodEntry); JSHandle func = GetHArg(argv, argc, 0); // 0: means the zeroth parameter if (func.GetTaggedValue().IsECMAObject()) { Method *method = ECMAObject::Cast(func.GetTaggedValue().GetTaggedObject())->GetCallTarget(thread); if (method->IsNativeWithCallField()) { return JSTaggedValue::Hole().GetRawData(); } JSHandle funcObj = JSHandle::Cast(func); FrameHandler frameHandler(thread); for (; frameHandler.HasFrame(); frameHandler.PrevJSFrame()) { if (frameHandler.IsEntryFrame() || frameHandler.IsBuiltinFrame()) { continue; } auto *debuggerMgr = thread->GetEcmaVM()->GetJsDebuggerManager(); debuggerMgr->GetNotificationManager()->MethodEntryEvent(thread, method, funcObj->GetLexicalEnv(thread)); return JSTaggedValue::Hole().GetRawData(); } } return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(MethodExit) { RUNTIME_STUBS_HEADER(MethodExit); FrameHandler frameHandler(thread); for (; frameHandler.HasFrame(); frameHandler.PrevJSFrame()) { if (frameHandler.IsEntryFrame() || frameHandler.IsBuiltinFrame()) { continue; } Method *method = frameHandler.GetMethod(); // Skip builtins method if (method->IsNativeWithCallField()) { continue; } auto *debuggerMgr = thread->GetEcmaVM()->GetJsDebuggerManager(); debuggerMgr->GetNotificationManager()->MethodExitEvent(thread, method); return JSTaggedValue::Hole().GetRawData(); } return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(CreateEmptyObject) { RUNTIME_STUBS_HEADER(CreateEmptyObject); EcmaVM *ecmaVm = thread->GetEcmaVM(); ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle globalEnv = ecmaVm->GetGlobalEnv(); return RuntimeCreateEmptyObject(thread, factory, globalEnv).GetRawData(); } DEF_RUNTIME_STUBS(GetUnmapedArgs) { RUNTIME_STUBS_HEADER(GetUnmapedArgs); auto sp = const_cast(thread->GetCurrentInterpretedFrame()); uint32_t startIdx = 0; // 0: means restIdx uint32_t actualNumArgs = InterpreterAssembly::GetNumArgs(thread, sp, 0, startIdx); return RuntimeGetUnmapedArgs(thread, sp, actualNumArgs, startIdx).GetRawData(); } DEF_RUNTIME_STUBS(CopyRestArgs) { RUNTIME_STUBS_HEADER(CopyRestArgs); JSTaggedValue restIdx = GetArg(argv, argc, 0); // 0: means the zeroth parameter auto sp = const_cast(thread->GetCurrentInterpretedFrame()); uint32_t startIdx = 0; uint32_t restNumArgs = InterpreterAssembly::GetNumArgs(thread, sp, restIdx.GetInt(), startIdx); return RuntimeCopyRestArgs(thread, sp, restNumArgs, startIdx).GetRawData(); } DEF_RUNTIME_STUBS(CreateArrayWithBuffer) { RUNTIME_STUBS_HEADER(CreateArrayWithBuffer); JSHandle argArray = GetHArg(argv, argc, 0); // 0: means the zeroth parameter EcmaVM *ecmaVm = thread->GetEcmaVM(); ObjectFactory *factory = ecmaVm->GetFactory(); return RuntimeCreateArrayWithBuffer(thread, factory, argArray).GetRawData(); } DEF_RUNTIME_STUBS(CreateObjectWithBuffer) { RUNTIME_STUBS_HEADER(CreateObjectWithBuffer); JSHandle argObj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter EcmaVM *ecmaVm = thread->GetEcmaVM(); ObjectFactory *factory = ecmaVm->GetFactory(); return RuntimeCreateObjectWithBuffer(thread, factory, argObj).GetRawData(); } DEF_RUNTIME_STUBS(NewThisObject) { RUNTIME_STUBS_HEADER(NewThisObject); JSHandle ctor(GetHArg(argv, argc, 0)); // 0: means the zeroth parameter JSHandle newTarget(GetHArg(argv, argc, 1)); // 1: means the first parameter ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle obj; if (newTarget->IsUndefined()) { obj = factory->NewJSObjectByConstructor(ctor); } else { obj = factory->NewJSObjectByConstructor(ctor, newTarget); } if (obj.GetTaggedValue().IsJSShared()) { obj->GetJSHClass()->SetExtensible(false); } RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); return obj.GetTaggedType(); // state is not set here } DEF_RUNTIME_STUBS(NewObjRange) { RUNTIME_STUBS_HEADER(NewObjRange); JSHandle func = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle newTarget = GetHArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue firstArgIdx = GetArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue length = GetArg(argv, argc, 3); // 3: means the third parameter return RuntimeNewObjRange(thread, func, newTarget, static_cast(firstArgIdx.GetInt()), static_cast(length.GetInt())).GetRawData(); } DEF_RUNTIME_STUBS(DefineFunc) { RUNTIME_STUBS_HEADER(DefineFunc); JSHandle constpool = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue methodId = GetArg(argv, argc, 1); // 1: means the first parameter JSHandle module = GetHArg(argv, argc, 2); // 2: means the second parameter uint16_t length = static_cast(GetArg(argv, argc, 3).GetInt()); // 3: means the third parameter JSHandle env = GetHArg(argv, argc, 4); // 4: means the fourth parameter JSHandle homeObject = GetHArg(argv, argc, 5); // 5: means the fifth parameter return RuntimeDefinefunc(thread, constpool, static_cast(methodId.GetInt()), module, length, env, homeObject).GetRawData(); } DEF_RUNTIME_STUBS(CreateRegExpWithLiteral) { RUNTIME_STUBS_HEADER(CreateRegExpWithLiteral); JSHandle pattern = GetHArg(argv, argc, 0); JSTaggedValue flags = GetArg(argv, argc, 1); return RuntimeCreateRegExpWithLiteral(thread, pattern, static_cast(flags.GetInt())).GetRawData(); } DEF_RUNTIME_STUBS(ThrowIfSuperNotCorrectCall) { RUNTIME_STUBS_HEADER(ThrowIfSuperNotCorrectCall); JSTaggedValue index = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue thisValue = GetArg(argv, argc, 1); // 1: means the first parameter return RuntimeThrowIfSuperNotCorrectCall(thread, static_cast(index.GetInt()), thisValue).GetRawData(); } DEF_RUNTIME_STUBS(CreateObjectHavingMethod) { RUNTIME_STUBS_HEADER(CreateObjectHavingMethod); JSHandle literal = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle env = GetHArg(argv, argc, 1); // 1: means the first parameter EcmaVM *ecmaVm = thread->GetEcmaVM(); ObjectFactory *factory = ecmaVm->GetFactory(); return RuntimeCreateObjectHavingMethod(thread, factory, literal, env).GetRawData(); } DEF_RUNTIME_STUBS(CreateObjectWithExcludedKeys) { RUNTIME_STUBS_HEADER(CreateObjectWithExcludedKeys); JSTaggedValue numKeys = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle objVal = GetHArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue firstArgRegIdx = GetArg(argv, argc, 2); // 2: means the second parameter return RuntimeCreateObjectWithExcludedKeys(thread, static_cast(numKeys.GetInt()), objVal, static_cast(firstArgRegIdx.GetInt())).GetRawData(); } DEF_RUNTIME_STUBS(DefineMethod) { RUNTIME_STUBS_HEADER(DefineMethod); JSHandle method = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle homeObject = GetHArg(argv, argc, 1); // 1: means the first parameter uint16_t length = static_cast(GetArg(argv, argc, 2).GetInt()); // 2: means the second parameter JSHandle env = GetHArg(argv, argc, 3); // 3: means the third parameter JSHandle module = GetHArg(argv, argc, 4); // 4: means the fourth parameter auto res = RuntimeDefineMethod(thread, method, homeObject, length, env, module); #if ECMASCRIPT_ENABLE_IC const uint32_t INDEX_OF_SLOT_ID = 5; // 5: index of slotId in argv if (argc > INDEX_OF_SLOT_ID) { RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); uint16_t slotId = static_cast(GetArg(argv, argc, INDEX_OF_SLOT_ID).GetInt()); const uint32_t INDEX_OF_JS_FUNC = 6; // 6: index of jsFunc in argv ASSERT(argc > INDEX_OF_JS_FUNC); JSHandle jsFuncHandle = GetHArg(argv, argc, INDEX_OF_JS_FUNC); JSHandle resHandle(thread, res); SetProfileTypeInfoCellToFunction(thread, jsFuncHandle, resHandle, slotId); res = resHandle.GetTaggedValue(); } #endif return res.GetRawData(); } DEF_RUNTIME_STUBS(SetPatchModule) { RUNTIME_STUBS_HEADER(SetPatchModule); JSHandle func = GetHArg(argv, argc, 0); // 0: means the zeroth parameter RuntimeSetPatchModule(thread, func); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(CallSpread) { RUNTIME_STUBS_HEADER(CallSpread); JSHandle func = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle obj = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle array = GetHArg(argv, argc, 2); // 2: means the second parameter return RuntimeCallSpread(thread, func, obj, array).GetRawData(); } DEF_RUNTIME_STUBS(DefineGetterSetterByValue) { RUNTIME_STUBS_HEADER(DefineGetterSetterByValue); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle prop = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle getter = GetHArg(argv, argc, 2); // 2: means the second parameter JSHandle setter = GetHArg(argv, argc, 3); // 3: means the third parameter JSTaggedValue flag = GetArg(argv, argc, 4); // 4: means the fourth parameter JSHandle func = GetHArg(argv, argc, 5); // 5: means the sixth parameter int32_t pcOffset = GetArg(argv, argc, 6).GetInt(); // 6: means the seventh parameter bool bFlag = flag.ToBoolean(); return RuntimeDefineGetterSetterByValue(thread, obj, prop, getter, setter, bFlag, func, pcOffset).GetRawData(); } DEF_RUNTIME_STUBS(SuperCall) { RUNTIME_STUBS_HEADER(SuperCall); JSHandle func = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue firstVRegIdx = GetArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue length = GetArg(argv, argc, 2); // 2: means the second parameter auto sp = const_cast(thread->GetCurrentInterpretedFrame()); JSTaggedValue newTarget = InterpreterAssembly::GetNewTarget(thread, sp); return RuntimeSuperCall(thread, func, JSHandle(thread, newTarget), static_cast(firstVRegIdx.GetInt()), static_cast(length.GetInt())).GetRawData(); } DEF_RUNTIME_STUBS(OptSuperCall) { RUNTIME_STUBS_HEADER(OptSuperCall); JSHandle func = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle newTarget = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle taggedArray(thread, GetArg(argv, argc, 2)); // 2: means the second parameter JSTaggedValue length = GetArg(argv, argc, 3); // 3: means the third parameter return RuntimeOptSuperCall(thread, func, newTarget, taggedArray, static_cast(length.GetInt())).GetRawData(); } DEF_RUNTIME_STUBS(ThrowNotCallableException) { RUNTIME_STUBS_HEADER(ThrowNotCallableException); EcmaVM *ecmaVm = thread->GetEcmaVM(); ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle func = GetHArg(argv, argc, 0); std::string message = JSTaggedValue::ExceptionToString(thread, func); message.append(" is not callable"); JSHandle error = factory->GetJSError(ErrorType::TYPE_ERROR, message.c_str(), StackCheck::NO); thread->SetException(error.GetTaggedValue()); return JSTaggedValue::Exception().GetRawData(); } DEF_RUNTIME_STUBS(ThrowSetterIsUndefinedException) { RUNTIME_STUBS_HEADER(ThrowSetterIsUndefinedException); EcmaVM *ecmaVm = thread->GetEcmaVM(); ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle error = factory->GetJSError(ErrorType::TYPE_ERROR, "Cannot set property when setter is undefined", StackCheck::NO); thread->SetException(error.GetTaggedValue()); return JSTaggedValue::Exception().GetRawData(); } DEF_RUNTIME_STUBS(ThrowCallConstructorException) { RUNTIME_STUBS_HEADER(ThrowCallConstructorException); EcmaVM *ecmaVm = thread->GetEcmaVM(); ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle error = factory->GetJSError(ErrorType::TYPE_ERROR, "class constructor cannot called without 'new'", StackCheck::NO); thread->SetException(error.GetTaggedValue()); return JSTaggedValue::Exception().GetRawData(); } DEF_RUNTIME_STUBS(ThrowNonConstructorException) { RUNTIME_STUBS_HEADER(ThrowNonConstructorException); EcmaVM *ecmaVm = thread->GetEcmaVM(); ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle error = factory->GetJSError(ErrorType::TYPE_ERROR, "function is non-constructor", StackCheck::NO); thread->SetException(error.GetTaggedValue()); return JSTaggedValue::Exception().GetRawData(); } DEF_RUNTIME_STUBS(ThrowStackOverflowException) { RUNTIME_STUBS_HEADER(ThrowStackOverflowException); EcmaVM *ecmaVm = thread->GetEcmaVM(); // Multi-thread could cause stack-overflow-check failed too, // so check thread here to distinguish it with the actual stack overflow. ecmaVm->CheckThread(); LOG_ECMA(ERROR) << "Stack overflow! current:" << thread->GetCurrentStackPosition() << " limit:" << thread->GetStackLimit(); ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle error = factory->GetJSError(ErrorType::RANGE_ERROR, "Stack overflow!", StackCheck::NO); if (LIKELY(!thread->HasPendingException())) { thread->SetException(error.GetTaggedValue()); } return JSTaggedValue::Exception().GetRawData(); } DEF_RUNTIME_STUBS(ThrowDerivedMustReturnException) { RUNTIME_STUBS_HEADER(ThrowDerivedMustReturnException); EcmaVM *ecmaVm = thread->GetEcmaVM(); ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle error = factory->GetJSError(ErrorType::TYPE_ERROR, "Derived constructor must return object or undefined", StackCheck::NO); thread->SetException(error.GetTaggedValue()); return JSTaggedValue::Exception().GetRawData(); } DEF_RUNTIME_STUBS(LdBigInt) { RUNTIME_STUBS_HEADER(LdBigInt); JSHandle numberBigInt = GetHArg(argv, argc, 0); // 0: means the zeroth parameter 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); JSHandle value = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeToNumeric(thread, value).GetRawData(); } DEF_RUNTIME_STUBS(ToNumericConvertBigInt) { RUNTIME_STUBS_HEADER(ToNumericConvertBigInt); JSHandle value = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle numericVal(thread, RuntimeToNumeric(thread, value)); if (numericVal->IsBigInt()) { JSHandle bigNumericVal(numericVal); return BigInt::BigIntToNumber(bigNumericVal).GetRawData(); } return numericVal->GetRawData(); } DEF_RUNTIME_STUBS(DynamicImport) { RUNTIME_STUBS_HEADER(DynamicImport); JSHandle specifier = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle currentFunc = GetHArg(argv, argc, 1); // 1: means the zeroth parameter return RuntimeDynamicImport(thread, specifier, currentFunc).GetRawData(); } DEF_RUNTIME_STUBS(NewLexicalEnvWithName) { RUNTIME_STUBS_HEADER(NewLexicalEnvWithName); JSTaggedValue numVars = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue scopeId = GetArg(argv, argc, 1); // 1: means the first parameter return RuntimeNewLexicalEnvWithName(thread, static_cast(numVars.GetInt()), static_cast(scopeId.GetInt())).GetRawData(); } DEF_RUNTIME_STUBS(NewSendableEnv) { RUNTIME_STUBS_HEADER(NewSendableEnv); JSTaggedValue numVars = GetArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeNewSendableEnv(thread, static_cast(numVars.GetInt())).GetRawData(); } DEF_RUNTIME_STUBS(OptGetUnmapedArgs) { RUNTIME_STUBS_HEADER(OptGetUnmapedArgs); JSTaggedValue actualNumArgs = GetArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeOptGetUnmapedArgs(thread, actualNumArgs.GetInt()).GetRawData(); } DEF_RUNTIME_STUBS(OptNewLexicalEnvWithName) { RUNTIME_STUBS_HEADER(OptNewLexicalEnvWithName); JSTaggedValue taggedNumVars = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue taggedScopeId = GetArg(argv, argc, 1); // 1: means the first parameter JSHandle currentEnv = GetHArg(argv, argc, 2); // 2: means the second parameter JSHandle func = GetHArg(argv, argc, 3); // 3: means the third parameter uint16_t numVars = static_cast(taggedNumVars.GetInt()); uint16_t scopeId = static_cast(taggedScopeId.GetInt()); return RuntimeOptNewLexicalEnvWithName(thread, numVars, scopeId, currentEnv, func).GetRawData(); } DEF_RUNTIME_STUBS(OptCopyRestArgs) { RUNTIME_STUBS_HEADER(OptCopyRestArgs); JSTaggedValue actualArgc = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue restIndex = GetArg(argv, argc, 1); // 1: means the first parameter return RuntimeOptCopyRestArgs(thread, actualArgc.GetInt(), restIndex.GetInt()).GetRawData(); } DEF_RUNTIME_STUBS(OptNewObjRange) { RUNTIME_STUBS_HEADER(OptNewObjRange); return RuntimeOptNewObjRange(thread, argv, argc).GetRawData(); } DEF_RUNTIME_STUBS(GetTypeArrayPropertyByIndex) { RUNTIME_STUBS_HEADER(GetTypeArrayPropertyByIndex); JSTaggedValue obj = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue idx = GetArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue jsType = GetArg(argv, argc, 2); // 2: means the second parameter return JSTypedArray::FastGetPropertyByIndex(thread, obj, idx.GetInt(), JSType(jsType.GetInt())).GetRawData(); } DEF_RUNTIME_STUBS(SetTypeArrayPropertyByIndex) { RUNTIME_STUBS_HEADER(SetTypeArrayPropertyByIndex); JSTaggedValue obj = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue idx = GetArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue value = GetArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue jsType = GetArg(argv, argc, 3); // 3: means the third parameter return JSTypedArray::FastSetPropertyByIndex(thread, obj, idx.GetInt(), value, JSType(jsType.GetInt())).GetRawData(); } DEF_RUNTIME_STUBS(FastCopyElementToArray) { RUNTIME_STUBS_HEADER(FastCopyElementToArray); JSHandle typedArray = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle array = GetHArg(argv, argc, 1); // 1: means the first parameter return JSTaggedValue(JSTypedArray::FastCopyElementToArray(thread, typedArray, array)).GetRawData(); } DEF_RUNTIME_STUBS(GetPropertyByName) { RUNTIME_STUBS_HEADER(GetPropertyByName); JSHandle target = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle key = GetHArg(argv, argc, 1); // 1: means the first parameter return JSTaggedValue::GetProperty(thread, target, key).GetValue()->GetRawData(); } DEF_RUNTIME_STUBS(DebugAOTPrint) { RUNTIME_STUBS_HEADER(DebugAOTPrint); int ecmaOpcode = GetArg(argv, argc, 0).GetInt(); int path = GetArg(argv, argc, 1).GetInt(); std::string pathStr = path == 0 ? "slow path " : "TYPED path "; std::string data = JsStackInfo::BuildJsStackTrace(thread, true); std::string opcode = kungfu::GetEcmaOpcodeStr(static_cast(ecmaOpcode)); LOG_ECMA(INFO) << "AOT " << pathStr << ": " << opcode << "@ " << data; return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(ProfileOptimizedCode) { RUNTIME_STUBS_HEADER(ProfileOptimizedCode); JSHandle func = GetHArg(argv, argc, 0); int bcIndex = GetArg(argv, argc, 1).GetInt(); EcmaOpcode ecmaOpcode = static_cast(GetArg(argv, argc, 2).GetInt()); OptCodeProfiler::Mode mode = static_cast(GetArg(argv, argc, 3).GetInt()); OptCodeProfiler* profiler = thread->GetEcmaVM()->GetOptCodeProfiler(); profiler->Update(thread, func, bcIndex, ecmaOpcode, mode); return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(ProfileTypedOp) { RUNTIME_STUBS_HEADER(ProfileOptimizedCode); kungfu::OpCode opcode = static_cast(GetArg(argv, argc, 0).GetInt()); TypedOpProfiler* profiler = thread->GetEcmaVM()->GetTypedOpProfiler(); if (profiler != nullptr) { profiler->Update(opcode); } return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(VerifyVTableLoading) { RUNTIME_STUBS_HEADER(VerifyVTableLoading); JSHandle receiver = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle key = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle typedPathValue = GetHArg(argv, argc, 2); // 2: means the second parameter JSHandle verifiedPathValue = JSTaggedValue::GetProperty(thread, receiver, key).GetValue(); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); if (UNLIKELY(!JSTaggedValue::SameValue(thread, typedPathValue, verifiedPathValue))) { std::ostringstream oss; receiver->Dump(thread, oss); LOG_ECMA(ERROR) << "Verify VTable Load Failed, receiver: " << oss.str(); oss.str(""); LOG_ECMA(ERROR) << "Verify VTable Load Failed, key: " << EcmaStringAccessor(key.GetTaggedValue()).ToStdString(thread); typedPathValue->Dump(thread, oss); LOG_ECMA(ERROR) << "Verify VTable Load Failed, typed path value: " << oss.str(); oss.str(""); verifiedPathValue->Dump(thread, oss); LOG_ECMA(ERROR) << "Verify VTable Load Failed, verified path value: " << oss.str(); } return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(VerifyVTableStoring) { RUNTIME_STUBS_HEADER(VerifyVTableStoring); JSHandle receiver = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle key = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle storeValue = GetHArg(argv, argc, 2); // 2: means the second parameter JSHandle verifiedValue = JSTaggedValue::GetProperty(thread, receiver, key).GetValue(); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); if (UNLIKELY(!JSTaggedValue::SameValue(thread, storeValue, verifiedValue))) { std::ostringstream oss; receiver->Dump(thread, oss); LOG_ECMA(ERROR) << "Verify VTable Store Failed, receiver: " << oss.str(); oss.str(""); LOG_ECMA(ERROR) << "Verify VTable Store Failed, key: " << EcmaStringAccessor(key.GetTaggedValue()).ToStdString(thread); storeValue->Dump(thread, oss); LOG_ECMA(ERROR) << "Verify VTable Store Failed, typed path store value: " << oss.str(); oss.str(""); verifiedValue->Dump(thread, oss); LOG_ECMA(ERROR) << "Verify VTable Store Failed, verified path load value: " << oss.str(); } return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(JSObjectGetMethod) { RUNTIME_STUBS_HEADER(JSObjectGetMethod); JSHandle obj(thread, GetArg(argv, argc, 0)); JSHandle key(thread, GetArg(argv, argc, 1)); JSHandle result = JSObject::GetMethod(thread, obj, key); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); return result->GetRawData(); } DEF_RUNTIME_STUBS(BigIntEqual) { RUNTIME_STUBS_HEADER(BigIntEqual); JSTaggedValue left = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue right = GetArg(argv, argc, 1); // 1: means the first parameter if (BigInt::Equal(left, right)) { return JSTaggedValue::VALUE_TRUE; } return JSTaggedValue::VALUE_FALSE; } DEF_RUNTIME_STUBS(StringEqual) { RUNTIME_STUBS_HEADER(StringEqual); JSHandle left = GetHArg(argv, argc, 0); JSHandle right = GetHArg(argv, argc, 1); EcmaVM *vm = thread->GetEcmaVM(); left = JSHandle(thread, EcmaStringAccessor::Flatten(vm, left)); right = JSHandle(thread, EcmaStringAccessor::Flatten(vm, right)); if (EcmaStringAccessor::StringsAreEqualDiffUtfEncoding(thread, *left, *right)) { return JSTaggedValue::VALUE_TRUE; } return JSTaggedValue::VALUE_FALSE; } DEF_RUNTIME_STUBS(StringIndexOf) { RUNTIME_STUBS_HEADER(StringIndexOf); JSHandle receiver = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle searchElement = GetHArg(argv, argc, 1); // 1: means the first parameter uint32_t from = static_cast(GetArg(argv, argc, 2).GetInt()); // 2: means the second parameter uint32_t len = static_cast(GetArg(argv, argc, 3).GetInt()); // 3: means the third parameter return JSStableArray::IndexOf(thread, receiver, searchElement, from, len).GetRawData(); } DEF_RUNTIME_STUBS(LdPatchVar) { RUNTIME_STUBS_HEADER(LdPatchVar); JSTaggedValue idx = GetArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeLdPatchVar(thread, idx.GetInt()).GetRawData(); } DEF_RUNTIME_STUBS(StPatchVar) { RUNTIME_STUBS_HEADER(StPatchVar); JSTaggedValue idx = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle value = GetHArg(argv, argc, 1); // 1: means the first parameter return RuntimeStPatchVar(thread, idx.GetInt(), value).GetRawData(); } DEF_RUNTIME_STUBS(NotifyConcurrentResult) { RUNTIME_STUBS_HEADER(NotifyConcurrentResult); JSTaggedValue result = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue hint = GetArg(argv, argc, 1); // 1: means the first parameter return RuntimeNotifyConcurrentResult(thread, result, hint).GetRawData(); } DEF_RUNTIME_STUBS(NotifyArrayPrototypeChanged) { RUNTIME_STUBS_HEADER(NotifyArrayPrototypeChanged); thread->GetEcmaVM()->GetGlobalEnv()->NotifyDetectorDeoptimize( thread, GlobalEnv::ArrayPrototypeChangedGuardiansBits::START_BIT); return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(UpdateAOTHClass) { RUNTIME_STUBS_HEADER(UpdateAOTHClass); JSHandle oldhclass = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle newhclass = GetHArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue key = GetArg(argv, argc, 2); // 2: means the second parameter return RuntimeUpdateAOTHClass(thread, oldhclass, newhclass, key).GetRawData(); } DEF_RUNTIME_STUBS(DefineField) { RUNTIME_STUBS_HEADER(DefineField); JSTaggedValue obj = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue propKey = GetArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue value = GetArg(argv, argc, 2); // 2: means the second parameter return RuntimeDefineField(thread, obj, propKey, value).GetRawData(); } DEF_RUNTIME_STUBS(CreatePrivateProperty) { RUNTIME_STUBS_HEADER(CreatePrivateProperty); JSTaggedValue lexicalEnv = GetArg(argv, argc, 0); // 0: means the zeroth parameter uint32_t count = static_cast(GetArg(argv, argc, 1).GetInt()); // 1: means the first parameter JSTaggedValue constpool = GetArg(argv, argc, 2); // 2: means the second parameter uint32_t literalId = static_cast(GetArg(argv, argc, 3).GetInt()); // 3: means the third parameter JSTaggedValue module = GetArg(argv, argc, 4); // 4: means the fourth parameter return RuntimeCreatePrivateProperty(thread, lexicalEnv, count, constpool, literalId, module).GetRawData(); } DEF_RUNTIME_STUBS(DefinePrivateProperty) { RUNTIME_STUBS_HEADER(DefinePrivateProperty); JSTaggedValue lexicalEnv = GetArg(argv, argc, 0); // 0: means the zeroth parameter uint32_t levelIndex = static_cast(GetArg(argv, argc, 1).GetInt()); // 1: means the first parameter uint32_t slotIndex = static_cast(GetArg(argv, argc, 2).GetInt()); // 2: means the second parameter JSTaggedValue obj = GetArg(argv, argc, 3); // 3: means the third parameter JSTaggedValue value = GetArg(argv, argc, 4); // 4: means the fourth parameter return RuntimeDefinePrivateProperty(thread, lexicalEnv, levelIndex, slotIndex, obj, value).GetRawData(); } DEF_RUNTIME_STUBS(ContainerRBTreeForEach) { RUNTIME_STUBS_HEADER(ContainerRBTreeForEach); JSHandle node = GetHArg(argv, argc, 0); // 0: param index JSHandle callbackFnHandle = GetHArg(argv, argc, 1); // 1: param index JSHandle thisArgHandle = GetHArg(argv, argc, 2); // 2: param index JSHandle thisHandle = GetHArg(argv, argc, 3); // 3: param index JSHandle type = GetHArg(argv, argc, 4); // 4: param index ASSERT(node->IsRBTreeNode()); ASSERT(callbackFnHandle->IsCallable()); ASSERT(type->IsInt()); JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); auto containersType = static_cast(type->GetInt()); JSMutableHandle queue(thread, thread->GetEcmaVM()->GetFactory()->NewTaggedQueue(0)); JSMutableHandle treeNode(thread, JSTaggedValue::Undefined()); queue.Update(JSTaggedValue(TaggedQueue::Push(thread, queue, node))); while (!queue->Empty(thread)) { treeNode.Update(queue->Pop(thread)); EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, 3); // 3: three args RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); info->SetCallArg(containersType == kungfu::ContainersType::HASHSET_FOREACH ? treeNode->GetKey(thread) : treeNode->GetValue(thread), treeNode->GetKey(thread), thisHandle.GetTaggedValue()); JSTaggedValue funcResult = JSFunction::Call(info); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult.GetRawData()); if (!treeNode->GetLeft(thread).IsHole()) { JSHandle left(thread, treeNode->GetLeft(thread)); queue.Update(JSTaggedValue(TaggedQueue::Push(thread, queue, left))); } if (!treeNode->GetRight(thread).IsHole()) { JSHandle right(thread, treeNode->GetRight(thread)); queue.Update(JSTaggedValue(TaggedQueue::Push(thread, queue, right))); } } return JSTaggedValue::True().GetRawData(); } DEF_RUNTIME_STUBS(GetOrInternStringFromHashTrieTable) { RUNTIME_STUBS_HEADER(GetOrInternStringFromHashTrieTable); JSHandle value = GetHArg(argv, argc, 0); // 0: means the zeroth parameter ASSERT(value->IsString()); JSHandle str = JSTaggedValue::ToString(thread, value); EcmaStringTable *stringTable = thread->GetEcmaVM()->GetEcmaStringTable(); return JSTaggedValue::Cast(static_cast(stringTable->GetOrInternString(thread->GetEcmaVM(), *str))); } DEF_RUNTIME_STUBS(InsertStringToTable) { #if !ENABLE_NEXT_OPTIMIZATION RUNTIME_STUBS_HEADER(InsertStringToTable); JSHandle str = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return JSTaggedValue::Cast( static_cast(thread->GetEcmaVM()->GetEcmaStringTable()->InsertStringToTable(thread->GetEcmaVM(), str))); #else return JSTaggedType(); #endif } DEF_RUNTIME_STUBS(SlowFlattenString) { RUNTIME_STUBS_HEADER(SlowFlattenString); JSHandle str = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return JSTaggedValue(EcmaStringAccessor::SlowFlatten(thread->GetEcmaVM(), str)).GetRawData(); } DEF_RUNTIME_STUBS(TryGetInternString) { RUNTIME_STUBS_HEADER(TryGetInternString); JSHandle string = GetHArg(argv, argc, 0); // 0: means the zeroth parameter return RuntimeTryGetInternString(argGlue, string); } DEF_RUNTIME_STUBS(FastCopyFromArrayToTypedArray) { RUNTIME_STUBS_HEADER(FastCopyFromArrayToTypedArray); JSHandle targetArray = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue len = GetArg(argv, argc, 1); // 1: param index JSHandle obj = GetHArg(argv, argc, 2); // 2: param index return JSStableArray::FastCopyFromArrayToTypedArray(thread, targetArray, base::TypedArrayHelper::GetType(targetArray), 0, len.GetInt(), obj).GetRawData(); } DEF_RUNTIME_STUBS(DecodeURIComponent) { RUNTIME_STUBS_HEADER(DecodeURIComponent); JSHandle arg = GetHArg(argv, argc, 0); JSHandle string = JSTaggedValue::ToString(thread, arg); if (thread->HasPendingException()) { return JSTaggedValue::VALUE_EXCEPTION; } if (EcmaStringAccessor(string).IsTreeString()) { string = JSHandle(thread, EcmaStringAccessor::Flatten(thread->GetEcmaVM(), string)); } auto stringAcc = EcmaStringAccessor(string); JSTaggedValue result; if (stringAcc.IsLineString()) { // line string or flatten tree string if (!stringAcc.IsUtf16()) { result = RuntimeDecodeURIComponent(thread, string, stringAcc.GetDataUtf8()); } else { result = RuntimeDecodeURIComponent(thread, string, stringAcc.GetDataUtf16()); } } else { ASSERT(stringAcc.IsSlicedString()); auto parent = SlicedEcmaString::Cast(string.GetTaggedValue())->GetParent(thread); auto parentStrAcc = EcmaStringAccessor(parent); auto startIndex = SlicedEcmaString::Cast(string.GetTaggedValue())->GetStartIndex(); #if !ENABLE_NEXT_OPTIMIZATION if (parentStrAcc.IsLineString()) { if (parentStrAcc.IsUtf8()) { result = RuntimeDecodeURIComponent(thread, string, parentStrAcc.GetDataUtf8() + startIndex); } else { result = RuntimeDecodeURIComponent(thread, string, parentStrAcc.GetDataUtf16() + startIndex); } #else // ENABLE_NEXT_OPTIMIZATION if (parentStrAcc.IsLineString() && !parentStrAcc.IsUtf8()) { result = RuntimeDecodeURIComponent(thread, string, parentStrAcc.GetDataUtf16() + startIndex); #endif // ENABLE_NEXT_OPTIMIZATION } else { result = RuntimeDecodeURIComponent(thread, string, parentStrAcc.GetDataUtf8() + startIndex); } } return result.GetRawData(); } void RuntimeStubs::UpdateFieldType(uintptr_t argGlue, JSTaggedType hclass, uint64_t value) { auto cls = reinterpret_cast(hclass); PropertyAttributes attrValue(value); JSHClass::UpdateFieldType(JSThread::GlueToJSThread(argGlue), cls, attrValue); } JSTaggedType RuntimeStubs::GetActualArgvNoGC(uintptr_t argGlue) { DISALLOW_GARBAGE_COLLECTION; auto thread = JSThread::GlueToJSThread(argGlue); JSTaggedType *current = const_cast(thread->GetLastLeaveFrame()); FrameIterator it(current, thread); ASSERT(it.IsOptimizedFrame()); it.Advance(); ASSERT(it.IsAotOrJitFunctionFrame()); if (it.IsFastJitFunctionFrame()) { auto fastJitFunctionFrame = it.GetFrame(); return reinterpret_cast(fastJitFunctionFrame->GetArgv(it)); } else { auto optimizedJSFunctionFrame = it.GetFrame(); return reinterpret_cast(optimizedJSFunctionFrame->GetArgv(it)); } } double RuntimeStubs::FloatMod(double x, double y) { return std::fmod(x, y); } double RuntimeStubs::FloatAcos(double x) { return std::acos(x); } double RuntimeStubs::FloatAcosh(double x) { return std::acosh(x); } double RuntimeStubs::FloatAsin(double x) { return std::asin(x); } double RuntimeStubs::FloatAsinh(double x) { return std::asinh(x); } double RuntimeStubs::FloatAtan(double x) { return std::atan(x); } double RuntimeStubs::FloatAtan2(double y, double x) { return std::atan2(y, x); } double RuntimeStubs::FloatAtanh(double x) { return std::atanh(x); } double RuntimeStubs::FloatCos(double x) { return std::cos(x); } double RuntimeStubs::FloatCosh(double x) { return std::cosh(x); } double RuntimeStubs::FloatSin(double x) { return std::sin(x); } double RuntimeStubs::FloatSinh(double x) { return std::sinh(x); } double RuntimeStubs::FloatTan(double x) { return std::tan(x); } double RuntimeStubs::FloatTanh(double x) { return std::tanh(x); } double RuntimeStubs::FloatCbrt(double x) { return std::cbrt(x); } double RuntimeStubs::FloatTrunc(double x) { return std::trunc(x); } double RuntimeStubs::FloatCeil(double x) { return std::ceil(x); } double RuntimeStubs::FloatFloor(double x) { return std::floor(x); } double RuntimeStubs::FloatLog(double x) { return std::log(x); } double RuntimeStubs::FloatLog2(double x) { return std::log2(x); } double RuntimeStubs::FloatLog10(double x) { return std::log10(x); } double RuntimeStubs::FloatLog1p(double x) { return std::log1p(x); } double RuntimeStubs::FloatExp(double x) { return std::exp(x); } double RuntimeStubs::FloatExpm1(double x) { return std::expm1(x); } double RuntimeStubs::FloatPow(double base, double exp) { return std::pow(base, exp); } double RuntimeStubs::CallDateNow() { // time from now is in ms. int64_t ans; struct timeval tv { }; gettimeofday(&tv, nullptr); ans = static_cast(tv.tv_sec) * MS_PER_SECOND + (tv.tv_usec / MS_PER_SECOND); return static_cast(ans); } int32_t RuntimeStubs::DoubleToInt(double x, size_t bits) { return base::NumberHelper::DoubleToInt(x, bits); } int32_t RuntimeStubs::SaturateTruncDoubleToInt32(double x) { return base::NumberHelper::SaturateTruncDoubleToInt32(x); } uint8_t RuntimeStubs::LrInt(double x) { DISALLOW_GARBAGE_COLLECTION; return static_cast(std::lrint(x)); } void RuntimeStubs::InsertOldToNewRSet([[maybe_unused]] uintptr_t argGlue, uintptr_t object, size_t offset) { Region *region = Region::ObjectAddressToRange(object); uintptr_t slotAddr = object + offset; return region->InsertOldToNewRSet(slotAddr); } void RuntimeStubs::InsertLocalToShareRSet([[maybe_unused]] uintptr_t argGlue, uintptr_t object, size_t offset) { Region *region = Region::ObjectAddressToRange(object); uintptr_t slotAddr = object + offset; region->InsertLocalToShareRSet(slotAddr); } void RuntimeStubs::SetBitAtomic(GCBitset::GCBitsetWord *word, GCBitset::GCBitsetWord mask, GCBitset::GCBitsetWord oldValue) { volatile auto atomicWord = reinterpret_cast *>(word); GCBitset::GCBitsetWord oldValueBeforeCAS = oldValue; std::atomic_compare_exchange_strong_explicit(atomicWord, &oldValue, oldValue | mask, std::memory_order_release, std::memory_order_relaxed); while (oldValue != oldValueBeforeCAS) { if (oldValue & mask) { return; } oldValueBeforeCAS = oldValue; std::atomic_compare_exchange_strong_explicit(atomicWord, &oldValue, oldValue | mask, std::memory_order_release, std::memory_order_relaxed); } } void RuntimeStubs::MarkingBarrier([[maybe_unused]] uintptr_t argGlue, uintptr_t object, size_t offset, TaggedObject *value) { uintptr_t slotAddr = object + offset; Region *objectRegion = Region::ObjectAddressToRange(object); Region *valueRegion = Region::ObjectAddressToRange(value); ASSERT(!valueRegion->InSharedHeap()); auto thread = JSThread::GlueToJSThread(argGlue); #if ECMASCRIPT_ENABLE_BARRIER_CHECK if (!thread->GetEcmaVM()->GetHeap()->IsAlive(JSTaggedValue(value).GetHeapObject())) { LOG_FULL(FATAL) << "RuntimeStubs::MarkingBarrier checked value:" << value << " is invalid!"; } #endif ASSERT(thread->IsConcurrentMarkingOrFinished()); if (!g_isEnableCMCGC) { Barriers::Update(thread, slotAddr, objectRegion, value, valueRegion); } } void RuntimeStubs::SharedGCMarkingBarrier(uintptr_t argGlue, uintptr_t object, size_t offset, TaggedObject *value) { uintptr_t slotAddr = object + offset; Region *objectRegion = Region::ObjectAddressToRange(object); Region *valueRegion = Region::ObjectAddressToRange(value); ASSERT(valueRegion->InSharedSweepableSpace()); auto thread = JSThread::GlueToJSThread(argGlue); #if ECMASCRIPT_ENABLE_BARRIER_CHECK if (!thread->GetEcmaVM()->GetHeap()->IsAlive(JSTaggedValue(value).GetHeapObject())) { LOG_FULL(FATAL) << "RuntimeStubs::SharedGCMarkingBarrier checked value:" << value << " is invalid!"; } #endif ASSERT(thread->IsSharedConcurrentMarkingOrFinished()); if (!g_isEnableCMCGC) { Barriers::UpdateShared(thread, slotAddr, objectRegion, value, valueRegion); } } void RuntimeStubs::CMCGCMarkingBarrier([[maybe_unused]] uintptr_t argGlue, [[maybe_unused]] uintptr_t object, [[maybe_unused]] size_t offset, [[maybe_unused]] TaggedObject *value) { auto thread = JSThread::GlueToJSThread(argGlue); ASSERT(g_isEnableCMCGC); Barriers::CMCWriteBarrier(thread, (TaggedObject*)object, offset, JSTaggedType(value)); } JSTaggedType RuntimeStubs::ReadBarrier(uintptr_t argGlue, uintptr_t addr) { auto thread = JSThread::GlueToJSThread(argGlue); return Barriers::ReadBarrierForObject(thread, addr); } void RuntimeStubs::CopyCallTarget(uintptr_t argGlue, uintptr_t callTarget) { auto thread = JSThread::GlueToJSThread(argGlue); base::GCHelper::CopyCallTarget(thread, reinterpret_cast(callTarget)); } void RuntimeStubs::CopyArgvArray(uintptr_t argGlue, uintptr_t argv, uint64_t argc) { auto thread = JSThread::GlueToJSThread(argGlue); base::GCHelper::CopyArgvArray(thread, reinterpret_cast(argv), argc); // argv should be ToSpace Reference } bool RuntimeStubs::BigIntEquals(JSTaggedType left, JSTaggedType right) { DISALLOW_GARBAGE_COLLECTION; return BigInt::Equal(JSTaggedValue(left), JSTaggedValue(right)); } bool RuntimeStubs::BigIntSameValueZero(JSTaggedType left, JSTaggedType right) { DISALLOW_GARBAGE_COLLECTION; return BigInt::SameValueZero(JSTaggedValue(left), JSTaggedValue(right)); } JSTaggedValue RuntimeStubs::JSHClassFindProtoTransitions(uintptr_t argGlue, JSHClass *cls, JSTaggedValue key, JSTaggedValue proto) { DISALLOW_GARBAGE_COLLECTION; return JSTaggedValue(cls->FindProtoTransitions(JSThread::GlueToJSThread(argGlue), key, proto)); } JSTaggedValue RuntimeStubs::NumberHelperStringToDouble(uintptr_t argGlue, EcmaString *numberString) { DISALLOW_GARBAGE_COLLECTION; CVector buf; JSThread *thread = JSThread::GlueToJSThread(argGlue); Span str = EcmaStringAccessor(numberString).ToUtf8Span(thread, buf); if (base::NumberHelper::IsEmptyString(str.begin(), str.end())) { return base::BuiltinsBase::GetTaggedDouble(base::NAN_VALUE); } double result = base::NumberHelper::StringToDouble(str.begin(), str.end(), 0, base::IGNORE_TRAILING); return base::BuiltinsBase::GetTaggedDouble(result); } double RuntimeStubs::TimeClip(double time) { DISALLOW_GARBAGE_COLLECTION; return JSDate::TimeClip(time); } double RuntimeStubs::SetDateValues(double year, double month, double day) { DISALLOW_GARBAGE_COLLECTION; if (std::isnan(year) || !std::isfinite(year) || std::isnan(month) || !std::isfinite(month) || std::isnan(day) || !std::isfinite(day)) { return base::NAN_VALUE; } return JSDate::SetDateValues(static_cast(year), static_cast(month), static_cast(day)); } JSTaggedValue RuntimeStubs::NewObject(EcmaRuntimeCallInfo *info) { ASSERT(info); JSThread *thread = info->GetThread(); JSHandle func(info->GetFunction()); if (!func->IsHeapObject()) { RETURN_STACK_BEFORE_THROW_IF_ASM(thread); THROW_TYPE_ERROR_AND_RETURN(thread, "function is nullptr", JSTaggedValue::Exception()); } if (!func->IsJSFunction()) { if (func->IsBoundFunction()) { JSTaggedValue result = JSBoundFunction::ConstructInternal(info); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return result; } if (func->IsJSProxy()) { JSTaggedValue jsObj = JSProxy::ConstructInternal(info); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return jsObj; } THROW_TYPE_ERROR_AND_RETURN(thread, "Constructed NonConstructable", JSTaggedValue::Exception()); } JSTaggedValue result = JSFunction::ConstructInternal(info); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return result; } void RuntimeStubs::SaveFrameToContext(JSThread *thread, JSHandle context) { FrameHandler frameHandler(thread); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); uint32_t nregs = frameHandler.GetNumberArgs(); JSHandle regsArray = factory->NewTaggedArray(nregs); for (uint32_t i = 0; i < nregs; i++) { JSTaggedValue value = frameHandler.GetVRegValue(i); regsArray->Set(thread, i, value); } context->SetRegsArray(thread, regsArray.GetTaggedValue()); JSTaggedValue function = frameHandler.GetFunction(); JSFunction *func = JSFunction::Cast(function.GetTaggedObject()); Method *method = func->GetCallTarget(thread); if (func->IsCompiledCode()) { bool isFastCall = func->IsCompiledFastCall(); // get this flag before clear it uintptr_t entry = isFastCall ? thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_FastCallToAsmInterBridge) : thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_AOTCallToAsmInterBridge); func->SetCodeEntry(entry); method->ClearAOTStatusWhenDeopt(entry); func->ClearCompiledCodeFlags(); } context->SetMethod(thread, function); context->SetThis(thread, frameHandler.GetThis()); uint32_t offset = 0; // pc in baseline is not real bytecode offset, so skip to get the offset if (reinterpret_cast(frameHandler.GetPc()) != std::numeric_limits::max()) { BytecodeInstruction ins(frameHandler.GetPc()); offset = ins.GetSize(); } context->SetAcc(thread, frameHandler.GetAcc()); context->SetLexicalEnv(thread, thread->GetCurrentLexenv()); context->SetNRegs(nregs); context->SetBCOffset(frameHandler.GetBytecodeOffset() + offset); } JSTaggedValue RuntimeStubs::CallBoundFunction(EcmaRuntimeCallInfo *info) { JSThread *thread = info->GetThread(); JSHandle boundFunc(info->GetFunction()); if (boundFunc->GetBoundTarget(thread).IsJSFunction()) { JSHandle targetFunc(thread, boundFunc->GetBoundTarget(thread)); if (targetFunc->IsClassConstructor()) { THROW_TYPE_ERROR_AND_RETURN(thread, "class constructor cannot called without 'new'", JSTaggedValue::Exception()); } } JSHandle boundArgs(thread, boundFunc->GetBoundArguments(thread)); const uint32_t boundLength = boundArgs->GetLength(); const uint32_t argsLength = info->GetArgsNumber() + boundLength; JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); EcmaRuntimeCallInfo *runtimeInfo = EcmaInterpreter::NewRuntimeCallInfo(thread, JSHandle(thread, boundFunc->GetBoundTarget(thread)), info->GetThis(), undefined, argsLength); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); if (boundLength == 0) { runtimeInfo->SetCallArg(argsLength, 0, info, 0); } else { // 0 ~ boundLength is boundArgs; boundLength ~ argsLength is args of EcmaRuntimeCallInfo. runtimeInfo->SetCallArg(boundLength, boundArgs); runtimeInfo->SetCallArg(argsLength, boundLength, info, 0); } return EcmaInterpreter::Execute(runtimeInfo); } DEF_RUNTIME_STUBS(DeoptHandler) { RUNTIME_STUBS_HEADER(DeoptHandler); kungfu::DeoptType type = static_cast(GetTArg(argv, argc, 0)); JSHandle maybeAcc = GetHArg(argv, argc, 1); size_t depth = Deoptimizier::GetInlineDepth(thread); Deoptimizier deopt(thread, depth, type); std::vector deoptBundle; deopt.CollectDeoptBundleVec(deoptBundle); ASSERT(!deoptBundle.empty()); size_t shift = Deoptimizier::ComputeShift(depth); deopt.CollectVregs(deoptBundle, shift); deopt.UpdateAndDumpDeoptInfo(type); return deopt.ConstructAsmInterpretFrame(maybeAcc); } DEF_RUNTIME_STUBS(AotInlineTrace) { RUNTIME_STUBS_HEADER(AotInlineTrace); JSTaggedValue callerFunc = GetArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue inlineFunc = GetArg(argv, argc, 1); // 1: means the first parameter JSFunction *callerJSFunc = JSFunction::Cast(callerFunc); JSFunction *inlineJSFunc = JSFunction::Cast(inlineFunc); Method *callerMethod = Method::Cast(JSFunction::Cast(callerJSFunc)->GetMethod(thread)); Method *inlineMethod = Method::Cast(JSFunction::Cast(inlineJSFunc)->GetMethod(thread)); auto callerRecordName = callerMethod->GetRecordNameStr(thread); auto inlineRecordNanme = inlineMethod->GetRecordNameStr(thread); const std::string callerFuncName(callerMethod->GetMethodName(thread)); const std::string inlineFuncNanme(inlineMethod->GetMethodName(thread)); std::string callerFullName = callerFuncName + "@" + std::string(callerRecordName); std::string inlineFullName = inlineFuncNanme + "@" + std::string(inlineRecordNanme); LOG_TRACE(INFO) << "aot inline function name: " << inlineFullName << " caller function name: " << callerFullName; return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(AotInlineBuiltinTrace) { RUNTIME_STUBS_HEADER(AotInlineBuiltinTrace); JSTaggedValue callerFunc = GetArg(argv, argc, 0); JSFunction *callerJSFunc = JSFunction::Cast(callerFunc); Method *callerMethod = Method::Cast(callerJSFunc->GetMethod(thread)); auto callerRecordName = callerMethod->GetRecordNameStr(thread); const std::string callerFuncName(callerMethod->GetMethodName(thread)); std::string callerFullName = callerFuncName + "@" + std::string(callerRecordName); auto builtinId = static_cast(GetArg(argv, argc, 1).GetInt()); LOG_TRACE(INFO) << "aot inline builtin: " << kungfu::BuiltinsStubCSigns::GetBuiltinName(builtinId) << ", caller function name:" << callerFullName; return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(AotCallBuiltinTrace) { RUNTIME_STUBS_HEADER(AotCallBuiltinTrace); JSTaggedValue callerFunc = GetArg(argv, argc, 0); JSFunction *callerJSFunc = JSFunction::Cast(callerFunc); Method *callerMethod = Method::Cast(callerJSFunc->GetMethod(thread)); auto callerRecordName = callerMethod->GetRecordNameStr(thread); const std::string callerFuncName(callerMethod->GetMethodName(thread)); std::string callerFullName = callerFuncName + "@" + std::string(callerRecordName); auto builtinId = static_cast(GetArg(argv, argc, 1).GetInt()); LOG_TRACE(INFO) << "aot call builtin: " << kungfu::BuiltinsStubCSigns::GetBuiltinName(builtinId) << ", caller function name:" << callerFullName; return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(LocaleCompare) { RUNTIME_STUBS_HEADER(LocaleCompare); JSHandle thisTag = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle thatTag = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle locales = GetHArg(argv, argc, 2); // 2: means the second parameter JSHandle options = GetHArg(argv, argc, 3); // 3: means the third parameter JSHandle thisObj(JSTaggedValue::RequireObjectCoercible(thread, thisTag)); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); [[maybe_unused]] JSHandle thisHandle = JSTaggedValue::ToString(thread, thisObj); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); [[maybe_unused]] JSHandle thatHandle = JSTaggedValue::ToString(thread, thatTag); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); return builtins::BuiltinsString::DoLocaleCompare(thread, thisHandle, thatHandle, locales, options).GetRawData(); } DEF_RUNTIME_STUBS(ArraySort) { RUNTIME_STUBS_HEADER(ArraySort); JSHandle thisHandle = GetHArg(argv, argc, 0); return RuntimeArraySort(thread, thisHandle).GetRawData(); } JSTaggedValue RuntimeStubs::RuntimeArraySort(JSThread *thread, JSHandle thisHandle) { // 1. Let obj be ToObject(this value). JSHandle thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception()); // 2. Let len be ToLength(Get(obj, "length")). int64_t len = ArrayHelper::GetArrayLength(thread, JSHandle(thisObjHandle)); // 3. ReturnIfAbrupt(len). RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception()); JSHandle hclass(thread, thisObjHandle->GetClass()); if (!hclass->IsDictionaryElement()) { JSHandle elements(thread, thisObjHandle->GetElements(thread)); // remove elements number check with pgo later and add int fast path at the same time if (len <= elements->GetLength() && CheckElementsNumber(thread, elements, len)) { return ArrayNumberSort(thread, thisObjHandle, len); } } JSHandle callbackFnHandle(thread, JSTaggedValue::Undefined()); JSArray::Sort(thread, JSHandle::Cast(thisObjHandle), callbackFnHandle); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception()); return thisObjHandle.GetTaggedValue(); } DEF_RUNTIME_STUBS(HClassCloneWithAddProto) { RUNTIME_STUBS_HEADER(HClassCloneWithAddProto); JSHandle jshclass = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle key = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle proto = GetHArg(argv, argc, 2); // 2: means the second parameter return JSHClass::CloneWithAddProto(thread, jshclass, key, proto).GetTaggedValue().GetRawData(); } void RuntimeStubs::StartCallTimer(uintptr_t argGlue, JSTaggedType func, bool isAot) { DISALLOW_GARBAGE_COLLECTION; auto thread = JSThread::GlueToJSThread(argGlue); JSTaggedValue callTarget(func); Method *method = Method::Cast(JSFunction::Cast(callTarget)->GetMethod(thread)); if (method->IsNativeWithCallField()) { return; } size_t methodId = method->GetMethodId().GetOffset(); auto callTimer = thread->GetEcmaVM()->GetCallTimer(); callTimer->InitialStatAndTimer(thread, method, methodId, isAot); callTimer->StartCount(methodId, isAot); } void RuntimeStubs::EndCallTimer(uintptr_t argGlue, JSTaggedType func) { DISALLOW_GARBAGE_COLLECTION; auto thread = JSThread::GlueToJSThread(argGlue); JSTaggedValue callTarget(func); Method *method = Method::Cast(JSFunction::Cast(callTarget)->GetMethod(thread)); if (method->IsNativeWithCallField()) { return; } auto callTimer = thread->GetEcmaVM()->GetCallTimer(); callTimer->StopCount(thread, method); } int32_t RuntimeStubs::StringGetStart(bool isUtf8, EcmaString *srcString, int32_t length, int32_t startIndex) { DISALLOW_GARBAGE_COLLECTION; if (isUtf8) { Span data(EcmaStringAccessor(srcString).GetDataUtf8() + startIndex, length); return static_cast(base::StringHelper::GetStart(data, length)); } else { Span data(EcmaStringAccessor(srcString).GetDataUtf16() + startIndex, length); return static_cast(base::StringHelper::GetStart(data, length)); } } int32_t RuntimeStubs::StringGetEnd(bool isUtf8, EcmaString *srcString, int32_t start, int32_t length, int32_t startIndex) { DISALLOW_GARBAGE_COLLECTION; if (isUtf8) { Span data(EcmaStringAccessor(srcString).GetDataUtf8() + startIndex, length); return base::StringHelper::GetEnd(data, start, length); } else { Span data(EcmaStringAccessor(srcString).GetDataUtf16() + startIndex, length); return base::StringHelper::GetEnd(data, start, length); } } DEF_RUNTIME_STUBS(FastStringify) { RUNTIME_STUBS_HEADER(FastStringify); JSHandle value = GetHArg(argv, argc, 0); JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); base::JsonStringifier jsonStringifier(thread); JSHandle result = jsonStringifier.Stringify(value, undefined, undefined); return result.GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(GetLinkedHash) { RUNTIME_STUBS_HEADER(GetLinkedHash); JSTaggedValue key = GetArg(argv, argc, 0); // 0: means the zeroth parameter return JSTaggedValue(LinkedHash::Hash(thread, key)).GetRawData(); } DEF_RUNTIME_STUBS(LinkedHashMapComputeCapacity) { RUNTIME_STUBS_HEADER(LinkedHashMapComputeCapacity); JSTaggedValue value = GetArg(argv, argc, 0); // 0: means the zeroth parameter return JSTaggedValue(LinkedHashMap::ComputeCapacity(value.GetInt())).GetRawData(); } DEF_RUNTIME_STUBS(LinkedHashSetComputeCapacity) { RUNTIME_STUBS_HEADER(LinkedHashSetComputeCapacity); JSTaggedValue value = GetArg(argv, argc, 0); // 0: means the zeroth parameter return JSTaggedValue(LinkedHashSet::ComputeCapacity(value.GetInt())).GetRawData(); } DEF_RUNTIME_STUBS(ObjectSlowAssign) { RUNTIME_STUBS_HEADER(ObjectSlowAssign); JSHandle toAssign = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle source = GetHArg(argv, argc, 1); // 1: means the first parameter return builtins::BuiltinsObject::AssignTaggedValue(thread, source, toAssign).GetRawData(); } DEF_RUNTIME_STUBS(NameDictionaryGetAllEnumKeys) { RUNTIME_STUBS_HEADER(NameDictionaryGetAllEnumKeys); JSHandle object = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue argKeys = GetArg(argv, argc, 1); // 1: means the first parameter int numOfKeys = argKeys.GetInt(); uint32_t keys = 0; ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle keyArray = factory->NewTaggedArray(numOfKeys); NameDictionary *dict = NameDictionary::Cast(object->GetProperties(thread).GetTaggedObject()); dict->GetAllEnumKeys(thread, 0, keyArray, &keys); if (keys < keyArray->GetLength()) { keyArray->Trim(thread, keys); } return keyArray.GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(NumberDictionaryGetAllEnumKeys) { RUNTIME_STUBS_HEADER(NumberDictionaryGetAllEnumKeys); JSHandle array = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle elementArray = GetHArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue argKeys = GetArg(argv, argc, 2); // 2: means the second parameter int elementIndex = argKeys.GetInt(); uint32_t keys = elementIndex; NumberDictionary::GetAllEnumKeys( thread, JSHandle(array), elementIndex, elementArray, &keys); if (keys < elementArray->GetLength()) { elementArray->Trim(thread, keys); } return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(NumberToString) { RUNTIME_STUBS_HEADER(NumberToString); JSTaggedValue argKeys = GetArg(argv, argc, 0); return JSHandle::Cast(base::NumberHelper::NumberToString(thread, argKeys)).GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(NumberBigIntNativePointerToString) { RUNTIME_STUBS_HEADER(NumberBigIntNativePointerToString); JSTaggedValue argKeys = GetArg(argv, argc, 0); if (argKeys.IsNumber()) { return JSHandle::Cast(base::NumberHelper::NumberToString(thread, argKeys)).GetTaggedValue().GetRawData(); } JSHandle tagged(thread, argKeys); if (tagged->IsBigInt()) { JSHandle taggedValue(tagged); return BigInt::ToString(thread, taggedValue).GetTaggedValue().GetRawData(); } if (tagged->IsNativePointer()) { JSHandle taggedValue(tagged); return taggedValue->ToString(thread).GetTaggedValue().GetRawData(); } return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(IntToString) { RUNTIME_STUBS_HEADER(IntToString); JSTaggedValue argKeys = GetArg(argv, argc, 0); return JSHandle::Cast(base::NumberHelper::IntToEcmaString(thread, argKeys.GetInt())).GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(LocaleCompareWithGc) { RUNTIME_STUBS_HEADER(LocaleCompareWithGc); JSHandle locales = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle thisHandle = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle thatHandle = GetHArg(argv, argc, 2); // 2: means the second parameter JSHandle options = GetHArg(argv, argc, 3); // 3: means the third parameter bool cacheable = options->IsUndefined() && (locales->IsUndefined() || locales->IsString()); const CompareStringsOption csOption = JSCollator::CompareStringsOptionFor(thread, locales, options); return builtins::BuiltinsString::LocaleCompareGC(thread, thisHandle, thatHandle, locales, options, csOption, cacheable).GetRawData(); } DEF_RUNTIME_STUBS(ParseInt) { RUNTIME_STUBS_HEADER(ParseInt); JSHandle msg = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle arg2 = GetHArg(argv, argc, 1); // 1: means the first parameter int32_t radix = 0; // 1. Let inputString be ToString(string). JSHandle numberString = JSTaggedValue::ToString(thread, msg); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); if (!arg2->IsUndefined()) { // 7. Let R = ToInt32(radix). radix = JSTaggedValue::ToInt32(thread, arg2); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); } return base::NumberHelper::StringToNumber(thread, *numberString, radix).GetRawData(); } int RuntimeStubs::IntLexicographicCompare(JSTaggedType x, JSTaggedType y) { DISALLOW_GARBAGE_COLLECTION; return JSTaggedValue::IntLexicographicCompare(JSTaggedValue(x), JSTaggedValue(y)); } int RuntimeStubs::DoubleLexicographicCompare(JSTaggedType x, JSTaggedType y) { DISALLOW_GARBAGE_COLLECTION; return JSTaggedValue::DoubleLexicographicCompare(JSTaggedValue(x), JSTaggedValue(y)); } int RuntimeStubs::FastArraySortString(uintptr_t argGlue, JSTaggedValue x, JSTaggedValue y) { DISALLOW_GARBAGE_COLLECTION; auto thread = JSThread::GlueToJSThread(argGlue); JSHandle valueX(thread, x); JSHandle valueY(thread, y); return static_cast(EcmaStringAccessor::Compare(thread->GetEcmaVM(), valueX, valueY)); } DEF_RUNTIME_STUBS(LocaleCompareCacheable) { RUNTIME_STUBS_HEADER(LocaleCompareCacheable); JSHandle locales = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle thisHandle = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle thatHandle = GetHArg(argv, argc, 2); // 2: means the second parameter #if ENABLE_NEXT_OPTIMIZATION const CompareStringsOption csOption = JSCollator::CompareStringsOptionFor(thread, locales); JSTaggedValue result = JSCollator::FastCachedCompareStrings(thread, locales, thisHandle, thatHandle, csOption); #else auto collator = JSCollator::GetCachedIcuCollator(thread, locales); JSTaggedValue result = JSTaggedValue::Undefined(); if (collator != nullptr) { [[maybe_unused]]const CompareStringsOption csOption = JSCollator::CompareStringsOptionFor( thread, locales); result = JSCollator::CompareStrings(thread, collator, thisHandle, thatHandle, csOption); } #endif return result.GetRawData(); } JSTaggedValue RuntimeStubs::StringToNumber(uintptr_t argGlue, JSTaggedType numberString, int32_t radix) { DISALLOW_GARBAGE_COLLECTION; auto input = EcmaString::Cast(JSTaggedValue(numberString)); return base::NumberHelper::StringToNumber(JSThread::GlueToJSThread(argGlue), input, radix); } void RuntimeStubs::ArrayTrim(uintptr_t argGlue, TaggedArray *array, int64_t newLength) { DISALLOW_GARBAGE_COLLECTION; uint32_t length = static_cast(newLength); auto thread = JSThread::GlueToJSThread(argGlue); array->Trim(thread, length); } bool RuntimeStubs::IsFastRegExp(uintptr_t argGlue, JSTaggedValue thisValue) { auto thread = JSThread::GlueToJSThread(argGlue); return builtins::BuiltinsRegExp::IsFastRegExp(thread, thisValue); } RememberedSet* RuntimeStubs::CreateLocalToShare(Region* region) { return region->CreateLocalToShareRememberedSet(); } RememberedSet* RuntimeStubs::CreateOldToNew(Region* region) { return region->CreateOldToNewRememberedSet(); } template static bool CompareFloat(T x, T y) { if (x < y) { return true; } if (x > y) { return false; } if constexpr (!std::is_integral::value) { double doubleX = x; double doubleY = y; if (x == 0 && x == y) { /* -0.0 is less than +0.0 */ return std::signbit(doubleX) && !std::signbit(doubleY); } if (!std::isnan(doubleX) && std::isnan(doubleY)) { /* number is less than NaN */ return true; } } return false; } void RuntimeStubs::SortTypedArray(uintptr_t argGlue, JSTypedArray *typedArray) { DISALLOW_GARBAGE_COLLECTION; JSHClass *hclass = typedArray->GetClass(); const JSType jsType = hclass->GetObjectType(); JSThread *thread = JSThread::GlueToJSThread(argGlue); JSTaggedValue buffer = typedArray->GetViewedArrayBufferOrByteArray(thread); const uint32_t len = typedArray->GetArrayLength(); if (len == 0) { return; } void *pointer = builtins::BuiltinsArrayBuffer::GetDataPointFromBuffer(thread, buffer); switch (jsType) { case JSType::JS_INT8_ARRAY: std::sort(static_cast(pointer), static_cast(pointer) + len); break; case JSType::JS_UINT8_ARRAY: case JSType::JS_UINT8_CLAMPED_ARRAY: std::sort(static_cast(pointer), static_cast(pointer) + len); break; case JSType::JS_INT16_ARRAY: std::sort(static_cast(pointer), static_cast(pointer) + len); break; case JSType::JS_UINT16_ARRAY: std::sort(static_cast(pointer), static_cast(pointer) + len); break; case JSType::JS_INT32_ARRAY: std::sort(static_cast(pointer), static_cast(pointer) + len); break; case JSType::JS_UINT32_ARRAY: std::sort(static_cast(pointer), static_cast(pointer) + len); break; case JSType::JS_FLOAT32_ARRAY: std::sort(static_cast(pointer), static_cast(pointer) + len, CompareFloat); break; case JSType::JS_FLOAT64_ARRAY: std::sort(static_cast(pointer), static_cast(pointer) + len, CompareFloat); break; default: UNREACHABLE(); } } void RuntimeStubs::ReverseTypedArray(uintptr_t argGlue, JSTypedArray *typedArray) { DISALLOW_GARBAGE_COLLECTION; JSHClass *hclass = typedArray->GetClass(); const JSType jsType = hclass->GetObjectType(); JSThread *thread = JSThread::GlueToJSThread(argGlue); JSTaggedValue buffer = typedArray->GetViewedArrayBufferOrByteArray(thread); const uint32_t len = typedArray->GetArrayLength(); void *pointer = builtins::BuiltinsArrayBuffer::GetDataPointFromBuffer(thread, buffer); switch (jsType) { case JSType::JS_INT8_ARRAY: std::reverse(static_cast(pointer), static_cast(pointer) + len); break; case JSType::JS_UINT8_ARRAY: case JSType::JS_UINT8_CLAMPED_ARRAY: std::reverse(static_cast(pointer), static_cast(pointer) + len); break; case JSType::JS_INT16_ARRAY: std::reverse(static_cast(pointer), static_cast(pointer) + len); break; case JSType::JS_UINT16_ARRAY: std::reverse(static_cast(pointer), static_cast(pointer) + len); break; case JSType::JS_INT32_ARRAY: std::reverse(static_cast(pointer), static_cast(pointer) + len); break; case JSType::JS_UINT32_ARRAY: std::reverse(static_cast(pointer), static_cast(pointer) + len); break; case JSType::JS_FLOAT32_ARRAY: std::reverse(static_cast(pointer), static_cast(pointer) + len); break; case JSType::JS_FLOAT64_ARRAY: std::reverse(static_cast(pointer), static_cast(pointer) + len); break; default: UNREACHABLE(); } } void RuntimeStubs::FinishObjSizeTracking(uintptr_t argGlue, JSHClass *cls) { JSThread *thread = JSThread::GlueToJSThread(argGlue); uint32_t finalInObjPropsNum = JSHClass::VisitTransitionAndFindMaxNumOfProps(thread, cls); if (finalInObjPropsNum < cls->GetInlinedProperties()) { // UpdateObjSize with finalInObjPropsNum JSHClass::VisitTransitionAndUpdateObjSize(thread, cls, finalInObjPropsNum); } } void RuntimeStubs::FillObject(JSTaggedType *dst, JSTaggedType value, uint32_t count) { DISALLOW_GARBAGE_COLLECTION; std::fill_n(dst, count, value); } bool RuntimeStubs::IsTargetBundleName(uintptr_t argGlue) { auto thread = JSThread::GlueToJSThread(argGlue); return thread->GetEcmaVM()->GetJSOptions().FindTraceBundleName( thread->GetEcmaVM()->GetBundleName()); } DEF_RUNTIME_STUBS(TraceLoadSlowPath) { #if ECMASCRIPT_ENABLE_TRACE_LOAD if (!IsTargetBundleName(argGlue)) { return JSTaggedValue::Undefined().GetRawData(); } ECMA_BYTRACE_START_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "[dfx]TraceLoadSlowPath"); #endif return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(TraceLoadGetter) { #if ECMASCRIPT_ENABLE_TRACE_LOAD if (!IsTargetBundleName(argGlue)) { return JSTaggedValue::Undefined().GetRawData(); } ECMA_BYTRACE_START_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "[DFX]TraceLoadGetter"); #endif return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(TraceLoadDetail) { #if ECMASCRIPT_ENABLE_TRACE_LOAD if (!IsTargetBundleName(argGlue)) { return JSTaggedValue::Undefined().GetRawData(); } JSHandle receiver = GetHArg(argv, argc, 0); JSHandle profile = GetHArg(argv, argc, 1); JSTaggedValue slotId = GetArg(argv, argc, 2); CString msg = "[DFX]Trace Load Detail: "; if (profile->IsUndefined()) { msg += "ProfileTypeInfo Undefine"; } else { auto prof = JSHandle::Cast(profile); auto slot = slotId.GetInt(); auto first = prof->GetIcSlot(thread, slot); auto second = prof->GetIcSlot(thread, slot + 1); if (first.IsHole()) { if (second.IsHole()) { msg += "other-mega, "; // 1: Call SetAsMegaDFX and set it to 1 (for placeholder purposes).. } else if (second == JSTaggedValue(ProfileTypeAccessor::MegaState::NOTFOUND_MEGA)) { msg += "not_found-mage, "; // 2: Call SetAsMegaDFX and set it to 2 (for placeholder purposes). } else if (second == JSTaggedValue(ProfileTypeAccessor::MegaState::DICT_MEGA)) { msg += "dictionary-mega, "; } else if (second.IsString()) { msg += "ic-mega, "; } else { msg += "unkown-mega, "; } } else if (first.IsUndefined()) { msg += "undedfine slot, "; } else if (first.IsWeak()) { if (second.IsPrototypeHandler()) { auto prototypeHandler = PrototypeHandler::Cast(second.GetTaggedObject()); JSTaggedValue handlerInfoVal = prototypeHandler->GetHandlerInfo(); if (!handlerInfoVal.IsInt()) { msg += "mono prototype, "; } else { auto handlerInfo = static_cast(handlerInfoVal.GetInt()); if (HandlerBase::IsNumber(handlerInfo)) { msg += "mono primitive type number prototype, "; } else if (HandlerBase::IsBoolean(handlerInfo)) { msg += "mono primitive type boolean prototype, "; } else { msg += "mono prototype, "; } } } else { msg += "mono, "; } } else { msg += "poly, "; } #if ECMASCRIPT_ENABLE_TRACE_LOAD_MORE auto thread = JSThread::GlueToJSThread(argGlue); DumpInfoForMoreLdInfo(thread, receiver, msg); #endif } if (!receiver->IsHeapObject()) { if (receiver->IsNumber()) { msg += "prim_number"; } else if (receiver->IsBoolean()) { msg += "prim_boolean"; } else if (receiver->IsSymbol()) { msg += "prim_symbol"; } else if (receiver->IsBigInt()) { msg += "prim_bigint"; } else if (receiver->IsString()) { msg += "prim_string"; } else { msg += "prim_obj"; } } else { msg += "heap_obj"; } ECMA_BYTRACE_START_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, msg.c_str()); #endif return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(TraceLoadEnd) { #if ECMASCRIPT_ENABLE_TRACE_LOAD if (!IsTargetBundleName(argGlue)) { return JSTaggedValue::Undefined().GetRawData(); } ECMA_BYTRACE_FINISH_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK); #endif return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(TraceLoadValueSlowPath) { #if ECMASCRIPT_ENABLE_TRACE_LOAD_VALUE if (!IsTargetBundleName(argGlue)) { return JSTaggedValue::Undefined().GetRawData(); } ECMA_BYTRACE_START_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "[dfx]TraceLoadValueSlowPath"); #endif return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(TraceLoadValueDetail) { #if ECMASCRIPT_ENABLE_TRACE_LOAD_VALUE if (!IsTargetBundleName(argGlue)) { return JSTaggedValue::Undefined().GetRawData(); } JSHandle receiver = GetHArg(argv, argc, 0); JSHandle profile = GetHArg(argv, argc, 1); JSTaggedValue slotId = GetArg(argv, argc, 2); JSTaggedValue key = GetArg(argv, argc, 3); CString msg = ""; DumpInfoForLdObjByValue(profile, slotId, key, msg); #if ECMASCRIPT_ENABLE_TRACE_LOAD_MORE msg += " | "; auto thread = JSThread::GlueToJSThread(argGlue); DumpInfoForMoreLdInfo(thread, receiver, msg); #endif ECMA_BYTRACE_START_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, msg.c_str()); #endif return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(TraceLoadValueEnd) { #if ECMASCRIPT_ENABLE_TRACE_LOAD_VALUE if (!IsTargetBundleName(argGlue)) { return JSTaggedValue::Undefined().GetRawData(); } ECMA_BYTRACE_FINISH_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK); #endif return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(TraceCallDetail) { #if ECMASCRIPT_ENABLE_TRACE_CALL if (!IsTargetBundleName(argGlue)) { return JSTaggedValue::Undefined().GetRawData(); } JSHandle profile = GetHArg(argv, argc, 0); JSTaggedValue slotId = GetArg(argv, argc, 1); std::string msg = "[DFX]Trace Call Detail: "; if (profile->IsUndefined()) { msg += "ProfileTypeInfo Undefine"; } else { auto prof = JSHandle::Cast(profile); auto slot = slotId.GetInt(); auto slotValue = prof->GetIcSlot(slot); if (slotValue.IsJSFunction()) { JSFunction *callee = JSFunction::Cast(slotValue); Method *calleeMethod = Method::Cast(callee->GetMethod()); auto methodName = calleeMethod->GetMethodName(); auto calleeMethodId = static_cast(calleeMethod->GetMethodId().GetOffset()); auto calleeAbcId = PGOProfiler::GetMethodAbcId(callee); msg += std::string("[js function] id: ") + std::to_string(calleeMethodId) + " abc id: " + std::to_string(calleeAbcId) + " method name: " + methodName; } else { msg += "[unkown]"; } } ECMA_BYTRACE_START_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, msg.c_str()); #endif return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(TraceCallEnd) { #if ECMASCRIPT_ENABLE_TRACE_CALL if (!IsTargetBundleName(argGlue)) { return JSTaggedValue::Undefined().GetRawData(); } ECMA_BYTRACE_FINISH_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK); #endif return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(TraceStoreFastPath) { #if ECMASCRIPT_ENABLE_TRACE_STORE if (!IsTargetBundleName(argGlue)) { return JSTaggedValue::Undefined().GetRawData(); } ECMA_BYTRACE_START_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "[DFX]TraceStoreFastPath"); #endif return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(TraceStoreSlowPath) { #if ECMASCRIPT_ENABLE_TRACE_STORE if (!IsTargetBundleName(argGlue)) { return JSTaggedValue::Undefined().GetRawData(); } ECMA_BYTRACE_START_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "[DFX]TraceStoreSlowPath"); #endif return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(TraceStoreEnd) { #if ECMASCRIPT_ENABLE_TRACE_STORE if (!IsTargetBundleName(argGlue)) { return JSTaggedValue::Undefined().GetRawData(); } ECMA_BYTRACE_FINISH_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK); #endif return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(TraceStoreDetail) { #if ECMASCRIPT_ENABLE_TRACE_STORE if (!IsTargetBundleName(argGlue)) { return JSTaggedValue::Undefined().GetRawData(); } JSHandle receiver = GetHArg(argv, argc, 0); // 0: means the first parameter JSHandle profile = GetHArg(argv, argc, 1); // 1: means the second parameter JSTaggedValue slotId = GetArg(argv, argc, 2); // 2: means the third parameter CString msg = "[DFX]Trace Store Detail: "; if (profile->IsUndefined()) { msg += "ProfileTypeInfo Undefine"; } else { auto prof = JSHandle::Cast(profile); auto slot = slotId.GetInt(); auto first = prof->GetIcSlot(slot); auto second = prof->GetIcSlot(slot + 1); if (first.IsHole()) { if (second.IsHole()) { msg += "mega, "; } } else if (first.IsUndefined()) { msg += "undedfine slot, "; } else if (first.IsWeak()) { if (second.IsPrototypeHandler()) { msg += "mono prototype, "; } else if (second.IsTransitionHandler()) { msg += "mono transition, "; } else if (second.IsTransWithProtoHandler()) { msg += "mono transition with proto, "; } else { msg += "mono, "; } } else { msg += "poly, "; } } if (!receiver->IsHeapObject()) { msg += "prim_obj"; } else { msg += "heap_obj"; } ECMA_BYTRACE_START_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, msg.c_str()); #endif return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(TraceNum) { #if ECMASCRIPT_ENABLE_LAZY_DEOPT_TRACE if (!IsTargetBundleName(argGlue)) { return JSTaggedValue::Undefined().GetRawData(); } uint32_t type = static_cast(GetTArg(argv, argc, 0)); static uint32_t traceNum[128] = {}; traceNum[type] ++; if (traceNum[type] % TRACE_NUMBER == 0) { std::string s = "Trace type " + std::to_string(type); ECMA_BYTRACE_START_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, s.c_str()); ECMA_BYTRACE_FINISH_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK); } #endif return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(TraceLazyDeoptNum) { #if ECMASCRIPT_ENABLE_LAZY_DEOPT_TRACE if (!IsTargetBundleName(argGlue)) { return JSTaggedValue::Undefined().GetRawData(); } static uint32_t traceLazyDeoptNum = 0; traceLazyDeoptNum ++; if (traceLazyDeoptNum % TRACE_NUMBER == 0) { std::string s = "Lazy Deoptimize Code."; ECMA_BYTRACE_START_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, s.c_str()); ECMA_BYTRACE_FINISH_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK); } #endif return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(TraceLazyDeoptFailNum) { #if ECMASCRIPT_ENABLE_LAZY_DEOPT_TRACE if (!IsTargetBundleName(argGlue)) { return JSTaggedValue::Undefined().GetRawData(); } static uint32_t traceLazyDeoptFailNum = 0; traceLazyDeoptFailNum ++; if (traceLazyDeoptFailNum % TRACE_NUMBER == 0) { std::string s = "Lazy Deoptimize Code Fail." ECMA_BYTRACE_START_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, s.c_str()); ECMA_BYTRACE_FINISH_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK); } #endif return JSTaggedValue::Undefined().GetRawData(); } // static void RuntimeStubs::TraceLazyDeoptCommitSuccess(uintptr_t argGlue, JSHandle func) { #if ECMASCRIPT_ENABLE_LAZY_DEOPT_TRACE if (!IsTargetBundleName(argGlue)) { return; } auto thread = JSThread::GlueToJSThread(argGlue); JSTaggedValue funcNameValue = JSFunction::NameGetter(thread, JSHandle::Cast(func)); std::string funcName = EcmaStringAccessor(funcNameValue).ToStdString(); funcName += " Lazy Deoptimize Commit Success."; ECMA_BYTRACE_START_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, funcName.c_str()); ECMA_BYTRACE_FINISH_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK); #endif } DEF_RUNTIME_STUBS(TraceDefineFunc) { #if ECMASCRIPT_ENABLE_TRACE_DEFINEFUNC RUNTIME_STUBS_HEADER(TraceDefineFunc); if (!IsTargetBundleName(argGlue)) { return JSTaggedValue::Undefined().GetRawData(); } int methodId = GetArg(argv, argc, 0).GetInt(); JSHandle profileTypeInfo = GetHArg(argv, argc, 1); int slotId = GetArg(argv, argc, 2).GetInt(); CStringStream msg; msg << "[DFX]Trace Define Func: "; msg << "method id " << methodId << " "; if (profileTypeInfo->IsUndefined()) { msg << "profileTypeInfo undefined"; } else { ProfileTypeInfo *profile = ProfileTypeInfo::Cast(profileTypeInfo->GetTaggedObject()); JSTaggedValue slotValue = profile->Get(slotId); if (slotValue.IsUndefined()) { msg << "slot value undefined"; } if (slotValue.IsHole()) { msg << "slot value hole"; } if (slotValue.IsProfileTypeInfoCell()) { JSTaggedValue code = ProfileTypeInfoCell::Cast(slotValue)->GetMachineCode(); msg << "slot has machine code: " << code.IsHeapObject() && code.IsWeak(); } } ECMA_BYTRACE_START_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, msg.str().c_str()); #endif return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(TraceDefineFuncEnd) { #if ECMASCRIPT_ENABLE_TRACE_DEFINEFUNC ECMA_BYTRACE_FINISH_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK); #endif return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(ArrayForEachContinue) { RUNTIME_STUBS_HEADER(ArrayForEachContinue); JSHandle thisArgHandle = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSMutableHandle key(thread, GetHArg(argv, argc, 1)); // 1: means the first parameter JSHandle thisObjVal = GetHArg(argv, argc, 2); // 2: means the second parameter JSHandle callbackFnHandle = GetHArg(argv, argc, 3); // 3: means the third parameter JSHandle lengthHandle = GetHArg(argv, argc, 4); // 4: means the fourth parameter const uint32_t argsLength = 3; // 3: «kValue, k, O» uint32_t i = static_cast(key->GetInt()); uint32_t len = static_cast(lengthHandle->GetInt()); JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); while (i < len) { bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, i); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); if (exists) { JSHandle kValue = JSArray::FastGetPropertyByValue(thread, thisObjVal, i); key.Update(JSTaggedValue(i)); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue()); JSTaggedValue funcResult = JSFunction::Call(info); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult.GetRawData()); } i++; } return JSTaggedValue::Undefined().GetRawData(); } DEF_RUNTIME_STUBS(AOTEnableProtoChangeMarker) { RUNTIME_STUBS_HEADER(AOTEnableProtoChangeMarker); JSHandle result(GetHArg(argv, argc, 0)); // 0: means the zeroth parameter JSHandle ihc = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle aotLiteralInfo(GetHArg(argv, argc, 2)); // 2: means the second parameter DefineFuncTryUseAOTHClass(thread, result, ihc, aotLiteralInfo); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(GetSharedModule) { RUNTIME_STUBS_HEADER(GetSharedModule); JSHandle module = GetHArg(argv, argc, 0); // 0: means the zeroth parameter ModuleManager *moduleManager = thread->GetModuleManager(); return moduleManager->GenerateSendableFuncModule(module).GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(SetPrototypeTransition) { RUNTIME_STUBS_HEADER(SetPrototypeTransition); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle proto = GetHArg(argv, argc, 1); // 1: means the third parameter ElementsKind oldKind = obj->GetJSHClass()->GetElementsKind(); JSHClass::SetPrototypeTransition(thread, obj, proto); JSObject::TryMigrateToGenericKindForJSObject(thread, obj, oldKind); return JSTaggedValue::Hole().GetRawData(); } DEF_RUNTIME_STUBS(JSProxyGetProperty) { RUNTIME_STUBS_HEADER(JSProxyGetProperty); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle keyHandle = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle receiver = GetHArg(argv, argc, 2); // 2: means the second parameter return JSProxy::GetProperty(thread, JSHandle(obj), keyHandle, receiver).GetValue()->GetRawData(); } DEF_RUNTIME_STUBS(JSProxySetProperty) { RUNTIME_STUBS_HEADER(JSProxySetProperty); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle keyHandle = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle valueHandle = GetHArg(argv, argc, 2); // 2: means the second parameter JSHandle receiver = GetHArg(argv, argc, 3); // 3: means the third parameter bool mayThrow = GetArg(argv, argc, 4).ToBoolean(); // 4: means mayThrow exception during JSProxy::SetProperty auto result = JSProxy::SetProperty(thread, JSHandle(obj), keyHandle, valueHandle, receiver, mayThrow); return JSTaggedValue(result).GetRawData(); } DEF_RUNTIME_STUBS(CheckGetTrapResult) { RUNTIME_STUBS_HEADER(CheckGetTrapResult); JSHandle targetHandle = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle keyHandle = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle resutlHandle = GetHArg(argv, argc, 2); // 2: means the second parameter return JSProxy::CheckGetTrapResult(thread, targetHandle, keyHandle, resutlHandle).GetValue()->GetRawData(); } DEF_RUNTIME_STUBS(CheckSetTrapResult) { RUNTIME_STUBS_HEADER(CheckSetTrapResult); JSHandle targetHandle = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle keyHandle = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle valueHandle = GetHArg(argv, argc, 2); // 2: means the second parameter return JSTaggedValue(JSProxy::CheckSetTrapResult(thread, targetHandle, keyHandle, valueHandle)).GetRawData(); } DEF_RUNTIME_STUBS(JSProxyHasProperty) { RUNTIME_STUBS_HEADER(JSProxyHasProperty); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle keyHandle = GetHArg(argv, argc, 1); // 1: means the first parameter bool res = false; res = JSProxy::HasProperty(thread, JSHandle(obj), keyHandle); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); return JSTaggedValue(res).GetRawData(); } DEF_RUNTIME_STUBS(JSTypedArrayHasProperty) { RUNTIME_STUBS_HEADER(JSTypedArrayHasProperty); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle keyHandle = GetHArg(argv, argc, 1); // 1: means the first parameter bool res = false; res = JSTypedArray::HasProperty(thread, obj, keyHandle); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); return JSTaggedValue(res).GetRawData(); } DEF_RUNTIME_STUBS(ModuleNamespaceHasProperty) { RUNTIME_STUBS_HEADER(ModuleNamespaceHasProperty); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle keyHandle = GetHArg(argv, argc, 1); // 1: means the first parameter bool res = false; res = ModuleNamespace::HasProperty(thread, obj, keyHandle); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); return JSTaggedValue(res).GetRawData(); } DEF_RUNTIME_STUBS(JSObjectHasProperty) { RUNTIME_STUBS_HEADER(JSObjectHasProperty); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle keyHandle = GetHArg(argv, argc, 1); // 1: means the first parameter bool res = false; if (keyHandle->IsInt()) { uint32_t keyToIndex = static_cast(keyHandle->GetInt()); res = JSObject::HasProperty(thread, JSHandle(obj), keyToIndex); } else { res = JSObject::HasProperty(thread, JSHandle(obj), keyHandle); } RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); return JSTaggedValue(res).GetRawData(); } DEF_RUNTIME_STUBS(HasProperty) { RUNTIME_STUBS_HEADER(HasProperty); JSHandle obj = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSTaggedValue key = GetArg(argv, argc, 1); // 1: means the first parameter bool res = false; if (key.IsInt()) { uint32_t keyToIndex = static_cast(key.GetInt()); res = JSTaggedValue::HasProperty(thread, obj, keyToIndex); } else { JSHandle keyHandle(thread, key); res = JSTaggedValue::HasProperty(thread, obj, keyHandle); } RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData()); return JSTaggedValue(res).GetRawData(); } DEF_RUNTIME_STUBS(ObjectPrototypeHasOwnProperty) { RUNTIME_STUBS_HEADER(ObjectPrototypeHasOwnProperty); JSHandle thisValue = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle key = GetHArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue result = builtins::BuiltinsObject::HasOwnPropertyInternal(thread, thisValue, key); return result.GetRawData(); } DEF_RUNTIME_STUBS(ReflectHas) { RUNTIME_STUBS_HEADER(ReflectHas); JSHandle target = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle key = GetHArg(argv, argc, 1); // 1: means the first parameter JSTaggedValue result = builtins::BuiltinsReflect::ReflectHasInternal(thread, target, key); return result.GetRawData(); } DEF_RUNTIME_STUBS(ReflectConstruct) { // newTarget = target, args = [] RUNTIME_STUBS_HEADER(ReflectConstruct); JSHandle target = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle args = thread->GetEcmaVM()->GetFactory()->EmptyArray(); JSTaggedValue result = builtins::BuiltinsReflect::ReflectConstructInternal(thread, target, args, target); return result.GetRawData(); } DEF_RUNTIME_STUBS(ReflectApply) { RUNTIME_STUBS_HEADER(ReflectApply); JSHandle target = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle thisValue = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle argumentsList = GetHArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue result = builtins::BuiltinsReflect::ReflectApplyInternal(thread, target, thisValue, argumentsList); return result.GetRawData(); } DEF_RUNTIME_STUBS(FunctionPrototypeApply) { RUNTIME_STUBS_HEADER(FunctionPrototypeApply); JSHandle thisFunc = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle thisArg = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle argArray = GetHArg(argv, argc, 2); // 2: means the second parameter JSTaggedValue result = builtins::BuiltinsFunction::FunctionPrototypeApplyInternal(thread, thisFunc, thisArg, argArray); return result.GetRawData(); } DEF_RUNTIME_STUBS(FunctionPrototypeBind) { RUNTIME_STUBS_HEADER(FunctionPrototypeBind); JSHandle target = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle thisArg = GetHArg(argv, argc, 1); // 1: means the first parameter JSHandle argsArray = thread->GetEcmaVM()->GetFactory()->EmptyArray(); JSTaggedValue result = builtins::BuiltinsFunction::FunctionPrototypeBindInternal(thread, target, thisArg, argsArray); return result.GetRawData(); } DEF_RUNTIME_STUBS(FunctionPrototypeCall) { RUNTIME_STUBS_HEADER(FunctionPrototypeCall); JSHandle thisFunc = GetHArg(argv, argc, 0); // 0: means the zeroth parameter JSHandle thisArg = GetHArg(argv, argc, 1); // 1: means the first parameter if (!thisFunc->IsCallable()) { THROW_TYPE_ERROR_AND_RETURN(thread, "call target is not callable", JSTaggedValue::VALUE_EXCEPTION); } JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); uint32_t argsLength = argc - 2; // 2: thisFunc and thisArg EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, thisFunc, thisArg, undefined, argsLength); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::VALUE_EXCEPTION); uint32_t index = 0; for (uint32_t i = 2; i < argc; ++i) { // 2: thisFunc and thisArg JSTaggedValue arg = GetArg(argv, argc, i); info->SetCallArg(index++, arg); } return JSFunction::Call(info).GetRawData(); } DEF_RUNTIME_STUBS(GetCollationValueFromIcuCollator) { RUNTIME_STUBS_HEADER(GetCollationValueFromIcuCollator); JSHandle collator = GetHArg(argv, argc, 0); // 0: means the zeroth parameter UErrorCode status = U_ZERO_ERROR; icu::Collator *icuCollator = collator->GetIcuCollator(thread); icu::Locale icu_locale(icuCollator->getLocale(ULOC_VALID_LOCALE, status)); std::string collation_value = icu_locale.getUnicodeKeywordValue("co", status); if (collation_value != "search" && collation_value != "") { return thread->GetEcmaVM()->GetFactory()->NewFromStdString(collation_value).GetTaggedValue().GetRawData(); } return thread->GlobalConstants()->GetDefaultString().GetRawData(); } DEF_RUNTIME_STUBS(GetAllFlagsInternal) { RUNTIME_STUBS_HEADER(GetAllFlagsInternal); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle value = GetHArg(argv, argc, 0); // 0: means the zeroth parameter uint64_t bigFlagsStr = static_cast(value->GetInt()); std::string strFlags = ""; strFlags.reserve(RegExpParser::FLAG_NUM); if (bigFlagsStr & RegExpParser::FLAG_HASINDICES) { strFlags += "d"; } if (bigFlagsStr & RegExpParser::FLAG_GLOBAL) { strFlags += "g"; } if (bigFlagsStr & RegExpParser::FLAG_IGNORECASE) { strFlags += "i"; } if (bigFlagsStr & RegExpParser::FLAG_MULTILINE) { strFlags += "m"; } if (bigFlagsStr & RegExpParser::FLAG_DOTALL) { strFlags += "s"; } if (bigFlagsStr & RegExpParser::FLAG_UTF16) { strFlags += "u"; } if (bigFlagsStr & RegExpParser::FLAG_STICKY) { strFlags += "y"; } JSHandle flagsString = factory->NewFromUtf8(std::string_view(strFlags)); return flagsString.GetTaggedValue().GetRawData(); } DEF_RUNTIME_STUBS(SlowSharedObjectStoreBarrier) { RUNTIME_STUBS_HEADER(SlowSharedObjectStoreBarrier); JSHandle value = GetHArg(argv, argc, 0); // 0: means the zeroth parameter ASSERT(value->IsTreeString()); JSHandle publishValue = JSTaggedValue::PublishSharedValueSlow(thread, value); return publishValue.GetTaggedValue().GetRawData(); } void RuntimeStubs::CopyObjectPrimitive(uintptr_t argGlue, JSTaggedType *dstObj, JSTaggedType *dst, JSTaggedType *src, uint32_t count) { DISALLOW_GARBAGE_COLLECTION; auto thread = JSThread::GlueToJSThread(argGlue); // check CMC-GC phase inside if (thread->NeedReadBarrier()) { Barriers::CopyObjectPrimitive(thread, reinterpret_cast(dst), reinterpret_cast(src), count); } else { Barriers::CopyObjectPrimitive(thread, reinterpret_cast(dst), reinterpret_cast(src), count); } } void RuntimeStubs::ObjectCopy(uintptr_t argGlue, JSTaggedType *dstObj, JSTaggedType *dst, JSTaggedType *src, uint32_t count) { DISALLOW_GARBAGE_COLLECTION; if (g_isEnableCMCGC) { auto thread = JSThread::GlueToJSThread(argGlue); // check CMC-GC phase inside Barriers::CopyObject(thread, reinterpret_cast(dstObj), reinterpret_cast(dst), reinterpret_cast(src), count); } else { (void)argGlue; std::copy_n(src, count, dst); } } void RuntimeStubs::ReverseArray(uintptr_t argGlue, JSTaggedType *dst, uint32_t length) { DISALLOW_GARBAGE_COLLECTION; if (g_isEnableCMCGC) { auto thread = JSThread::GlueToJSThread(argGlue); if (thread->NeedReadBarrier()) { for (uint32_t i = 0; i < length; i++) { Barriers::UpdateSlot(thread, dst, i * sizeof(JSTaggedType)); } } } std::reverse(dst, dst + length); } JSTaggedValue RuntimeStubs::FindPatchModule(uintptr_t argGlue, JSTaggedValue resolvedModule) { DISALLOW_GARBAGE_COLLECTION; auto thread = JSThread::GlueToJSThread(argGlue); JSHandle module(thread, resolvedModule); return (thread->GetEcmaVM()->FindPatchModule(module->GetEcmaModuleRecordNameString())).GetTaggedValue(); } JSTaggedValue RuntimeStubs::UpdateSharedModule(uintptr_t argGlue, JSTaggedValue resolvedModule) { DISALLOW_GARBAGE_COLLECTION; auto thread = JSThread::GlueToJSThread(argGlue); JSHandle module(thread, resolvedModule); JSHandle sharedModule = SharedModuleManager::GetInstance()->GetSModule(thread, module->GetEcmaModuleRecordNameString()); if (sharedModule.GetTaggedValue().IsSourceTextModule()) { return sharedModule.GetTaggedValue(); } return module.GetTaggedValue(); } void RuntimeStubs::FatalPrintMisstakenResolvedBinding(int32_t index, JSTaggedValue curModule) { DISALLOW_GARBAGE_COLLECTION; JSThread *thread = JSThread::GetCurrent(); std::ostringstream oss; curModule.Dump(thread, oss); LOG_ECMA(FATAL) << "Get module value failed, mistaken ResolvedBinding" << ", index: " << index << ", currentModule: " << oss.str(); UNREACHABLE(); } void RuntimeStubs::LoadNativeModuleFailed(JSTaggedValue curModule) { DISALLOW_GARBAGE_COLLECTION; LOG_FULL(WARN) << "Load native module failed, so is " << SourceTextModule::GetModuleName(curModule); } JSTaggedValue RuntimeStubs::GetExternalModuleVar(uintptr_t argGlue, JSFunction *jsFunc, int32_t index) { auto thread = JSThread::GlueToJSThread(argGlue); return ModuleManager::GetExternalModuleVarFastPathForJIT(thread, index, jsFunc); } bool RuntimeStubs::MarkRSetCardTable(BaseObject* obj) { common::RegionDesc* region = common::RegionDesc::GetAliveRegionDescAt(reinterpret_cast(obj)); return region->MarkRSetCardTable(obj); } void RuntimeStubs::MarkInBuffer(BaseObject* ref) { ref = reinterpret_cast(reinterpret_cast(ref) & ~(common::Barrier::TAG_WEAK)); common::Mutator* mutator = common::Mutator::GetMutator(); mutator->RememberObjectInSatbBuffer(ref); } void RuntimeStubs::BatchMarkInBuffer(void* src, size_t count) { uintptr *srcPtr = reinterpret_cast(src); common::Mutator* mutator = common::Mutator::GetMutator(); for (size_t i = 0; i < count; i++) { BaseObject* ref = reinterpret_cast(srcPtr[i]); if (!common::Heap::IsTaggedObject(reinterpret_cast(ref))) { continue; } ref = reinterpret_cast(reinterpret_cast(ref) & ~(common::Barrier::TAG_WEAK)); mutator->RememberObjectInSatbBuffer(ref); } } DEF_RUNTIME_STUBS(ComputeHashcode) { RUNTIME_STUBS_HEADER(ComputeHashcode); JSTaggedValue ecmaString = GetArg(argv, argc, 0); // 0: means the zeroth parameter auto string = EcmaString::Cast(ecmaString); uint32_t result = EcmaStringAccessor(string).ComputeHashcode(thread); return JSTaggedValue(static_cast(result)).GetRawData(); } void RuntimeStubs::Initialize(JSThread *thread) { #define DEF_RUNTIME_STUB(name) kungfu::RuntimeStubCSigns::ID_##name #define INITIAL_RUNTIME_FUNCTIONS(name) \ thread->RegisterRTInterface(DEF_RUNTIME_STUB(name), reinterpret_cast(name)); RUNTIME_STUB_WITHOUT_GC_LIST(INITIAL_RUNTIME_FUNCTIONS) RUNTIME_STUB_WITH_GC_LIST(INITIAL_RUNTIME_FUNCTIONS) RUNTIME_STUB_WITH_DFX(INITIAL_RUNTIME_FUNCTIONS) TEST_RUNTIME_STUB_GC_LIST(INITIAL_RUNTIME_FUNCTIONS) #undef INITIAL_RUNTIME_FUNCTIONS #undef DEF_RUNTIME_STUB } #if defined(__clang__) #pragma clang diagnostic pop #elif defined(__GNUC__) #pragma GCC diagnostic pop #endif } // namespace panda::ecmascript