mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
Add atomics project and modify code errors
Signed-off-by: jiangkai43 <jiangkai43@huawei.com> https://gitee.com/openharmony/ark_js_runtime/issues/I599WU
This commit is contained in:
parent
0c5dd8f92a
commit
b13fb03d17
3
BUILD.gn
3
BUILD.gn
@ -301,6 +301,7 @@ config("icu_path_test_config") {
|
||||
|
||||
ecma_source = [
|
||||
"ecmascript/base/array_helper.cpp",
|
||||
"ecmascript/base/atomic_helper.cpp",
|
||||
"ecmascript/base/builtins_base.cpp",
|
||||
"ecmascript/base/error_helper.cpp",
|
||||
"ecmascript/base/json_parser.cpp",
|
||||
@ -314,6 +315,7 @@ ecma_source = [
|
||||
"ecmascript/builtins/builtins_array.cpp",
|
||||
"ecmascript/builtins/builtins_arraybuffer.cpp",
|
||||
"ecmascript/builtins/builtins_async_function.cpp",
|
||||
"ecmascript/builtins/builtins_atomics.cpp",
|
||||
"ecmascript/builtins/builtins_bigint.cpp",
|
||||
"ecmascript/builtins/builtins_boolean.cpp",
|
||||
"ecmascript/builtins/builtins_dataview.cpp",
|
||||
@ -476,6 +478,7 @@ ecma_source = [
|
||||
"ecmascript/tagged_dictionary.cpp",
|
||||
"ecmascript/tagged_tree.cpp",
|
||||
"ecmascript/template_string.cpp",
|
||||
"ecmascript/waiter_list.cpp",
|
||||
"ecmascript/weak_vector.cpp",
|
||||
"ecmascript/compiler/llvm/llvm_stackmap_parser.cpp",
|
||||
"ecmascript/stubs/runtime_stubs.cpp",
|
||||
|
140
ecmascript/base/atomic_helper.cpp
Normal file
140
ecmascript/base/atomic_helper.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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/atomic_helper.h"
|
||||
#include "ecmascript/base/typed_array_helper-inl.h"
|
||||
|
||||
namespace panda::ecmascript::base {
|
||||
using BuiltinsArrayBuffer = builtins::BuiltinsArrayBuffer;
|
||||
|
||||
JSTaggedValue AtomicHelper::ValidateIntegerTypedArray(JSThread *thread, JSHandle<JSTaggedValue> typedArray,
|
||||
bool waitable)
|
||||
{
|
||||
// 1. If waitable is not present, set waitable to false.
|
||||
// 2. Let buffer be ? ValidateTypedArray(typedArray).
|
||||
JSTaggedValue buffer = TypedArrayHelper::ValidateTypedArray(thread, typedArray);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
JSHandle<JSTaggedValue> bufferHandle(thread, buffer);
|
||||
|
||||
// 3. Let typeName be typedArray.[[TypedArrayName]].
|
||||
// 4. Let type be the Element Type value in Table 60 for typeName.
|
||||
JSHandle<JSTaggedValue> typeName(thread, JSTypedArray::Cast(typedArray->GetTaggedObject())->GetTypedArrayName());
|
||||
DataViewType type = JSTypedArray::GetTypeFromName(thread, typeName);
|
||||
|
||||
// 5. If waitable is true, then
|
||||
// a. If typeName is not "Int32Array" or "BigInt64Array", throw a TypeError exception.
|
||||
// 6. Else,
|
||||
// a. If ! IsUnclampedIntegerElementType(type) is false and ! IsBigIntElementType(type) is false,
|
||||
// throw a TypeError exception.
|
||||
if (waitable) {
|
||||
if (!(type == DataViewType::INT32 || type == DataViewType::BIGINT64)) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "The typeName is not Int32Array/BigInt64Array.",
|
||||
JSTaggedValue::Exception());
|
||||
}
|
||||
} else {
|
||||
if (!(BuiltinsArrayBuffer::IsUnclampedIntegerElementType(type) ||
|
||||
BuiltinsArrayBuffer::IsBigIntElementType(type))) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "The typedArray type is not UnclampedInteger/BigInt.",
|
||||
JSTaggedValue::Exception());
|
||||
}
|
||||
}
|
||||
// 7. Return buffer.
|
||||
return bufferHandle.GetTaggedValue();
|
||||
}
|
||||
|
||||
int32_t AtomicHelper::ValidateAtomicAccess(JSThread *thread, const JSHandle<JSTaggedValue> typedArray,
|
||||
JSHandle<JSTaggedValue> requestIndex)
|
||||
{
|
||||
// 1. Assert: typedArray is an Object that has a [[ViewedArrayBuffer]] internal slot.
|
||||
ASSERT(typedArray->IsECMAObject() && typedArray->IsTypedArray());
|
||||
// 2. Let length be typedArray.[[ArrayLength]].
|
||||
JSHandle<JSObject> typedArrayObj(typedArray);
|
||||
JSHandle<JSTypedArray> srcObj(typedArray);
|
||||
int32_t length = static_cast<int32_t>(srcObj->GetArrayLength());
|
||||
|
||||
// 3. Let accessIndex be ? ToIndex(requestIndex).
|
||||
JSTaggedNumber accessIndex = JSTaggedValue::ToIndex(thread, requestIndex);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, 0);
|
||||
int32_t index = base::NumberHelper::DoubleInRangeInt32(accessIndex.GetNumber());
|
||||
|
||||
// 4. Assert: accessIndex ≥ 0.
|
||||
ASSERT(index >= 0);
|
||||
|
||||
// 5. If accessIndex ≥ length, throw a RangeError exception.
|
||||
if (index >= length) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "Index is overflow.", 0);
|
||||
}
|
||||
|
||||
// 6. Let arrayTypeName be typedArray.[[TypedArrayName]].
|
||||
// 7. Let elementSize be the Element Size value specified in Table 60 for arrayTypeName.
|
||||
// 8. Let offset be typedArray.[[ByteOffset]].
|
||||
JSHandle<JSTaggedValue> arrayTypeName(thread, JSTypedArray::Cast(*typedArrayObj)->GetTypedArrayName());
|
||||
int32_t elementSize = TypedArrayHelper::GetSizeFromName(thread, arrayTypeName);
|
||||
uint32_t offset = srcObj->GetByteOffset();
|
||||
// 9. Return (accessIndex × elementSize) + offset.
|
||||
int32_t allOffset = index * elementSize + offset;
|
||||
return allOffset;
|
||||
}
|
||||
|
||||
JSTaggedValue AtomicHelper::AtomicStore(JSThread *thread, const JSHandle<JSTaggedValue> &typedArray,
|
||||
JSHandle<JSTaggedValue> index, JSHandle<JSTaggedValue> &value)
|
||||
{
|
||||
JSTaggedValue bufferValue = ValidateIntegerTypedArray(thread, typedArray);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
JSHandle<JSTaggedValue> buffer(thread, bufferValue);
|
||||
uint32_t indexedPosition = ValidateAtomicAccess(thread, typedArray, index);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
JSHandle<JSTaggedValue> arrayTypeName(thread,
|
||||
JSTypedArray::Cast(typedArray->GetTaggedObject())->GetTypedArrayName());
|
||||
DataViewType type = JSTypedArray::GetTypeFromName(thread, arrayTypeName);
|
||||
JSHandle<JSTaggedValue> bufferTag;
|
||||
if (type == DataViewType::BIGUINT64 || type == DataViewType::BIGINT64) {
|
||||
JSTaggedValue integerValue = JSTaggedValue::ToBigInt(thread, value);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
bufferTag = JSHandle<JSTaggedValue>(thread, integerValue);
|
||||
} else {
|
||||
JSTaggedNumber integerValue = JSTaggedValue::ToInteger(thread, value);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
bufferTag = JSHandle<JSTaggedValue>(thread, integerValue);
|
||||
}
|
||||
if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer.GetTaggedValue())) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "The ArrayBuffer of this value is detached buffer.",
|
||||
JSTaggedValue::Exception());
|
||||
}
|
||||
BuiltinsArrayBuffer::SetValueInBuffer(thread, buffer.GetTaggedValue(), indexedPosition, type, bufferTag, true);
|
||||
return bufferTag.GetTaggedValue();
|
||||
}
|
||||
|
||||
JSTaggedValue AtomicHelper::AtomicLoad(JSThread *thread, const JSHandle<JSTaggedValue> &typedArray,
|
||||
JSHandle<JSTaggedValue> index)
|
||||
{
|
||||
JSTaggedValue bufferValue = ValidateIntegerTypedArray(thread, typedArray);
|
||||
JSHandle<JSTaggedValue> buffer(thread, bufferValue);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
int32_t indexedPosition = ValidateAtomicAccess(thread, typedArray, index);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer.GetTaggedValue())) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "The ArrayBuffer of this value is detached buffer.",
|
||||
JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSTaggedValue> arrayTypeName(thread,
|
||||
JSTypedArray::Cast(typedArray->GetTaggedObject())->GetTypedArrayName());
|
||||
DataViewType elementType = JSTypedArray::GetTypeFromName(thread, arrayTypeName);
|
||||
return BuiltinsArrayBuffer::GetValueFromBuffer(thread, buffer.GetTaggedValue(),
|
||||
indexedPosition, elementType, true);
|
||||
}
|
||||
} // panda::ecmascript::base
|
||||
|
104
ecmascript/base/atomic_helper.h
Normal file
104
ecmascript/base/atomic_helper.h
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_BASE_ATOMIC_HELPER_H
|
||||
#define ECMASCRIPT_BASE_ATOMIC_HELPER_H
|
||||
|
||||
#include "ecmascript/js_dataview.h"
|
||||
|
||||
namespace panda::ecmascript::base {
|
||||
enum class BytesSize : int32_t {ONEBYTES = 1, TWOBYTES = 2, FOURBYTES = 4, EIGHTBYTES = 8};
|
||||
|
||||
class AtomicHelper final {
|
||||
public:
|
||||
struct SubFun {
|
||||
template<typename T>
|
||||
T operator()(T *ptr, const T *arg) const
|
||||
{
|
||||
std::atomic<T> *atomicValue = reinterpret_cast<std::atomic<T> *>(ptr);
|
||||
return atomicValue->fetch_sub(arg[0], std::memory_order_seq_cst);
|
||||
}
|
||||
};
|
||||
|
||||
struct AddFun {
|
||||
template<typename T>
|
||||
T operator()(T *ptr, const T *arg) const
|
||||
{
|
||||
std::atomic<T> *atomicValue = reinterpret_cast<std::atomic<T> *>(ptr);
|
||||
return atomicValue->fetch_add(arg[0], std::memory_order_seq_cst);
|
||||
}
|
||||
};
|
||||
|
||||
struct AndFun {
|
||||
template<typename T>
|
||||
T operator()(T *ptr, const T *arg) const
|
||||
{
|
||||
std::atomic<T> *atomicValue = reinterpret_cast<std::atomic<T> *>(ptr);
|
||||
return atomicValue->fetch_and(arg[0], std::memory_order_seq_cst);
|
||||
}
|
||||
};
|
||||
|
||||
struct OrFun {
|
||||
template<typename T>
|
||||
T operator()(T *ptr, const T *arg) const
|
||||
{
|
||||
std::atomic<T> *atomicValue = reinterpret_cast<std::atomic<T> *>(ptr);
|
||||
return atomicValue->fetch_or(arg[0], std::memory_order_seq_cst);
|
||||
}
|
||||
};
|
||||
|
||||
struct XorFun {
|
||||
template<typename T>
|
||||
T operator()(T *ptr, const T *arg) const
|
||||
{
|
||||
std::atomic<T> *atomicValue = reinterpret_cast<std::atomic<T> *>(ptr);
|
||||
return atomicValue->fetch_xor(arg[0], std::memory_order_seq_cst);
|
||||
}
|
||||
};
|
||||
|
||||
struct CompareExchangeFun {
|
||||
template<typename T>
|
||||
T operator()(T *ptr, const T *arg) const
|
||||
{
|
||||
T a = arg[0];
|
||||
std::atomic<T> *atomicValue = reinterpret_cast<std::atomic<T> *>(ptr);
|
||||
atomicValue->compare_exchange_strong(a, arg[1], std::memory_order_seq_cst);
|
||||
return a;
|
||||
}
|
||||
};
|
||||
|
||||
struct ExchangeFun {
|
||||
template<typename T>
|
||||
T operator()(T *ptr, const T *arg) const
|
||||
{
|
||||
std::atomic<T> *atomicValue = reinterpret_cast<std::atomic<T> *>(ptr);
|
||||
return atomicValue->exchange(arg[0], std::memory_order_seq_cst);
|
||||
}
|
||||
};
|
||||
|
||||
// 25.4.1.1 ValidateIntegerTypedArray ( typedArray [ , waitable ] )
|
||||
static JSTaggedValue ValidateIntegerTypedArray(JSThread *thread, JSHandle<JSTaggedValue> typedArray,
|
||||
bool waitable = false);
|
||||
// 25.4.2.2 ValidateAtomicAccess ( typedArray, requestIndex )
|
||||
static int32_t ValidateAtomicAccess(JSThread *thread, const JSHandle<JSTaggedValue> typedArray,
|
||||
JSHandle<JSTaggedValue> requestIndex);
|
||||
static JSTaggedValue AtomicStore(JSThread *thread, const JSHandle<JSTaggedValue> &typedArray,
|
||||
JSHandle<JSTaggedValue> index, JSHandle<JSTaggedValue> &value);
|
||||
static JSTaggedValue AtomicLoad(JSThread *thread, const JSHandle<JSTaggedValue> &typedArray,
|
||||
JSHandle<JSTaggedValue> index);
|
||||
};
|
||||
} // namespace panda::ecmascript::base
|
||||
|
||||
#endif // ECMASCRIPT_BASE_ATOMIC_HELPER_H
|
@ -92,42 +92,6 @@ uint32_t TypedArrayHelper::GetElementSize(JSType type)
|
||||
}
|
||||
}
|
||||
|
||||
DataViewType TypedArrayHelper::GetTypeFromName(JSThread *thread, const JSHandle<JSTaggedValue> &typeName)
|
||||
{
|
||||
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledInt8ArrayString())) {
|
||||
return DataViewType::INT8;
|
||||
}
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledUint8ArrayString())) {
|
||||
return DataViewType::UINT8;
|
||||
}
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledUint8ClampedArrayString())) {
|
||||
return DataViewType::UINT8_CLAMPED;
|
||||
}
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledInt16ArrayString())) {
|
||||
return DataViewType::INT16;
|
||||
}
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledUint16ArrayString())) {
|
||||
return DataViewType::UINT16;
|
||||
}
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledInt32ArrayString())) {
|
||||
return DataViewType::INT32;
|
||||
}
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledUint32ArrayString())) {
|
||||
return DataViewType::UINT32;
|
||||
}
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledFloat32ArrayString())) {
|
||||
return DataViewType::FLOAT32;
|
||||
}
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledFloat64ArrayString())) {
|
||||
return DataViewType::FLOAT64;
|
||||
}
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledBigInt64ArrayString())) {
|
||||
return DataViewType::BIGINT64;
|
||||
}
|
||||
return DataViewType::BIGUINT64;
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> TypedArrayHelper::GetConstructor(JSThread *thread, const JSHandle<JSTaggedValue> &obj)
|
||||
{
|
||||
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
|
@ -186,14 +186,14 @@ JSTaggedValue TypedArrayHelper::CreateFromTypedArray(EcmaRuntimeCallInfo *argv,
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "The srcData is detached buffer.", JSTaggedValue::Exception());
|
||||
}
|
||||
// 8. Let elementType be the Element Type value in Table 61 for constructorName.
|
||||
DataViewType elementType = TypedArrayHelper::GetTypeFromName(thread, constructorName);
|
||||
DataViewType elementType = JSTypedArray::GetTypeFromName(thread, constructorName);
|
||||
// 9. Let elementLength be srcArray.[[ArrayLength]].
|
||||
// 10. Let srcName be the String value of srcArray.[[TypedArrayName]].
|
||||
// 11. Let srcType be the Element Type value in Table 61 for srcName.
|
||||
// 12. Let srcElementSize be the Element Size value specified in Table 61 for srcName.
|
||||
uint32_t elementLength = srcObj->GetArrayLength();
|
||||
JSHandle<JSTaggedValue> srcName(thread, srcObj->GetTypedArrayName());
|
||||
DataViewType srcType = TypedArrayHelper::GetTypeFromName(thread, srcName);
|
||||
DataViewType srcType = JSTypedArray::GetTypeFromName(thread, srcName);
|
||||
uint32_t srcElementSize = TypedArrayHelper::GetSizeFromName(thread, srcName);
|
||||
// 13. Let srcByteOffset be srcArray.[[ByteOffset]].
|
||||
// 14. Let elementSize be the Element Size value specified in Table 61 for constructorName.
|
||||
|
@ -43,7 +43,6 @@ public:
|
||||
inline static DataViewType GetType(JSType type);
|
||||
inline static uint32_t GetElementSize(const JSHandle<JSTypedArray> &obj);
|
||||
inline static uint32_t GetElementSize(JSType type);
|
||||
inline static DataViewType GetTypeFromName(JSThread *thread, const JSHandle<JSTaggedValue> &typeName);
|
||||
inline static JSHandle<JSTaggedValue> GetConstructor(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
|
||||
inline static JSHandle<JSFunction> GetConstructorFromName(JSThread *thread,
|
||||
const JSHandle<JSTaggedValue> &typeName);
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "ecmascript/builtins/builtins_array.h"
|
||||
#include "ecmascript/builtins/builtins_arraybuffer.h"
|
||||
#include "ecmascript/builtins/builtins_async_function.h"
|
||||
#include "ecmascript/builtins/builtins_atomics.h"
|
||||
#include "ecmascript/builtins/builtins_bigint.h"
|
||||
#include "ecmascript/builtins/builtins_boolean.h"
|
||||
#include "ecmascript/builtins/builtins_collator.h"
|
||||
@ -134,6 +135,7 @@ using StringIterator = builtins::BuiltinsStringIterator;
|
||||
using RegExp = builtins::BuiltinsRegExp;
|
||||
using Function = builtins::BuiltinsFunction;
|
||||
using Math = builtins::BuiltinsMath;
|
||||
using Atomics = builtins::BuiltinsAtomics;
|
||||
using ArrayBuffer = builtins::BuiltinsArrayBuffer;
|
||||
using Json = builtins::BuiltinsJson;
|
||||
using Proxy = builtins::BuiltinsProxy;
|
||||
@ -314,6 +316,7 @@ void Builtins::Initialize(const JSHandle<GlobalEnv> &env, JSThread *thread)
|
||||
|
||||
InitializeGlobalObject(env, globalObject);
|
||||
InitializeMath(env, objFuncPrototypeVal);
|
||||
InitializeAtomics(env, objFuncPrototypeVal);
|
||||
InitializeJson(env, objFuncPrototypeVal);
|
||||
InitializeIterator(env, objFuncDynclass);
|
||||
InitializeProxy(env);
|
||||
@ -1357,6 +1360,34 @@ void Builtins::InitializeWeakSet(const JSHandle<GlobalEnv> &env, const JSHandle<
|
||||
env->SetBuiltinsWeakSetFunction(thread_, weakSetFunction);
|
||||
}
|
||||
|
||||
void Builtins::InitializeAtomics(const JSHandle<GlobalEnv> &env,
|
||||
const JSHandle<JSTaggedValue> &objFuncPrototypeVal) const
|
||||
{
|
||||
[[maybe_unused]] EcmaHandleScope scope(thread_);
|
||||
JSHandle<JSHClass> atomicsDynclass = factory_->NewEcmaDynClass(JSObject::SIZE, JSType::JS_OBJECT,
|
||||
objFuncPrototypeVal);
|
||||
JSHandle<JSObject> atomicsObject = factory_->NewJSObject(atomicsDynclass);
|
||||
SetFunction(env, atomicsObject, "add", Atomics::Add, FunctionLength::THREE);
|
||||
SetFunction(env, atomicsObject, "and", Atomics::And, FunctionLength::THREE);
|
||||
SetFunction(env, atomicsObject, "sub", Atomics::Sub, FunctionLength::THREE);
|
||||
SetFunction(env, atomicsObject, "or", Atomics::Or, FunctionLength::THREE);
|
||||
SetFunction(env, atomicsObject, "xor", Atomics::Xor, FunctionLength::THREE);
|
||||
SetFunction(env, atomicsObject, "compareExchange", Atomics::CompareExchange, FunctionLength::FOUR);
|
||||
SetFunction(env, atomicsObject, "exchange", Atomics::Exchange, FunctionLength::THREE);
|
||||
SetFunction(env, atomicsObject, "isLockFree", Atomics::IsLockFree, FunctionLength::ONE);
|
||||
SetFunction(env, atomicsObject, "load", Atomics::Load, FunctionLength::TWO);
|
||||
SetFunction(env, atomicsObject, "store", Atomics::Store, FunctionLength::THREE);
|
||||
SetFunction(env, atomicsObject, "wait", Atomics::Wait, FunctionLength::FOUR);
|
||||
SetFunction(env, atomicsObject, "notify", Atomics::Notify, FunctionLength::THREE);
|
||||
JSHandle<JSTaggedValue> atomicsString(factory_->NewFromASCII("Atomics"));
|
||||
JSHandle<JSObject> globalObject(thread_, env->GetGlobalObject());
|
||||
PropertyDescriptor atomicsDesc(thread_, JSHandle<JSTaggedValue>::Cast(atomicsObject), true, false, true);
|
||||
JSObject::DefineOwnProperty(thread_, globalObject, atomicsString, atomicsDesc);
|
||||
// @@ToStringTag
|
||||
SetStringTagSymbol(env, atomicsObject, "Atomics");
|
||||
env->SetAtomicsFunction(thread_, atomicsObject);
|
||||
}
|
||||
|
||||
void Builtins::InitializeMath(const JSHandle<GlobalEnv> &env, const JSHandle<JSTaggedValue> &objFuncPrototypeVal) const
|
||||
{
|
||||
[[maybe_unused]] EcmaHandleScope scope(thread_);
|
||||
|
@ -141,6 +141,8 @@ private:
|
||||
|
||||
void InitializeMath(const JSHandle<GlobalEnv> &env, const JSHandle<JSTaggedValue> &objFuncPrototypeVal) const;
|
||||
|
||||
void InitializeAtomics(const JSHandle<GlobalEnv> &env, const JSHandle<JSTaggedValue> &objFuncPrototypeVal) const;
|
||||
|
||||
void InitializeJson(const JSHandle<GlobalEnv> &env, const JSHandle<JSTaggedValue> &objFuncPrototypeVal) const;
|
||||
|
||||
void InitializeString(const JSHandle<GlobalEnv> &env, const JSHandle<JSHClass> &primRefObjDynclass) const;
|
||||
|
@ -386,6 +386,22 @@ bool BuiltinsArrayBuffer::IsBigIntElementType(DataViewType type)
|
||||
return false;
|
||||
}
|
||||
|
||||
// es12 25.1.2.6 IsUnclampedIntegerElementType ( type )
|
||||
bool BuiltinsArrayBuffer::IsUnclampedIntegerElementType(DataViewType type)
|
||||
{
|
||||
switch (type) {
|
||||
case DataViewType::INT8:
|
||||
case DataViewType::INT16:
|
||||
case DataViewType::INT32:
|
||||
case DataViewType::UINT8:
|
||||
case DataViewType::UINT16:
|
||||
case DataViewType::UINT32:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void BuiltinsArrayBuffer::SetTypeData(uint8_t *block, T value, uint32_t index)
|
||||
{
|
||||
|
@ -66,6 +66,8 @@ public:
|
||||
// 24.1.1.1 AllocateArrayBuffer(constructor, byteLength)
|
||||
static JSTaggedValue AllocateArrayBuffer(JSThread *thread, const JSHandle<JSTaggedValue> &newTarget,
|
||||
double byteLength);
|
||||
// es12 25.1.2.6 IsUnclampedIntegerElementType ( type )
|
||||
static bool IsUnclampedIntegerElementType(DataViewType type);
|
||||
// es12 25.1.2.7 IsBigIntElementType ( type )
|
||||
static bool IsBigIntElementType(DataViewType type);
|
||||
|
||||
|
587
ecmascript/builtins/builtins_atomics.cpp
Normal file
587
ecmascript/builtins/builtins_atomics.cpp
Normal file
@ -0,0 +1,587 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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/builtins/builtins_atomics.h"
|
||||
|
||||
#include "ecmascript/base/atomic_helper.h"
|
||||
#include "ecmascript/base/typed_array_helper-inl.h"
|
||||
#include "utils/time.h"
|
||||
|
||||
namespace panda::ecmascript::builtins {
|
||||
using NumberHelper = base::NumberHelper;
|
||||
using AtomicHelper = base::AtomicHelper;
|
||||
using BytesSize = base::BytesSize;
|
||||
using BuiltinsArrayBuffer = builtins::BuiltinsArrayBuffer;
|
||||
|
||||
WaiterList *g_waitLists = Singleton<WaiterList>::GetInstance();
|
||||
Mutex *g_mutex = Singleton<Mutex>::GetInstance();
|
||||
|
||||
// 25.4.2 Atomics.add ( typedArray, index, value )
|
||||
JSTaggedValue BuiltinsAtomics::Sub(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, Atomics, Sub);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> typedArray = GetCallArg(argv, 0);
|
||||
JSHandle<JSTaggedValue> index = GetCallArg(argv, 1);
|
||||
return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::SubFun());
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsAtomics::Add(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, Atomics, Add);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> typedArray = GetCallArg(argv, 0);
|
||||
JSHandle<JSTaggedValue> index = GetCallArg(argv, 1);
|
||||
return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::AddFun());
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsAtomics::And(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, Atomics, And);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> typedArray = GetCallArg(argv, 0);
|
||||
JSHandle<JSTaggedValue> index = GetCallArg(argv, 1);
|
||||
return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::AndFun());
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsAtomics::Or(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, Atomics, Or);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> typedArray = GetCallArg(argv, 0);
|
||||
JSHandle<JSTaggedValue> index = GetCallArg(argv, 1);
|
||||
return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::OrFun());
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsAtomics::Xor(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, Atomics, Xor);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> typedArray = GetCallArg(argv, 0);
|
||||
JSHandle<JSTaggedValue> index = GetCallArg(argv, 1);
|
||||
return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::XorFun());
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsAtomics::CompareExchange(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, Atomics, CompareExchange);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> typedArray = GetCallArg(argv, 0);
|
||||
JSHandle<JSTaggedValue> index = GetCallArg(argv, 1);
|
||||
return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::CompareExchangeFun());
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsAtomics::Exchange(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, Atomics, Exchange);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> typedArray = GetCallArg(argv, 0);
|
||||
JSHandle<JSTaggedValue> index = GetCallArg(argv, 1);
|
||||
return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::ExchangeFun());
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsAtomics::Store(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, Atomics, Store);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> typedArray = GetCallArg(argv, 0);
|
||||
JSHandle<JSTaggedValue> index = GetCallArg(argv, 1);
|
||||
JSHandle<JSTaggedValue> value = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
|
||||
return AtomicHelper::AtomicStore(thread, typedArray, index, value);
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsAtomics::Load(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, Atomics, Load);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> typedArray = GetCallArg(argv, 0);
|
||||
JSHandle<JSTaggedValue> index = GetCallArg(argv, 1);
|
||||
return AtomicHelper::AtomicLoad(thread, typedArray, index);
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsAtomics::IsLockFree(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, Atomics, IsLockFree);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> sizeTag = GetCallArg(argv, 0);
|
||||
BytesSize size = BytesSize(JSTaggedValue::ToInt32(thread, sizeTag));
|
||||
bool result;
|
||||
switch (size) {
|
||||
case BytesSize::ONEBYTES:
|
||||
case BytesSize::TWOBYTES:
|
||||
case BytesSize::FOURBYTES:
|
||||
case BytesSize::EIGHTBYTES:
|
||||
result = true;
|
||||
break;
|
||||
default:
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
return JSTaggedValue(result);
|
||||
}
|
||||
|
||||
// 25.4.11 Atomics.wait ( typedArray, index, value, timeout )
|
||||
JSTaggedValue BuiltinsAtomics::Wait(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, Atomic, Wait);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
|
||||
JSHandle<JSTaggedValue> array = GetCallArg(argv, 0);
|
||||
JSHandle<JSTaggedValue> index = GetCallArg(argv, 1);
|
||||
JSHandle<JSTaggedValue> value = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
|
||||
JSHandle<JSTaggedValue> timeout = GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH);
|
||||
|
||||
// 1. Let buffer be ? ValidateIntegerTypedArray(typedArray, true).
|
||||
JSHandle<JSTaggedValue> arrayBuffer(thread, AtomicHelper::ValidateIntegerTypedArray(thread, array, true));
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// 2. If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception.
|
||||
if (!arrayBuffer->IsSharedArrayBuffer()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "buffer is not sharedArrayBuffer.",
|
||||
JSTaggedValue::Exception());
|
||||
}
|
||||
|
||||
// 3. Let indexedPosition be ? ValidateAtomicAccess(typedArray, index).
|
||||
int32_t indexedPosition = AtomicHelper::ValidateAtomicAccess(thread, array, index);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// 4. If typedArray.[[TypedArrayName]] is "BigInt64Array", let v be ? ToBigInt64(value).
|
||||
// 5. Otherwise, let v be ? ToInt32(value).
|
||||
int64_t v = 0;
|
||||
if (array->IsJSBigInt64Array()) {
|
||||
v = JSHandle<BigInt>::Cast(value)->ToInt64();
|
||||
} else {
|
||||
v = static_cast<int64_t>(JSTaggedValue::ToInt32(thread, value));
|
||||
}
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// 6. Let q be ? ToNumber(timeout).
|
||||
// 7. If q is NaN or +∞𝔽, let t be +∞; else if q is -∞𝔽, let t be 0; else let t be max(ℝ(q), 0).
|
||||
double t = 0;
|
||||
if (timeout->IsUndefined()) {
|
||||
t = base::POSITIVE_INFINITY;
|
||||
} else {
|
||||
JSTaggedNumber q = JSTaggedValue::ToNumber(thread, timeout);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
t = q.GetNumber();
|
||||
if (NumberHelper::IsNaN(q) || (!NumberHelper::IsFinite(q) && t > 0)) {
|
||||
t = base::POSITIVE_INFINITY;
|
||||
} else if (t < 0) {
|
||||
t = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 8. Let B be AgentCanSuspend().
|
||||
// 9. If B is false, throw a TypeError exception.
|
||||
if (!thread->GetEcmaVM()->GetAllowAtomicWait()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "vm does not allow wait to block.",
|
||||
JSTaggedValue::Exception());
|
||||
}
|
||||
WaitResult res = WaitResult::OK;
|
||||
if (array->IsJSBigInt64Array()) {
|
||||
// AtomicHelper::Wait<int64_t>(thread, arrayBuffer, indexedPosition, v, t);
|
||||
res = DoWait<int64_t>(thread, arrayBuffer, indexedPosition, v, t);
|
||||
} else {
|
||||
// AtomicHelper::Wait<int32_t>(thread, arrayBuffer, indexedPosition, static_cast<int32_t>(v), t);
|
||||
res = DoWait<int32_t>(thread, arrayBuffer, indexedPosition, static_cast<int32_t>(v), t);
|
||||
}
|
||||
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
|
||||
if (res == WaitResult::OK) {
|
||||
return globalConst->GetOkString();
|
||||
} else if (res == WaitResult::NOT_EQ) {
|
||||
return globalConst->GetNotEqualString();
|
||||
}
|
||||
return globalConst->GetTimeoutString();
|
||||
}
|
||||
|
||||
// 25.4.12 Atomics.notify ( typedArray, index, count )
|
||||
JSTaggedValue BuiltinsAtomics::Notify(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, Atomic, Notify);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
|
||||
JSHandle<JSTaggedValue> array = GetCallArg(argv, 0);
|
||||
JSHandle<JSTaggedValue> index = GetCallArg(argv, 1);
|
||||
JSHandle<JSTaggedValue> count = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
|
||||
|
||||
// 1. Let buffer be ? ValidateIntegerTypedArray(typedArray, true).
|
||||
JSHandle<JSTaggedValue> arrayBuffer(thread, AtomicHelper::ValidateIntegerTypedArray(thread, array, true));
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// 2. Let indexedPosition be ? ValidateAtomicAccess(typedArray, index).
|
||||
int32_t indexedPosition = AtomicHelper::ValidateAtomicAccess(thread, array, index);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// 3. If count is undefined, let c be +∞.
|
||||
// 4. Else,
|
||||
// a. Let intCount be ? ToIntegerOrInfinity(count).
|
||||
// b. Let c be max(intCount, 0).
|
||||
double c = 0;
|
||||
if (count->IsUndefined()) {
|
||||
c = base::POSITIVE_INFINITY;
|
||||
} else {
|
||||
JSTaggedNumber countTemp = JSTaggedValue::ToNumber(thread, count);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
c = base::NumberHelper::TruncateDouble(countTemp.GetNumber());
|
||||
c = c < 0 ? 0 : c;
|
||||
}
|
||||
// 6. If IsSharedArrayBuffer(buffer) is false, return +0𝔽.
|
||||
if (!arrayBuffer->IsSharedArrayBuffer()) {
|
||||
return JSTaggedValue(0);
|
||||
}
|
||||
return JSTaggedValue(Signal(arrayBuffer, indexedPosition, c));
|
||||
}
|
||||
|
||||
template<typename callbackfun>
|
||||
JSTaggedValue BuiltinsAtomics::AtomicReadModifyWrite(JSThread *thread, const JSHandle<JSTaggedValue> &typedArray,
|
||||
JSHandle<JSTaggedValue> &index, EcmaRuntimeCallInfo *argv,
|
||||
const callbackfun &op)
|
||||
{
|
||||
if (!typedArray->IsTypedArray()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "This is not a TypedArray.", JSTaggedValue::Exception());
|
||||
}
|
||||
// 1. Let buffer be ? ValidateIntegerTypedArray(typedArray).
|
||||
JSTaggedValue bufferValue = base::AtomicHelper::ValidateIntegerTypedArray(thread, typedArray);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
JSHandle<JSTaggedValue> buffer(thread, bufferValue);
|
||||
// 2. Let indexedPosition be ? ValidateAtomicAccess(typedArray, index).
|
||||
int32_t indexedPosition = base::AtomicHelper::ValidateAtomicAccess(thread, typedArray, index);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
// 3. Let arrayTypeName be typedArray.[[TypedArrayName]].
|
||||
JSHandle<JSTaggedValue> arrayTypeName(thread,
|
||||
JSTypedArray::Cast(typedArray->GetTaggedObject())->GetTypedArrayName());
|
||||
if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer.GetTaggedValue())) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "The ArrayBuffer of this value is detached buffer.",
|
||||
JSTaggedValue::Exception());
|
||||
}
|
||||
// 7. NOTE: The above check is not redundant with the check in ValidateIntegerTypedArray because the call to
|
||||
// ToBigInt or ToIntegerOrInfinity on the preceding lines can have arbitrary side effects, which could cause the
|
||||
// buffer to become detached.
|
||||
// 8. Let elementType be the Element Type value in Table 60 for arrayTypeName.
|
||||
DataViewType elementType = JSTypedArray::GetTypeFromName(thread, arrayTypeName);
|
||||
// 9. Return GetModifySetValueInBuffer(buffer, indexedPosition, elementType, v, op).
|
||||
return AtomicReadModifyWriteCase(thread, buffer.GetTaggedValue(), elementType, indexedPosition, argv, op);
|
||||
}
|
||||
|
||||
template<typename callbackfun>
|
||||
JSTaggedValue BuiltinsAtomics::AtomicReadModifyWriteCase(JSThread *thread, JSTaggedValue arrBuf,
|
||||
DataViewType type, int32_t indexedPosition,
|
||||
EcmaRuntimeCallInfo *argv, const callbackfun &op)
|
||||
{
|
||||
JSArrayBuffer *jsArrayBuffer = JSArrayBuffer::Cast(arrBuf.GetTaggedObject());
|
||||
JSTaggedValue data = jsArrayBuffer->GetArrayBufferData();
|
||||
void *pointer = JSNativePointer::Cast(data.GetTaggedObject())->GetExternalPointer();
|
||||
auto *block = reinterpret_cast<uint8_t *>(pointer);
|
||||
uint32_t size = argv->GetArgsNumber();
|
||||
switch (type) {
|
||||
case DataViewType::UINT8:
|
||||
return HandleWithUint8(thread, size, block, indexedPosition, argv, op);
|
||||
case DataViewType::INT8:
|
||||
return HandleWithInt8(thread, size, block, indexedPosition, argv, op);
|
||||
case DataViewType::UINT16:
|
||||
return HandleWithUint16(thread, size, block, indexedPosition, argv, op);
|
||||
case DataViewType::INT16:
|
||||
return HandleWithInt16(thread, size, block, indexedPosition, argv, op);
|
||||
case DataViewType::UINT32:
|
||||
return HandleWithUint32(thread, size, block, indexedPosition, argv, op);
|
||||
case DataViewType::INT32:
|
||||
return HandleWithInt32(thread, size, block, indexedPosition, argv, op);
|
||||
case DataViewType::BIGINT64:
|
||||
return HandleWithBigInt64(thread, size, block, indexedPosition, argv, op);
|
||||
case DataViewType::BIGUINT64:
|
||||
return HandleWithBigUint64(thread, size, block, indexedPosition, argv, op);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
template<typename callbackfun>
|
||||
JSTaggedValue BuiltinsAtomics::HandleWithUint8(JSThread *thread, uint32_t size, uint8_t *block,
|
||||
int32_t indexedPosition,
|
||||
EcmaRuntimeCallInfo *argv, const callbackfun &op)
|
||||
{
|
||||
JSHandle<JSTaggedValue> value = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
|
||||
uint8_t tag = JSTaggedValue::ToUint8(thread, value);
|
||||
if (size == 3) { // the number of parameters is 3
|
||||
auto result = op((block + indexedPosition), &tag);
|
||||
return BuiltinsBase::GetTaggedInt(result);
|
||||
}
|
||||
JSHandle<JSTaggedValue> newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH);
|
||||
uint8_t newTag = JSTaggedValue::ToUint8(thread, newValue);
|
||||
uint8_t arg[ARGS_NUMBER] = {0};
|
||||
arg[0] = tag;
|
||||
arg[1] = newTag;
|
||||
auto result = op((block + indexedPosition), arg);
|
||||
return JSTaggedValue(result);
|
||||
}
|
||||
|
||||
template<typename callbackfun>
|
||||
JSTaggedValue BuiltinsAtomics::HandleWithInt8(JSThread *thread, uint32_t size, uint8_t *block,
|
||||
int32_t indexedPosition,
|
||||
EcmaRuntimeCallInfo *argv, const callbackfun &op)
|
||||
{
|
||||
JSHandle<JSTaggedValue> value = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
|
||||
int8_t tag = JSTaggedValue::ToInt8(thread, value);
|
||||
if (size == 3) { // the number of parameters is 3
|
||||
auto result = op(reinterpret_cast<int8_t *>(block + indexedPosition), &tag);
|
||||
return BuiltinsBase::GetTaggedInt(result);
|
||||
}
|
||||
JSHandle<JSTaggedValue> newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH);
|
||||
int8_t newTag = JSTaggedValue::ToInt8(thread, newValue);
|
||||
int8_t arg[ARGS_NUMBER] = {0};
|
||||
arg[0] = tag;
|
||||
arg[1] = newTag;
|
||||
auto result = op(reinterpret_cast<int8_t *>(block + indexedPosition), arg);
|
||||
return JSTaggedValue(result);
|
||||
}
|
||||
|
||||
template<typename callbackfun>
|
||||
JSTaggedValue BuiltinsAtomics::HandleWithUint16(JSThread *thread, uint32_t size, uint8_t *block,
|
||||
int32_t indexedPosition,
|
||||
EcmaRuntimeCallInfo *argv, const callbackfun &op)
|
||||
{
|
||||
JSHandle<JSTaggedValue> value = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
|
||||
uint16_t tag = JSTaggedValue::ToUint16(thread, value);
|
||||
if (size == 3) { // the number of parameters is 3
|
||||
auto result = op(reinterpret_cast<uint16_t *>(block + indexedPosition), &tag);
|
||||
return BuiltinsBase::GetTaggedInt(result);
|
||||
}
|
||||
JSHandle<JSTaggedValue> newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH);
|
||||
uint16_t newTag = JSTaggedValue::ToUint16(thread, newValue);
|
||||
uint16_t arg[ARGS_NUMBER] = {0};
|
||||
arg[0] = tag;
|
||||
arg[1] = newTag;
|
||||
auto result = op(reinterpret_cast<uint16_t *>(block + indexedPosition), arg);
|
||||
return JSTaggedValue(result);
|
||||
}
|
||||
|
||||
template<typename callbackfun>
|
||||
JSTaggedValue BuiltinsAtomics::HandleWithInt16(JSThread *thread, uint32_t size, uint8_t *block,
|
||||
int32_t indexedPosition,
|
||||
EcmaRuntimeCallInfo *argv, const callbackfun &op)
|
||||
{
|
||||
JSHandle<JSTaggedValue> value = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
|
||||
int16_t tag = JSTaggedValue::ToInt16(thread, value);
|
||||
if (size == 3) { // the number of parameters is 3
|
||||
auto result = op(reinterpret_cast<int16_t *>(block + indexedPosition), &tag);
|
||||
return BuiltinsBase::GetTaggedInt(result);
|
||||
}
|
||||
JSHandle<JSTaggedValue> newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH);
|
||||
int16_t newTag = JSTaggedValue::ToInt16(thread, newValue);
|
||||
int16_t arg[ARGS_NUMBER] = {0};
|
||||
arg[0] = tag;
|
||||
arg[1] = newTag;
|
||||
auto result = op(reinterpret_cast<int16_t *>(block + indexedPosition), arg);
|
||||
return JSTaggedValue(result);
|
||||
}
|
||||
|
||||
template<typename callbackfun>
|
||||
JSTaggedValue BuiltinsAtomics::HandleWithUint32(JSThread *thread, uint32_t size, uint8_t *block,
|
||||
int32_t indexedPosition,
|
||||
EcmaRuntimeCallInfo *argv, const callbackfun &op)
|
||||
{
|
||||
JSHandle<JSTaggedValue> value = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
|
||||
uint32_t tag = JSTaggedValue::ToUint32(thread, value);
|
||||
if (size == 3) { // the number of parameters is 3
|
||||
auto result = op(reinterpret_cast<uint32_t *>(block + indexedPosition), &tag);
|
||||
return JSTaggedValue(result);
|
||||
}
|
||||
JSHandle<JSTaggedValue> newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH);
|
||||
uint32_t newTag = JSTaggedValue::ToUint32(thread, newValue);
|
||||
uint32_t arg[ARGS_NUMBER] = {0};
|
||||
arg[0] = tag;
|
||||
arg[1] = newTag;
|
||||
auto result = op(reinterpret_cast<uint32_t *>(block + indexedPosition), arg);
|
||||
return JSTaggedValue(result);
|
||||
}
|
||||
|
||||
template<typename callbackfun>
|
||||
JSTaggedValue BuiltinsAtomics::HandleWithInt32(JSThread *thread, uint32_t size, uint8_t *block,
|
||||
int32_t indexedPosition,
|
||||
EcmaRuntimeCallInfo *argv, const callbackfun &op)
|
||||
{
|
||||
JSHandle<JSTaggedValue> value = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
|
||||
int32_t tag = JSTaggedValue::ToInt32(thread, value);
|
||||
if (size == 3) { // the number of parameters is 3
|
||||
auto result = op(reinterpret_cast<int32_t *>(block + indexedPosition), &tag);
|
||||
return BuiltinsBase::GetTaggedInt(result);
|
||||
}
|
||||
JSHandle<JSTaggedValue> newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH);
|
||||
int32_t newTag = JSTaggedValue::ToInt32(thread, newValue);
|
||||
int32_t arg[ARGS_NUMBER] = {0};
|
||||
arg[0] = tag;
|
||||
arg[1] = newTag;
|
||||
auto result = op(reinterpret_cast<int32_t *>(block + indexedPosition), arg);
|
||||
return JSTaggedValue(result);
|
||||
}
|
||||
|
||||
template<typename callbackfun>
|
||||
JSTaggedValue BuiltinsAtomics::HandleWithBigInt64(JSThread *thread, uint32_t size, uint8_t *block,
|
||||
int32_t indexedPosition,
|
||||
EcmaRuntimeCallInfo *argv, const callbackfun &op)
|
||||
{
|
||||
JSHandle<JSTaggedValue> value = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
|
||||
int64_t val = 0;
|
||||
bool lossless = true;
|
||||
BigInt::BigIntToInt64(thread, value, &val, &lossless);
|
||||
if (size == 3) { // the number of parameters is 3
|
||||
auto result = op(reinterpret_cast<int64_t *>(block + indexedPosition), &val);
|
||||
return BigInt::Int64ToBigInt(thread, result).GetTaggedValue();
|
||||
}
|
||||
JSHandle<JSTaggedValue> newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH);
|
||||
int64_t newVal = 0;
|
||||
BigInt::BigIntToInt64(thread, newValue, &newVal, &lossless);
|
||||
int64_t arg[ARGS_NUMBER] = {0};
|
||||
arg[0] = val;
|
||||
arg[1] = newVal;
|
||||
auto result = op(reinterpret_cast<int64_t *>(block + indexedPosition), arg);
|
||||
return BigInt::Int64ToBigInt(thread, result).GetTaggedValue();
|
||||
}
|
||||
|
||||
template<typename callbackfun>
|
||||
JSTaggedValue BuiltinsAtomics::HandleWithBigUint64(JSThread *thread, uint32_t size, uint8_t *block,
|
||||
int32_t indexedPosition,
|
||||
EcmaRuntimeCallInfo *argv, const callbackfun &op)
|
||||
{
|
||||
JSHandle<JSTaggedValue> value = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
|
||||
uint64_t val = 0;
|
||||
bool lossless = true;
|
||||
BigInt::BigIntToUint64(thread, value, &val, &lossless);
|
||||
if (size == 3) { // the number of parameters is 3
|
||||
auto result = op(reinterpret_cast<uint64_t *>(block + indexedPosition), &val);
|
||||
return BigInt::Uint64ToBigInt(thread, result).GetTaggedValue();
|
||||
}
|
||||
JSHandle<JSTaggedValue> newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH);
|
||||
uint64_t newVal = 0;
|
||||
BigInt::BigIntToUint64(thread, newValue, &newVal, &lossless);
|
||||
uint64_t arg[ARGS_NUMBER] = {0};
|
||||
arg[0] = val;
|
||||
arg[1] = newVal;
|
||||
auto result = op(reinterpret_cast<uint64_t *>(block + indexedPosition), arg);
|
||||
return BigInt::Uint64ToBigInt(thread, result).GetTaggedValue();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
WaitResult BuiltinsAtomics::DoWait(JSThread *thread, JSHandle<JSTaggedValue> &arrayBuffer,
|
||||
size_t index, T execpt, double timeout)
|
||||
{
|
||||
MutexGuard lock_guard(g_mutex);
|
||||
JSHandle<JSNativePointer> np(thread, JSHandle<JSArrayBuffer>::Cast(arrayBuffer)->GetArrayBufferData());
|
||||
void *buffer = np->GetExternalPointer();
|
||||
ASSERT(buffer != nullptr);
|
||||
WaiterListNode *node = thread->GetEcmaVM()->GetWaiterListNode();
|
||||
node->date_ = buffer;
|
||||
node->index_ = index;
|
||||
node->waitPointer_ = reinterpret_cast<int8_t*>(buffer) + index;
|
||||
node->waiting_ = true;
|
||||
std::atomic<T> *atomicValue = reinterpret_cast<std::atomic<T> *>(node->waitPointer_);
|
||||
T value = atomicValue->load();
|
||||
if (value != execpt) {
|
||||
return WaitResult::NOT_EQ;
|
||||
}
|
||||
g_waitLists->AddNode(node);
|
||||
uint64_t currentTime = 0;
|
||||
uint64_t timeoutTime = 0;
|
||||
bool hasTimeout = timeout != base::POSITIVE_INFINITY;
|
||||
if (hasTimeout) {
|
||||
currentTime = time::GetCurrentTimeInMillis();
|
||||
timeoutTime = currentTime + static_cast<uint64_t>(timeout);
|
||||
}
|
||||
WaitResult res = WaitResult::OK;
|
||||
while (true) {
|
||||
if (!node->waiting_) {
|
||||
res = WaitResult::OK;
|
||||
break;
|
||||
}
|
||||
if (hasTimeout) {
|
||||
currentTime = time::GetCurrentTimeInMillis();
|
||||
if (currentTime >= timeoutTime) {
|
||||
res = WaitResult::TIME_OUT;
|
||||
break;
|
||||
}
|
||||
uint64_t untilTime = timeoutTime - currentTime;
|
||||
ASSERT(untilTime != 0);
|
||||
|
||||
node->cond_.TimedWait(g_mutex, untilTime);
|
||||
} else {
|
||||
node->cond_.Wait(g_mutex);
|
||||
}
|
||||
}
|
||||
g_waitLists->DeleteNode(node);
|
||||
node->waiting_ = false;
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t BuiltinsAtomics::Signal(JSHandle<JSTaggedValue> &arrayBuffer, const size_t &index, double wakeCount)
|
||||
{
|
||||
JSTaggedValue data = JSHandle<JSArrayBuffer>::Cast(arrayBuffer)->GetArrayBufferData();
|
||||
void *buffer = JSNativePointer::Cast(data.GetTaggedObject())->GetExternalPointer();
|
||||
ASSERT(buffer != nullptr);
|
||||
MutexGuard lock_guard(g_mutex);
|
||||
auto &locationListMap = g_waitLists->locationListMap_;
|
||||
auto iter = locationListMap.find(reinterpret_cast<int8_t *>(buffer) + index);
|
||||
if (iter == locationListMap.end()) {
|
||||
return 0;
|
||||
}
|
||||
WaiterListNode *node = iter->second.pHead;
|
||||
uint32_t wokenUpCount = 0;
|
||||
while (node != nullptr && wakeCount > 0.0) {
|
||||
if (!node->waiting_) {
|
||||
node = node->next_;
|
||||
continue;
|
||||
}
|
||||
if (buffer == node->date_) {
|
||||
ASSERT(index == node->index_);
|
||||
node->waiting_ = false;
|
||||
|
||||
WaiterListNode *oldNode = node;
|
||||
node = node->next_;
|
||||
oldNode->cond_.Signal();
|
||||
if (wakeCount != base::POSITIVE_INFINITY) {
|
||||
wakeCount--;
|
||||
}
|
||||
wokenUpCount++;
|
||||
continue;
|
||||
}
|
||||
node = node->next_;
|
||||
}
|
||||
return wokenUpCount;
|
||||
}
|
||||
} // namespace panda::ecmascript::builtins
|
94
ecmascript/builtins/builtins_atomics.h
Normal file
94
ecmascript/builtins/builtins_atomics.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_BUILTINS_BUILTINS_ATOMICS_H
|
||||
#define ECMASCRIPT_BUILTINS_BUILTINS_ATOMICS_H
|
||||
|
||||
#include "ecmascript/base/builtins_base.h"
|
||||
#include "ecmascript/js_dataview.h"
|
||||
#include "ecmascript/waiter_list.h"
|
||||
|
||||
namespace panda::ecmascript::builtins {
|
||||
enum class WaitResult: uint8_t {OK = 0, NOT_EQ, TIME_OUT};
|
||||
|
||||
class BuiltinsAtomics : public base::BuiltinsBase {
|
||||
public:
|
||||
// 25.4.2 Atomics.add ( typedArray, index, value )
|
||||
static JSTaggedValue Add(EcmaRuntimeCallInfo *argv);
|
||||
// 25.4.3 Atomics.and ( typedArray, index, value )
|
||||
static JSTaggedValue And(EcmaRuntimeCallInfo *argv);
|
||||
// 25.4.4 Atomics.compareExchange ( typedArray, index, expectedValue, replacementValue)
|
||||
static JSTaggedValue CompareExchange(EcmaRuntimeCallInfo *argv);
|
||||
// 25.4.5 Atomics.exchange ( typedArray, index, value )
|
||||
static JSTaggedValue Exchange(EcmaRuntimeCallInfo *argv);
|
||||
// 25.4.6 Atomics.isLockFree ( size )
|
||||
static JSTaggedValue IsLockFree(EcmaRuntimeCallInfo *argv);
|
||||
// 25.4.7 Atomics.load ( typedArray, index )
|
||||
static JSTaggedValue Load(EcmaRuntimeCallInfo *argv);
|
||||
// 25.4.8 Atomics.or ( typedArray, index, value )
|
||||
static JSTaggedValue Or(EcmaRuntimeCallInfo *argv);
|
||||
// 25.4.9 Atomics.store ( typedArray, index, value )
|
||||
static JSTaggedValue Store(EcmaRuntimeCallInfo *argv);
|
||||
// 25.4.10 Atomics.sub ( typedArray, index, value )
|
||||
static JSTaggedValue Sub(EcmaRuntimeCallInfo *argv);
|
||||
// 25.4.11 Atomics.wait ( typedArray, index, value, timeout)
|
||||
static JSTaggedValue Wait(EcmaRuntimeCallInfo *argv);
|
||||
// 25.4.12 Atomics.notify ( typedArray, index, count)
|
||||
static JSTaggedValue Notify(EcmaRuntimeCallInfo *argv);
|
||||
// 25.4.13 Atomics.xor ( typedArray, index, value )
|
||||
static JSTaggedValue Xor(EcmaRuntimeCallInfo *argv);
|
||||
|
||||
private:
|
||||
static uint32_t Signal(JSHandle<JSTaggedValue> &arrayBuffer, const size_t &index, double wakeCount);
|
||||
template <typename T>
|
||||
static WaitResult DoWait(JSThread *thread, JSHandle<JSTaggedValue> &arrayBuffer,
|
||||
size_t index, T execpt, double timeout);
|
||||
template<typename callbackfun>
|
||||
static JSTaggedValue AtomicReadModifyWrite(JSThread *thread, const JSHandle<JSTaggedValue> &typedArray,
|
||||
JSHandle<JSTaggedValue> &index, EcmaRuntimeCallInfo *argv,
|
||||
const callbackfun &op);
|
||||
template<typename callbackfun>
|
||||
static JSTaggedValue AtomicReadModifyWriteCase(JSThread *thread, JSTaggedValue buffer, DataViewType type,
|
||||
int32_t indexedPosition, EcmaRuntimeCallInfo *argv,
|
||||
const callbackfun &op);
|
||||
template<typename callbackfun>
|
||||
static JSTaggedValue HandleWithUint8(JSThread *thread, uint32_t size, uint8_t *block, int32_t indexedPosition,
|
||||
EcmaRuntimeCallInfo *argv, const callbackfun &op);
|
||||
template<typename callbackfun>
|
||||
static JSTaggedValue HandleWithInt8(JSThread *thread, uint32_t size, uint8_t *block, int32_t indexedPosition,
|
||||
EcmaRuntimeCallInfo *argv, const callbackfun &op);
|
||||
template<typename callbackfun>
|
||||
static JSTaggedValue HandleWithUint16(JSThread *thread, uint32_t size, uint8_t *block, int32_t indexedPosition,
|
||||
EcmaRuntimeCallInfo *argv, const callbackfun &op);
|
||||
template<typename callbackfun>
|
||||
static JSTaggedValue HandleWithInt16(JSThread *thread, uint32_t size, uint8_t *block, int32_t indexedPosition,
|
||||
EcmaRuntimeCallInfo *argv, const callbackfun &op);
|
||||
template<typename callbackfun>
|
||||
static JSTaggedValue HandleWithUint32(JSThread *thread, uint32_t size, uint8_t *block, int32_t indexedPosition,
|
||||
EcmaRuntimeCallInfo *argv, const callbackfun &op);
|
||||
template<typename callbackfun>
|
||||
static JSTaggedValue HandleWithInt32(JSThread *thread, uint32_t size, uint8_t *block, int32_t indexedPosition,
|
||||
EcmaRuntimeCallInfo *argv, const callbackfun &op);
|
||||
template<typename callbackfun>
|
||||
static JSTaggedValue HandleWithBigInt64(JSThread *thread, uint32_t size, uint8_t *block, int32_t indexedPosition,
|
||||
EcmaRuntimeCallInfo *argv, const callbackfun &op);
|
||||
template<typename callbackfun>
|
||||
static JSTaggedValue HandleWithBigUint64(JSThread *thread, uint32_t size, uint8_t *block, int32_t indexedPosition,
|
||||
EcmaRuntimeCallInfo *argv, const callbackfun &op);
|
||||
|
||||
static constexpr int ARGS_NUMBER = 2;
|
||||
};
|
||||
} // namespace panda::ecmascript::builtins
|
||||
#endif // ECMASCRIPT_BUILTINS_BUILTINS_MATH_H
|
@ -992,7 +992,7 @@ JSTaggedValue BuiltinsTypedArray::Set(EcmaRuntimeCallInfo *argv)
|
||||
uint32_t targetLength = targetObj->GetArrayLength();
|
||||
JSHandle<JSTaggedValue> targetName(thread, targetObj->GetTypedArrayName());
|
||||
uint32_t targetElementSize = TypedArrayHelper::GetSizeFromName(thread, targetName);
|
||||
DataViewType targetType = TypedArrayHelper::GetTypeFromName(thread, targetName);
|
||||
DataViewType targetType = JSTypedArray::GetTypeFromName(thread, targetName);
|
||||
uint32_t targetByteOffset = targetObj->GetByteOffset();
|
||||
|
||||
JSHandle<JSTaggedValue> argArray = GetCallArg(argv, 0);
|
||||
@ -1084,7 +1084,7 @@ JSTaggedValue BuiltinsTypedArray::Set(EcmaRuntimeCallInfo *argv)
|
||||
// 21. Let srcLength be the value of typedArray’s [[ArrayLength]] internal slot.
|
||||
// 22. Let srcByteOffset be the value of typedArray’s [[ByteOffset]] internal slot.
|
||||
JSHandle<JSTaggedValue> srcName(thread, typedArray->GetTypedArrayName());
|
||||
DataViewType srcType = TypedArrayHelper::GetTypeFromName(thread, srcName);
|
||||
DataViewType srcType = JSTypedArray::GetTypeFromName(thread, srcName);
|
||||
uint32_t srcElementSize = TypedArrayHelper::GetSizeFromName(thread, srcName);
|
||||
uint32_t srcLength = typedArray->GetArrayLength();
|
||||
uint32_t srcByteOffset = typedArray->GetByteOffset();
|
||||
@ -1214,11 +1214,11 @@ JSTaggedValue BuiltinsTypedArray::Slice(EcmaRuntimeCallInfo *argv)
|
||||
// 17. Let srcName be the String value of O’s [[TypedArrayName]] internal slot.
|
||||
// 18. Let srcType be the String value of the Element Type value in Table 49 for srcName.
|
||||
JSHandle<JSTaggedValue> srcName(thread, thisObj->GetTypedArrayName());
|
||||
DataViewType srcType = TypedArrayHelper::GetTypeFromName(thread, srcName);
|
||||
DataViewType srcType = JSTypedArray::GetTypeFromName(thread, srcName);
|
||||
// 19. Let targetName be the String value of A’s [[TypedArrayName]] internal slot.
|
||||
// 20. Let targetType be the String value of the Element Type value in Table 49 for targetName.
|
||||
JSHandle<JSTaggedValue> targetName(thread, JSTypedArray::Cast(*newArrObj)->GetTypedArrayName());
|
||||
DataViewType targetType = TypedArrayHelper::GetTypeFromName(thread, targetName);
|
||||
DataViewType targetType = JSTypedArray::GetTypeFromName(thread, targetName);
|
||||
// 21. If SameValue(srcType, targetType) is false, then
|
||||
// a. Let n be 0.
|
||||
// b. Repeat, while k < final
|
||||
|
@ -52,6 +52,7 @@ host_unittest_action("BuiltinsNaturalTest") {
|
||||
# test file
|
||||
"builtins_array_test.cpp",
|
||||
"builtins_arraybuffer_test.cpp",
|
||||
"builtins_atomics_test.cpp",
|
||||
"builtins_boolean_test.cpp",
|
||||
"builtins_dataview_test.cpp",
|
||||
"builtins_date_test.cpp",
|
||||
|
626
ecmascript/builtins/tests/builtins_atomics_test.cpp
Normal file
626
ecmascript/builtins/tests/builtins_atomics_test.cpp
Normal file
@ -0,0 +1,626 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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/builtins/builtins_array.h"
|
||||
#include "ecmascript/builtins/builtins_atomics.h"
|
||||
#include "ecmascript/builtins/builtins_typedarray.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_array.h"
|
||||
#include "ecmascript/js_handle.h"
|
||||
#include "ecmascript/js_thread.h"
|
||||
#include "ecmascript/js_typed_array.h"
|
||||
#include "ecmascript/tests/test_helper.h"
|
||||
|
||||
using namespace panda::ecmascript;
|
||||
using namespace panda::ecmascript::builtins;
|
||||
|
||||
namespace panda::test {
|
||||
using TypedArray = ecmascript::builtins::BuiltinsTypedArray;
|
||||
class BuiltinsAtomicsTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "SetUpTestCase";
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "TearDownCase";
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
TestHelper::DestroyEcmaVMWithScope(instance, scope);
|
||||
}
|
||||
|
||||
EcmaVM *instance {nullptr};
|
||||
EcmaHandleScope *scope {nullptr};
|
||||
JSThread *thread {nullptr};
|
||||
};
|
||||
|
||||
JSTypedArray *CreateTypedArray(JSThread *thread, const JSHandle<TaggedArray> &array)
|
||||
{
|
||||
auto ecmaVM = thread->GetEcmaVM();
|
||||
JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
|
||||
|
||||
JSHandle<JSTaggedValue> jsarray(JSArray::CreateArrayFromList(thread, array));
|
||||
JSHandle<JSFunction> int8_array(env->GetInt8ArrayFunction());
|
||||
JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
|
||||
// 6 : test case
|
||||
auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*int8_array), 6);
|
||||
ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue(*int8_array));
|
||||
ecmaRuntimeCallInfo1->SetThis(JSTaggedValue(*globalObject));
|
||||
ecmaRuntimeCallInfo1->SetCallArg(0, jsarray.GetTaggedValue());
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1.get());
|
||||
JSTaggedValue result = TypedArray::Int8ArrayConstructor(ecmaRuntimeCallInfo1.get());
|
||||
|
||||
EXPECT_TRUE(result.IsECMAObject());
|
||||
JSTypedArray *int8arr = JSTypedArray::Cast(reinterpret_cast<TaggedObject *>(result.GetRawData()));
|
||||
return int8arr;
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, Add_1)
|
||||
{
|
||||
ASSERT_NE(thread, nullptr);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(3));
|
||||
array->Set(thread, 0, JSTaggedValue(7));
|
||||
array->Set(thread, 1, JSTaggedValue(8));
|
||||
array->Set(thread, 2, JSTaggedValue(9));
|
||||
|
||||
JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array));
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(5)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::Add(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 7);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, Add_2)
|
||||
{
|
||||
ASSERT_NE(thread, nullptr);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(10));
|
||||
|
||||
JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array));
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(2)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::Add(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 0);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, Add_3)
|
||||
{
|
||||
ASSERT_NE(thread, nullptr);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(3));
|
||||
|
||||
JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array));
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(2)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::Add(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 0);
|
||||
|
||||
|
||||
auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
|
||||
ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfos->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfos->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfos->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
|
||||
prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos.get());
|
||||
JSTaggedValue results = BuiltinsAtomics::Load(ecmaRuntimeCallInfos.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(results.GetInt(), 2);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, And_1)
|
||||
{
|
||||
ASSERT_NE(thread, nullptr);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(10));
|
||||
array->Set(thread, 0, JSTaggedValue(7));
|
||||
array->Set(thread, 1, JSTaggedValue(0));
|
||||
array->Set(thread, 2, JSTaggedValue(0));
|
||||
|
||||
JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array));
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(2)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::Add(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 7);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, And_2)
|
||||
{
|
||||
ASSERT_NE(thread, nullptr);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(10));
|
||||
array->Set(thread, 0, JSTaggedValue(7));
|
||||
array->Set(thread, 1, JSTaggedValue(0));
|
||||
array->Set(thread, 2, JSTaggedValue(0));
|
||||
|
||||
JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array));
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(2)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::And(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 7);
|
||||
|
||||
|
||||
auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
|
||||
ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfos->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfos->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfos->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
|
||||
prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos.get());
|
||||
result = BuiltinsAtomics::Load(ecmaRuntimeCallInfos.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 2);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, CompareExchange_1)
|
||||
{
|
||||
ASSERT_NE(thread, nullptr);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(3));
|
||||
array->Set(thread, 0, JSTaggedValue(5));
|
||||
array->Set(thread, 1, JSTaggedValue(0));
|
||||
array->Set(thread, 2, JSTaggedValue(0));
|
||||
|
||||
JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array));
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 12);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(5)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(3, JSTaggedValue(static_cast<int32_t>(2)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::CompareExchange(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 5);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, CompareExchange_2)
|
||||
{
|
||||
ASSERT_NE(thread, nullptr);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(3));
|
||||
array->Set(thread, 0, JSTaggedValue(5));
|
||||
array->Set(thread, 1, JSTaggedValue(0));
|
||||
array->Set(thread, 2, JSTaggedValue(0));
|
||||
|
||||
JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array));
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 12);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(5)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(3, JSTaggedValue(static_cast<int32_t>(2)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::CompareExchange(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 5);
|
||||
|
||||
|
||||
auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
|
||||
ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfos->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfos->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfos->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
|
||||
prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos.get());
|
||||
result = BuiltinsAtomics::Load(ecmaRuntimeCallInfos.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 2);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, Exchange_1)
|
||||
{
|
||||
ASSERT_NE(thread, nullptr);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(3));
|
||||
array->Set(thread, 0, JSTaggedValue(3));
|
||||
array->Set(thread, 1, JSTaggedValue(0));
|
||||
array->Set(thread, 2, JSTaggedValue(0));
|
||||
|
||||
JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array));
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(6)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::Exchange(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 3);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, Exchange_2)
|
||||
{
|
||||
ASSERT_NE(thread, nullptr);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(3));
|
||||
array->Set(thread, 0, JSTaggedValue(3));
|
||||
array->Set(thread, 1, JSTaggedValue(0));
|
||||
array->Set(thread, 2, JSTaggedValue(0));
|
||||
|
||||
JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array));
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(6)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::Exchange(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 3);
|
||||
|
||||
|
||||
auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
|
||||
ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfos->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfos->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfos->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
|
||||
prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos.get());
|
||||
result = BuiltinsAtomics::Load(ecmaRuntimeCallInfos.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 6);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, Or_1)
|
||||
{
|
||||
ASSERT_NE(thread, nullptr);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(3));
|
||||
array->Set(thread, 0, JSTaggedValue(5));
|
||||
array->Set(thread, 1, JSTaggedValue(0));
|
||||
array->Set(thread, 2, JSTaggedValue(0));
|
||||
|
||||
JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array));
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(2)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::Or(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 5);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, Or_2)
|
||||
{
|
||||
ASSERT_NE(thread, nullptr);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(3));
|
||||
array->Set(thread, 0, JSTaggedValue(5));
|
||||
array->Set(thread, 1, JSTaggedValue(0));
|
||||
array->Set(thread, 2, JSTaggedValue(0));
|
||||
|
||||
JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array));
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 12);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(2)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::Or(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 5);
|
||||
|
||||
|
||||
auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
|
||||
ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfos->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfos->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfos->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
|
||||
prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos.get());
|
||||
result = BuiltinsAtomics::Load(ecmaRuntimeCallInfos.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 7);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, Sub_1)
|
||||
{
|
||||
ASSERT_NE(thread, nullptr);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(3));
|
||||
array->Set(thread, 0, JSTaggedValue(5));
|
||||
array->Set(thread, 1, JSTaggedValue(0));
|
||||
array->Set(thread, 2, JSTaggedValue(0));
|
||||
|
||||
JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array));
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(2)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::Sub(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 5);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, Sub_2)
|
||||
{
|
||||
ASSERT_NE(thread, nullptr);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(3));
|
||||
array->Set(thread, 0, JSTaggedValue(0));
|
||||
array->Set(thread, 1, JSTaggedValue(5));
|
||||
array->Set(thread, 2, JSTaggedValue(0));
|
||||
|
||||
JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array));
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(1)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(2)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::Sub(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 5);
|
||||
|
||||
auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
|
||||
ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfos->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfos->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfos->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(1)));
|
||||
|
||||
prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos.get());
|
||||
result = BuiltinsAtomics::Load(ecmaRuntimeCallInfos.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 3);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, Xor_1)
|
||||
{
|
||||
ASSERT_NE(thread, nullptr);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(3));
|
||||
array->Set(thread, 0, JSTaggedValue(5));
|
||||
array->Set(thread, 1, JSTaggedValue(7));
|
||||
array->Set(thread, 2, JSTaggedValue(0));
|
||||
|
||||
JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array));
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(1)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(2)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::Xor(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 7);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, Xor_2)
|
||||
{
|
||||
ASSERT_NE(thread, nullptr);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(3));
|
||||
array->Set(thread, 0, JSTaggedValue(5));
|
||||
array->Set(thread, 1, JSTaggedValue(7));
|
||||
array->Set(thread, 2, JSTaggedValue(0));
|
||||
|
||||
JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array));
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(1)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(2)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::Xor(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 7);
|
||||
|
||||
auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
|
||||
ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfos->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfos->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfos->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(1)));
|
||||
|
||||
prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos.get());
|
||||
result = BuiltinsAtomics::Load(ecmaRuntimeCallInfos.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 5);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_1)
|
||||
{
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(1)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::IsLockFree(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_TRUE(result.ToBoolean());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_2)
|
||||
{
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(2)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::IsLockFree(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_TRUE(result.ToBoolean());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_3)
|
||||
{
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(4)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::IsLockFree(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_TRUE(result.ToBoolean());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_4)
|
||||
{
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(-3)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::IsLockFree(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_FALSE(result.ToBoolean());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_5)
|
||||
{
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(8)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::IsLockFree(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_TRUE(result.ToBoolean());
|
||||
}
|
||||
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, Store_1)
|
||||
{
|
||||
ASSERT_NE(thread, nullptr);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(3));
|
||||
array->Set(thread, 0, JSTaggedValue(5));
|
||||
array->Set(thread, 1, JSTaggedValue(6));
|
||||
array->Set(thread, 2, JSTaggedValue(7));
|
||||
|
||||
JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array));
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(2)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::Store(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetDouble(), 2);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsAtomicsTest, Store_2)
|
||||
{
|
||||
ASSERT_NE(thread, nullptr);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
[[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(3));
|
||||
array->Set(thread, 0, JSTaggedValue(5));
|
||||
array->Set(thread, 1, JSTaggedValue(6));
|
||||
array->Set(thread, 2, JSTaggedValue(7));
|
||||
|
||||
JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array));
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(2)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsAtomics::Store(ecmaRuntimeCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetDouble(), 2);
|
||||
|
||||
auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
|
||||
ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfos->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfos->SetCallArg(0, obj.GetTaggedValue());
|
||||
ecmaRuntimeCallInfos->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
|
||||
|
||||
prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos.get());
|
||||
result = BuiltinsAtomics::Load(ecmaRuntimeCallInfos.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
ASSERT_EQ(result.GetInt(), 2);
|
||||
}
|
||||
}
|
@ -1711,6 +1711,8 @@ void GlobalEnv::Dump(std::ostream &os) const
|
||||
GetBuiltinsWeakMapFunction().GetTaggedValue().Dump(os);
|
||||
os << " - MathFunction: ";
|
||||
GetMathFunction().GetTaggedValue().Dump(os);
|
||||
os << " - AtomicsFunction: ";
|
||||
GetAtomicsFunction().GetTaggedValue().Dump(os);
|
||||
os << " - JsonFunction: ";
|
||||
GetJsonFunction().GetTaggedValue().Dump(os);
|
||||
os << " - StringFunction: ";
|
||||
@ -3589,6 +3591,7 @@ void GlobalEnv::DumpForSnapshot(std::vector<std::pair<CString, JSTaggedValue>> &
|
||||
vec.push_back(std::make_pair(CString("BuiltinsWeakSetFunction"), GetBuiltinsWeakSetFunction().GetTaggedValue()));
|
||||
vec.push_back(std::make_pair(CString("BuiltinsWeakMapFunction"), GetBuiltinsWeakMapFunction().GetTaggedValue()));
|
||||
vec.push_back(std::make_pair(CString("MathFunction"), GetMathFunction().GetTaggedValue()));
|
||||
vec.push_back(std::make_pair(CString("AtomicsFunction"), GetAtomicsFunction().GetTaggedValue()));
|
||||
vec.push_back(std::make_pair(CString("JsonFunction"), GetJsonFunction().GetTaggedValue()));
|
||||
vec.push_back(std::make_pair(CString("StringFunction"), GetStringFunction().GetTaggedValue()));
|
||||
vec.push_back(std::make_pair(CString("ProxyFunction"), GetProxyFunction().GetTaggedValue()));
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "ecmascript/mem/chunk_containers.h"
|
||||
#include "ecmascript/taskpool/taskpool.h"
|
||||
#include "ecmascript/js_thread.h"
|
||||
#include "ecmascript/waiter_list.h"
|
||||
|
||||
namespace panda {
|
||||
class JSNApi;
|
||||
@ -273,6 +274,21 @@ public:
|
||||
hostPromiseRejectionTracker_ = cb;
|
||||
}
|
||||
|
||||
void SetAllowAtomicWait(bool wait)
|
||||
{
|
||||
AllowAtomicWait_ = wait;
|
||||
}
|
||||
|
||||
bool GetAllowAtomicWait() const
|
||||
{
|
||||
return AllowAtomicWait_;
|
||||
}
|
||||
|
||||
WaiterListNode *GetWaiterListNode()
|
||||
{
|
||||
return &waiterListNode_;
|
||||
}
|
||||
|
||||
void PromiseRejectionTracker(const JSHandle<JSPromise> &promise,
|
||||
const JSHandle<JSTaggedValue> &reason, PromiseRejectionEvent operation)
|
||||
{
|
||||
@ -374,6 +390,9 @@ private:
|
||||
void* data_ {nullptr};
|
||||
|
||||
bool isProcessingPendingJob_ = false;
|
||||
// atomics
|
||||
bool AllowAtomicWait_ {true};
|
||||
WaiterListNode waiterListNode_;
|
||||
|
||||
friend class Snapshot;
|
||||
friend class SnapshotProcessor;
|
||||
|
@ -81,6 +81,7 @@ class JSThread;
|
||||
V(JSTaggedValue, BuiltinsWeakSetFunction, BUILTINS_WEAK_SET_FUNCTION_INDEX) \
|
||||
V(JSTaggedValue, MapPrototype, MAP_PROTOTYPE_INDEX) \
|
||||
V(JSTaggedValue, MathFunction, MATH_FUNCTION_INDEX) \
|
||||
V(JSTaggedValue, AtomicsFunction, ATOMICS_FUNCTION_INDEX) \
|
||||
V(JSTaggedValue, JsonFunction, JSON_FUNCTION_INDEX) \
|
||||
V(JSTaggedValue, StringFunction, STRING_FUNCTION_INDEX) \
|
||||
V(JSTaggedValue, ProxyFunction, PROXY_FUNCTION_INDEX) \
|
||||
|
@ -474,6 +474,9 @@ void GlobalEnvConstants::InitGlobalConstant(JSThread *thread)
|
||||
SetConstant(ConstantIndex::ELEMENT_INDEX, factory->NewFromASCII("element"));
|
||||
SetConstant(ConstantIndex::FLAGS_INDEX, factory->NewFromASCII("flags"));
|
||||
SetConstant(ConstantIndex::G_INDEX, factory->NewFromASCII("g"));
|
||||
SetConstant(ConstantIndex::NOT_EQUAL_INDEX, factory->NewFromASCII("not-equal"));
|
||||
SetConstant(ConstantIndex::OK_INDEX, factory->NewFromASCII("ok"));
|
||||
SetConstant(ConstantIndex::TIMEOUT_INDEX, factory->NewFromASCII("timed-out"));
|
||||
|
||||
auto accessor = factory->NewInternalAccessor(reinterpret_cast<void *>(JSFunction::PrototypeSetter),
|
||||
reinterpret_cast<void *>(JSFunction::PrototypeGetter));
|
||||
|
@ -342,7 +342,10 @@ class JSThread;
|
||||
V(JSTaggedValue, DisjunctionString, DISJUNCTION_INDEX, disjunction) \
|
||||
V(JSTaggedValue, ElementString, ELEMENT_INDEX, element) \
|
||||
V(JSTaggedValue, FlagsString, FLAGS_INDEX, flags) \
|
||||
V(JSTaggedValue, GString, G_INDEX, g)
|
||||
V(JSTaggedValue, GString, G_INDEX, g) \
|
||||
V(JSTaggedValue, NotEqualString, NOT_EQUAL_INDEX, notEqual) \
|
||||
V(JSTaggedValue, OkString, OK_INDEX, ok) \
|
||||
V(JSTaggedValue, TimeoutString, TIMEOUT_INDEX, timedout)
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define GLOBAL_ENV_CONSTANT_ACCESSOR(V) \
|
||||
|
@ -954,7 +954,7 @@ std::string BigIntHelper::MultiplyImpl(std::string &a, std::string &b)
|
||||
str[i + j + 1] = static_cast<int8_t>(temp2 % 10 + 48); // 2 and 10 and 48 is number
|
||||
addflag = temp2 / 10;
|
||||
}
|
||||
str[i] += static_cast<int8_t>(mulflag + addflag);
|
||||
str[i] += static_cast<uint32_t>(mulflag + addflag);
|
||||
}
|
||||
if (str[0] == '0') {
|
||||
str = str.substr(1, str.size());
|
||||
@ -1429,4 +1429,19 @@ ComparisonResult BigInt::CompareWithNumber(JSHandle<BigInt> bigint, JSHandle<JST
|
||||
}
|
||||
return ComparisonResult::EQUAL;
|
||||
}
|
||||
|
||||
int64_t BigInt::ToInt64()
|
||||
{
|
||||
int len = GetLength();
|
||||
ASSERT(len < 2); // The maximum length of the BigInt data is less 2
|
||||
uint64_t value = 0;
|
||||
uint32_t *addr = reinterpret_cast<uint32_t *>(&value);
|
||||
for (int index = len - 1; index >= 0; --index) {
|
||||
*(addr + index) = GetDigit(index);
|
||||
}
|
||||
if (GetSign()) {
|
||||
value = ~(value - 1);
|
||||
}
|
||||
return static_cast<int64_t>(value);
|
||||
}
|
||||
} // namespace
|
||||
|
@ -89,6 +89,8 @@ public:
|
||||
static JSTaggedValue AsintN(JSThread *thread, JSTaggedNumber &bits, JSHandle<BigInt> bigint);
|
||||
static JSTaggedNumber BigIntToNumber(JSHandle<BigInt> bigint);
|
||||
static ComparisonResult CompareWithNumber(JSHandle<BigInt> bigint, JSHandle<JSTaggedValue> number);
|
||||
|
||||
int64_t ToInt64();
|
||||
inline bool IsZero()
|
||||
{
|
||||
return GetLength() == 1 && !GetDigit(0);
|
||||
|
@ -406,6 +406,42 @@ bool JSTypedArray::IsValidIntegerIndex(const JSHandle<JSTaggedValue> &typedArray
|
||||
return true;
|
||||
}
|
||||
|
||||
DataViewType JSTypedArray::GetTypeFromName(JSThread *thread, const JSHandle<JSTaggedValue> &typeName)
|
||||
{
|
||||
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledInt8ArrayString())) {
|
||||
return DataViewType::INT8;
|
||||
}
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledUint8ArrayString())) {
|
||||
return DataViewType::UINT8;
|
||||
}
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledUint8ClampedArrayString())) {
|
||||
return DataViewType::UINT8_CLAMPED;
|
||||
}
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledInt16ArrayString())) {
|
||||
return DataViewType::INT16;
|
||||
}
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledUint16ArrayString())) {
|
||||
return DataViewType::UINT16;
|
||||
}
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledInt32ArrayString())) {
|
||||
return DataViewType::INT32;
|
||||
}
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledUint32ArrayString())) {
|
||||
return DataViewType::UINT32;
|
||||
}
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledFloat32ArrayString())) {
|
||||
return DataViewType::FLOAT32;
|
||||
}
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledFloat64ArrayString())) {
|
||||
return DataViewType::FLOAT64;
|
||||
}
|
||||
if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledBigInt64ArrayString())) {
|
||||
return DataViewType::BIGINT64;
|
||||
}
|
||||
return DataViewType::BIGUINT64;
|
||||
}
|
||||
|
||||
// static
|
||||
bool JSTypedArray::FastCopyElementToArray(JSThread *thread, const JSHandle<JSTaggedValue> &typedArray,
|
||||
JSHandle<TaggedArray> &array)
|
||||
|
@ -17,6 +17,7 @@
|
||||
#define ECMASCRIPT_JS_TYPED_ARRAY_H
|
||||
|
||||
#include "ecmascript/tagged_array.h"
|
||||
#include "ecmascript/js_dataview.h"
|
||||
#include "js_object.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
@ -94,6 +95,7 @@ public:
|
||||
// only use in TypeArray fast set property
|
||||
static JSTaggedNumber NonEcmaObjectToNumber(JSThread *thread, const JSTaggedValue tagged);
|
||||
static constexpr size_t VIEWED_ARRAY_BUFFER_OFFSET = JSObject::SIZE;
|
||||
static DataViewType GetTypeFromName(JSThread *thread, const JSHandle<JSTaggedValue> &typeName);
|
||||
ACCESSORS(ViewedArrayBuffer, VIEWED_ARRAY_BUFFER_OFFSET, TYPED_ARRAY_NAME_OFFSET)
|
||||
ACCESSORS(TypedArrayName, TYPED_ARRAY_NAME_OFFSET, BYTE_LENGTH_OFFSET)
|
||||
ACCESSORS_PRIMITIVE_FIELD(ByteLength, uint32_t, BYTE_LENGTH_OFFSET, BYTE_OFFSET_OFFSET)
|
||||
|
@ -104,6 +104,7 @@ void ConcurrentMarker::Reset(bool revertCSet)
|
||||
auto callback = [](Region *region) {
|
||||
region->ClearMarkGCBitset();
|
||||
region->ClearCrossRegionRSet();
|
||||
region->ResetAliveObject();
|
||||
};
|
||||
if (heap_->IsFullMark()) {
|
||||
heap_->EnumerateRegions(callback);
|
||||
|
@ -371,6 +371,18 @@ namespace panda::ecmascript {
|
||||
V(Math, Tan) \
|
||||
V(Math, Tanh) \
|
||||
V(Math, Trunc) \
|
||||
V(Atomics, Add) \
|
||||
V(Atomics, And) \
|
||||
V(Atomics, Or) \
|
||||
V(Atomics, Xor) \
|
||||
V(Atomics, Sub) \
|
||||
V(Atomics, Exchange) \
|
||||
V(Atomics, CompareEchange) \
|
||||
V(Atomics, Store) \
|
||||
V(Atomics, Load) \
|
||||
V(Atomics, IsLockFree) \
|
||||
V(Atomics, Wait) \
|
||||
V(Atomics, Notify) \
|
||||
V(Number, Constructor) \
|
||||
V(Number, IsFinite) \
|
||||
V(Number, IsInteger) \
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "ecmascript/builtins/builtins_array.h"
|
||||
#include "ecmascript/builtins/builtins_arraybuffer.h"
|
||||
#include "ecmascript/builtins/builtins_async_function.h"
|
||||
#include "ecmascript/builtins/builtins_atomics.h"
|
||||
#include "ecmascript/builtins/builtins_bigint.h"
|
||||
#include "ecmascript/builtins/builtins_boolean.h"
|
||||
#include "ecmascript/builtins/builtins_collator.h"
|
||||
@ -116,6 +117,7 @@ using StringIterator = builtins::BuiltinsStringIterator;
|
||||
using RegExp = builtins::BuiltinsRegExp;
|
||||
using Function = builtins::BuiltinsFunction;
|
||||
using Math = builtins::BuiltinsMath;
|
||||
using Atomics = builtins::BuiltinsAtomics;
|
||||
using ArrayBuffer = builtins::BuiltinsArrayBuffer;
|
||||
using Json = builtins::BuiltinsJson;
|
||||
using Proxy = builtins::BuiltinsProxy;
|
||||
@ -504,6 +506,17 @@ static uintptr_t g_nativeTable[] = {
|
||||
reinterpret_cast<uintptr_t>(Math::Tan),
|
||||
reinterpret_cast<uintptr_t>(Math::Tanh),
|
||||
reinterpret_cast<uintptr_t>(Math::Trunc),
|
||||
reinterpret_cast<uintptr_t>(Atomics::Wait),
|
||||
reinterpret_cast<uintptr_t>(Atomics::Exchange),
|
||||
reinterpret_cast<uintptr_t>(Atomics::CompareExchange),
|
||||
reinterpret_cast<uintptr_t>(Atomics::Store),
|
||||
reinterpret_cast<uintptr_t>(Atomics::Load),
|
||||
reinterpret_cast<uintptr_t>(Atomics::Notify),
|
||||
reinterpret_cast<uintptr_t>(Atomics::Xor),
|
||||
reinterpret_cast<uintptr_t>(Atomics::Or),
|
||||
reinterpret_cast<uintptr_t>(Atomics::Sub),
|
||||
reinterpret_cast<uintptr_t>(Atomics::And),
|
||||
reinterpret_cast<uintptr_t>(Atomics::Add),
|
||||
reinterpret_cast<uintptr_t>(Json::Parse),
|
||||
reinterpret_cast<uintptr_t>(Json::Stringify),
|
||||
reinterpret_cast<uintptr_t>(BuiltinsIterator::Next),
|
||||
|
71
ecmascript/waiter_list.cpp
Normal file
71
ecmascript/waiter_list.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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/waiter_list.h"
|
||||
#include "ecmascript/base/number_helper.h"
|
||||
#include "os/time.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
// --------------------------WaiterList------------------------------
|
||||
void WaiterList::AddNode(WaiterListNode *node)
|
||||
{
|
||||
ASSERT(node->prev_ == nullptr);
|
||||
ASSERT(node->next_ == nullptr);
|
||||
auto iter = locationListMap_.find(node->waitPointer_);
|
||||
if (iter != locationListMap_.end()) {
|
||||
iter->second.pTail->next_ = node;
|
||||
node->prev_ = iter->second.pTail;
|
||||
iter->second.pTail = node;
|
||||
} else {
|
||||
locationListMap_.insert(std::make_pair(node->waitPointer_, HeadAndTail {node, node}));
|
||||
}
|
||||
}
|
||||
|
||||
void WaiterList::DeleteNode(WaiterListNode *node)
|
||||
{
|
||||
auto iter = locationListMap_.find(node->waitPointer_);
|
||||
ASSERT(iter != locationListMap_.end());
|
||||
WaiterListNode *temp = iter->second.pHead;
|
||||
bool flag = false;
|
||||
while (temp != nullptr) {
|
||||
if (temp == node) {
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
temp = temp->next_;
|
||||
}
|
||||
ASSERT(flag);
|
||||
if (node == iter->second.pHead && node == iter->second.pTail) {
|
||||
locationListMap_.erase(iter);
|
||||
return;
|
||||
}
|
||||
|
||||
if (node == iter->second.pHead) {
|
||||
iter->second.pHead = node->next_;
|
||||
} else {
|
||||
ASSERT(node->prev_);
|
||||
node->prev_->next_ = node->next_;
|
||||
}
|
||||
|
||||
if (node == iter->second.pTail) {
|
||||
iter->second.pTail = node->prev_;
|
||||
} else {
|
||||
ASSERT(node->next_);
|
||||
node->next_->prev_ = node->prev_;
|
||||
}
|
||||
|
||||
node->prev_ = node->next_ = nullptr;
|
||||
}
|
||||
} // namespace
|
108
ecmascript/waiter_list.h
Normal file
108
ecmascript/waiter_list.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_WAITER_LIST_H
|
||||
#define ECMASCRIPT_WAITER_LIST_H
|
||||
|
||||
#include "ecmascript/ecma_macros.h"
|
||||
#include "ecmascript/mem/c_containers.h"
|
||||
#include "os/mutex.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
using Mutex = os::memory::Mutex;
|
||||
using LockHolder = os::memory::LockHolder<Mutex>;
|
||||
|
||||
class WaiterListNode {
|
||||
public:
|
||||
WaiterListNode() = default;
|
||||
~WaiterListNode() = default;
|
||||
|
||||
public:
|
||||
NO_COPY_SEMANTIC(WaiterListNode);
|
||||
NO_MOVE_SEMANTIC(WaiterListNode);
|
||||
|
||||
WaiterListNode *prev_ {nullptr};
|
||||
WaiterListNode *next_ {nullptr};
|
||||
// Used to call wait or Signal() to unlock wait and wake up
|
||||
os::memory::ConditionVariable cond_;
|
||||
|
||||
// Managed Arraybuffer or SharedArrayBuffer memory data
|
||||
void *date_ {nullptr};
|
||||
|
||||
// the offset of the element in the typedArray
|
||||
size_t index_ {0};
|
||||
|
||||
// the memory address data corresponding to the offset
|
||||
int8_t *waitPointer_ {nullptr};
|
||||
|
||||
// used to determine whether to wait, start wait when waiting_ is true
|
||||
bool waiting_ {false};
|
||||
|
||||
private:
|
||||
friend class WaiterList;
|
||||
};
|
||||
|
||||
// WaiterList to manage WaiterListNode
|
||||
class WaiterList {
|
||||
public:
|
||||
WaiterList() = default;
|
||||
void AddNode(WaiterListNode *node);
|
||||
void DeleteNode(WaiterListNode *node);
|
||||
struct HeadAndTail {
|
||||
WaiterListNode *pHead {nullptr};
|
||||
WaiterListNode *pTail {nullptr};
|
||||
};
|
||||
|
||||
// locationListMap_ is used AddNode or DeleteNode
|
||||
// When calling addnode If there is no corresponding memory data, add the node corresponding to the key
|
||||
CMap<int8_t *, HeadAndTail> locationListMap_;
|
||||
};
|
||||
|
||||
// The Singleton pattern is used to creat a global metux and WaiterList
|
||||
template <class T>
|
||||
class Singleton {
|
||||
public:
|
||||
~Singleton() {}
|
||||
NO_COPY_SEMANTIC(Singleton);
|
||||
NO_MOVE_SEMANTIC(Singleton);
|
||||
static T *GetInstance()
|
||||
{
|
||||
static T instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
private:
|
||||
Singleton() = default;
|
||||
};
|
||||
|
||||
class SCOPED_CAPABILITY MutexGuard
|
||||
{
|
||||
public:
|
||||
explicit MutexGuard(Mutex *mutex) : mutex_(mutex), lockHolder_(*mutex) {}
|
||||
void Unlock() RELEASE()
|
||||
{
|
||||
mutex_->Unlock();
|
||||
}
|
||||
void Lock() ACQUIRE()
|
||||
{
|
||||
mutex_->Lock();
|
||||
}
|
||||
|
||||
public:
|
||||
Mutex *mutex_;
|
||||
LockHolder lockHolder_;
|
||||
};
|
||||
} // namespace
|
||||
#endif // ECMASCRIPT_WAITER_LIST_H
|
Loading…
Reference in New Issue
Block a user