!918 add SharedArrayBuffer

Merge pull request !918 from 赵杜炜/master
This commit is contained in:
openharmony_ci 2022-04-02 11:58:42 +00:00 committed by Gitee
commit e802f8e5e3
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
23 changed files with 677 additions and 16 deletions

View File

@ -327,6 +327,7 @@ ecma_source = [
"ecmascript/builtins/builtins_reflect.cpp",
"ecmascript/builtins/builtins_regexp.cpp",
"ecmascript/builtins/builtins_set.cpp",
"ecmascript/builtins/builtins_sharedarraybuffer.cpp",
"ecmascript/builtins/builtins_string.cpp",
"ecmascript/builtins/builtins_string_iterator.cpp",
"ecmascript/builtins/builtins_symbol.cpp",
@ -458,6 +459,7 @@ ecma_source = [
"ecmascript/regexp/regexp_parser.cpp",
"ecmascript/regexp/regexp_parser_cache.cpp",
"ecmascript/runtime_api.cpp",
"ecmascript/sharedMemoryManaged/sharedmemorymanager.cpp",
"ecmascript/tagged_dictionary.cpp",
"ecmascript/tagged_tree.cpp",
"ecmascript/template_string.cpp",

View File

@ -72,7 +72,7 @@ JSTaggedValue TypedArrayHelper::TypedArrayConstructor(EcmaRuntimeCallInfo *argv,
if (firstArg->IsTypedArray()) {
return TypedArrayHelper::CreateFromTypedArray(argv, obj, constructorName);
}
if (firstArg->IsArrayBuffer()) {
if (firstArg->IsArrayBuffer() || firstArg->IsSharedArrayBuffer()) {
return TypedArrayHelper::CreateFromArrayBuffer(argv, obj, constructorName);
}
return TypedArrayHelper::CreateFromOrdinaryObject(argv, obj);

View File

@ -59,6 +59,7 @@
#include "ecmascript/builtins/builtins_regexp.h"
#include "ecmascript/builtins/builtins_relative_time_format.h"
#include "ecmascript/builtins/builtins_set.h"
#include "ecmascript/builtins/builtins_sharedarraybuffer.h"
#include "ecmascript/builtins/builtins_string.h"
#include "ecmascript/builtins/builtins_string_iterator.h"
#include "ecmascript/builtins/builtins_symbol.h"
@ -151,6 +152,7 @@ using PluralRules = builtins::BuiltinsPluralRules;
using DisplayNames = builtins::BuiltinsDisplayNames;
using ContainersPrivate = containers::ContainersPrivate;
using SharedArrayBuffer = builtins::BuiltinsSharedArrayBuffer;
bool GetAbsolutePath(const std::string &relativePath, std::string &absPath)
{
@ -300,6 +302,7 @@ void Builtins::Initialize(const JSHandle<GlobalEnv> &env, JSThread *thread)
InitializeString(env, primRefObjDynclass);
InitializeArrayBuffer(env, objFuncDynclass);
InitializeDataView(env, objFuncDynclass);
InitializeSharedArrayBuffer(env, objFuncDynclass);
JSHandle<JSHClass> argumentsDynclass = factory_->CreateJSArguments();
env->SetArgumentsClass(thread_, argumentsDynclass);
@ -2225,6 +2228,51 @@ void Builtins::InitializeReflect(const JSHandle<GlobalEnv> &env,
env->SetReflectFunction(thread_, reflectObject.GetTaggedValue());
}
void Builtins::InitializeSharedArrayBuffer(const JSHandle<GlobalEnv> &env,
const JSHandle<JSHClass> &objFuncDynclass) const
{
[[maybe_unused]] EcmaHandleScope scope(thread_);
// SharedArrayBuffer.prototype
JSHandle<JSObject> sharedArrayBufferFuncPrototype = factory_->NewJSObject(objFuncDynclass);
JSHandle<JSTaggedValue> sharedArrayBufferFuncPrototypeValue(sharedArrayBufferFuncPrototype);
// SharedArrayBuffer.prototype_or_dynclass
JSHandle<JSHClass> sharedArrayBufferFuncInstanceDynclass =
factory_->NewEcmaDynClass(
JSArrayBuffer::SIZE, JSType::JS_SHARED_ARRAY_BUFFER, sharedArrayBufferFuncPrototypeValue);
// SharedArrayBuffer = new Function()
JSHandle<JSObject> SharedArrayBufferFunction(NewBuiltinConstructor(env, sharedArrayBufferFuncPrototype,
SharedArrayBuffer::SharedArrayBufferConstructor, "SharedArrayBuffer", FunctionLength::ONE));
JSHandle<JSFunction>(SharedArrayBufferFunction)
->SetFunctionPrototype(thread_, sharedArrayBufferFuncInstanceDynclass.GetTaggedValue());
// SharedArrayBuffer prototype method
SetFunction(env, sharedArrayBufferFuncPrototype, "slice", SharedArrayBuffer::Slice, FunctionLength::TWO);
// SharedArrayBuffer method
SetFunction(env, SharedArrayBufferFunction,
"IsSharedArrayBuffer", SharedArrayBuffer::IsSharedArrayBuffer, FunctionLength::ONE);
// 25.2.3.2 get SharedArrayBuffer [ @@species ]
JSHandle<JSTaggedValue> speciesSymbol = env->GetSpeciesSymbol();
JSHandle<JSTaggedValue> speciesGetter =
CreateGetter(env, SharedArrayBuffer::Species, "[Symbol.species]", FunctionLength::ZERO);
SetGetter(JSHandle<JSObject>(SharedArrayBufferFunction), speciesSymbol, speciesGetter);
// 25.2.4.1 get SharedArrayBuffer.prototype.byteLength
JSHandle<JSTaggedValue> lengthGetter =
CreateGetter(env, SharedArrayBuffer::GetByteLength, "byteLength", FunctionLength::ZERO);
JSHandle<JSTaggedValue> lengthKey(factory_->NewFromCanBeCompressString("byteLength"));
SetGetter(sharedArrayBufferFuncPrototype, lengthKey, lengthGetter);
// 25.2.4.4 SharedArrayBuffer.prototype [ @@toStringTag ]
SetStringTagSymbol(env, sharedArrayBufferFuncPrototype, "SharedArrayBuffer");
env->SetSharedArrayBufferFunction(thread_, SharedArrayBufferFunction.GetTaggedValue());
}
void Builtins::InitializePromise(const JSHandle<GlobalEnv> &env, const JSHandle<JSHClass> &promiseFuncDynclass)
{
[[maybe_unused]] EcmaHandleScope scope(thread_);

View File

@ -158,6 +158,8 @@ private:
void InitializeArrayBuffer(const JSHandle<GlobalEnv> &env, const JSHandle<JSHClass> &objFuncDynclass) const;
void InitializeSharedArrayBuffer(const JSHandle<GlobalEnv> &env, const JSHandle<JSHClass> &objFuncDynclass) const;
void InitializeDataView(const JSHandle<GlobalEnv> &env, const JSHandle<JSHClass> &objFuncDynclass) const;
void InitializeProxy(const JSHandle<GlobalEnv> &env);

View File

@ -43,7 +43,7 @@ JSTaggedValue BuiltinsDataView::DataViewConstructor(EcmaRuntimeCallInfo *argv)
THROW_TYPE_ERROR_AND_RETURN(thread, "buffer is not Object", JSTaggedValue::Exception());
}
// 3. If buffer does not have an [[ArrayBufferData]] internal slot, throw a TypeError exception.
if (!bufferHandle->IsArrayBuffer()) {
if (!bufferHandle->IsArrayBuffer() && !bufferHandle->IsSharedArrayBuffer()) {
THROW_TYPE_ERROR_AND_RETURN(thread, "buffer is not ArrayBuffer", JSTaggedValue::Exception());
}
JSHandle<JSTaggedValue> offsetHandle = GetCallArg(argv, 1);

View File

@ -0,0 +1,257 @@
/*
* 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_sharedarraybuffer.h"
#include "ecmascript/ecma_macros.h"
#include "ecmascript/ecma_vm.h"
#include "ecmascript/global_env.h"
#include "ecmascript/internal_call_params.h"
#include "ecmascript/js_arraybuffer.h"
#include "ecmascript/js_object-inl.h"
#include "ecmascript/js_tagged_number.h"
#include "ecmascript/js_tagged_value-inl.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/object_factory.h"
#include "securec.h"
namespace panda::ecmascript::builtins {
// 25.2.2.1 SharedArrayBuffer ( [ length ] )
JSTaggedValue BuiltinsSharedArrayBuffer::SharedArrayBufferConstructor(EcmaRuntimeCallInfo *argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), SharedArrayBuffer, Constructor);
JSThread *thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
// 1. If NewTarget is undefined, throw a TypeError exception.
if (newTarget->IsUndefined()) {
THROW_TYPE_ERROR_AND_RETURN(thread, "newtarget is undefined", JSTaggedValue::Exception());
}
JSHandle<JSTaggedValue> lengthHandle = GetCallArg(argv, 0);
// 2. Let byteLength be ? ToIndex(length).
JSTaggedNumber lenNum = JSTaggedValue::ToIndex(thread, lengthHandle);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
double byteLength = lenNum.GetNumber();
// 3. Return ? AllocateSharedArrayBuffer(NewTarget, byteLength).
return AllocateSharedArrayBuffer(thread, newTarget, byteLength);
}
// 25.2.1.2 IsSharedArrayBuffer ( obj )
JSTaggedValue BuiltinsSharedArrayBuffer::IsSharedArrayBuffer(EcmaRuntimeCallInfo *argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(thread, SharedArrayBuffer, IsSharedArrayBuffer);
[[maybe_unused]] EcmaHandleScope handleScope(argv->GetThread());
JSHandle<JSTaggedValue> arg = GetCallArg(argv, 0);
// 1. If Type(arg) is not Object,and it not has an [[ArrayBufferData]] internal slot return false.
if (!arg->IsECMAObject()) {
return BuiltinsSharedArrayBuffer::GetTaggedBoolean(false);
}
if (!arg->IsSharedArrayBuffer()) {
return BuiltinsSharedArrayBuffer::GetTaggedBoolean(false);
}
// 2. Let bufferData be obj.[[ArrayBufferData]].
JSHandle<JSArrayBuffer> buffer(arg);
JSTaggedValue bufferdata = buffer->GetArrayBufferData();
// 3. If bufferData is null, return false.
if (bufferdata == JSTaggedValue::Null()) {
return BuiltinsSharedArrayBuffer::GetTaggedBoolean(false);
}
// 4. If this ArrayBuffer is not shared, return false.
if (buffer->GetShared() == false) {
return BuiltinsSharedArrayBuffer::GetTaggedBoolean(false);
}
return BuiltinsSharedArrayBuffer::GetTaggedBoolean(true);
}
bool BuiltinsSharedArrayBuffer::IsShared(JSTaggedValue arrayBuffer)
{
if (!arrayBuffer.IsSharedArrayBuffer()) {
return false;
}
JSArrayBuffer *buffer = JSArrayBuffer::Cast(arrayBuffer.GetTaggedObject());
JSTaggedValue dataSlot = buffer->GetArrayBufferData();
// 2. If arrayBuffers [[ArrayBufferData]] internal slot is null, return false.
if (dataSlot.IsNull()) {
return false;
}
// 3. If this ArrayBuffer is not shared, return false.
return buffer->GetShared();
}
// 25.2.1.1 AllocateSharedArrayBuffer ( constructor, byteLength )
JSTaggedValue BuiltinsSharedArrayBuffer::AllocateSharedArrayBuffer(
JSThread *thread, const JSHandle<JSTaggedValue> &newTarget, double byteLength)
{
BUILTINS_API_TRACE(thread, SharedArrayBuffer, AllocateSharedArrayBuffer);
/**
* 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%SharedArrayBuffer.prototype%",
* «[[ArrayBufferData]], [[ArrayBufferByteLength]] »).
* */
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> shaArrBufFunc = env->GetSharedArrayBufferFunction();
JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(shaArrBufFunc), newTarget);
// 2. ReturnIfAbrupt
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
// 3. Assert: byteLength is a positive integer.
ASSERT(JSTaggedValue(byteLength).IsInteger());
ASSERT(byteLength >= 0);
// 4. Let block be CreateSharedByteDataBlock(byteLength).
if (byteLength > INT_MAX) {
THROW_RANGE_ERROR_AND_RETURN(thread, "Out of range", JSTaggedValue::Exception());
}
JSHandle<JSArrayBuffer> sharedArrayBuffer(obj);
// 6. Set objs [[ArrayBufferData]] internal slot to block.
factory->NewJSSharedArrayBufferData(sharedArrayBuffer, byteLength);
// 7. Set objs [[ArrayBufferByteLength]] internal slot to byteLength.
sharedArrayBuffer->SetArrayBufferByteLength(static_cast<uint32_t>(byteLength));
// 8. Return obj.
return sharedArrayBuffer.GetTaggedValue();
}
// 25.2.3.2 get SharedArrayBuffer [ @@species ]
JSTaggedValue BuiltinsSharedArrayBuffer::Species(EcmaRuntimeCallInfo *argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), SharedArrayBuffer, Species);
// 1. Return the this value.
return GetThis(argv).GetTaggedValue();
}
// 25.2.4.1 get SharedArrayBuffer.prototype.byteLength
JSTaggedValue BuiltinsSharedArrayBuffer::GetByteLength(EcmaRuntimeCallInfo *argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), SharedArrayBuffer, GetByteLength);
JSThread *thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
// 1. Let O be the this value.
JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
// 2. If Type(O) is not Object, throw a TypeError exception.
if (!thisHandle->IsECMAObject()) {
THROW_TYPE_ERROR_AND_RETURN(thread, "this value is not an object", JSTaggedValue::Exception());
}
// 3. If O does not have an [[ArrayBufferData]] internal slot, throw a TypeError exception.
if (!thisHandle->IsSharedArrayBuffer()) {
THROW_TYPE_ERROR_AND_RETURN(thread, "don't have internal slot", JSTaggedValue::Exception());
}
JSHandle<JSArrayBuffer> shaArrBuf(thisHandle);
// 5. Let length be the value of Os [[SharedArrayBufferByteLength]] internal slot.
uint32_t length = shaArrBuf->GetArrayBufferByteLength();
// 6. Return length.
return JSTaggedValue(length);
}
// 25.2.4.3 SharedArrayBuffer.prototype.slice ( start, end )
JSTaggedValue BuiltinsSharedArrayBuffer::Slice(EcmaRuntimeCallInfo *argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), SharedArrayBuffer, Slice);
JSThread *thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
// 1. Let O be the this value.
JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
// 2. If Type(O) is not Object, throw a TypeError exception.
if (!thisHandle->IsECMAObject()) {
THROW_TYPE_ERROR_AND_RETURN(thread, "this value is not an object", JSTaggedValue::Exception());
}
JSHandle<JSArrayBuffer> shaArrBuf(thisHandle);
// 3. If O does not have an [[ArrayBufferData]] internal slot, throw a TypeError exception.
if (!thisHandle->IsSharedArrayBuffer()) {
THROW_TYPE_ERROR_AND_RETURN(thread, "don't have internal slot", JSTaggedValue::Exception());
}
// 4. If IsSharedArrayBuffer(O) is false, throw a TypeError exception.
if (!IsShared(thisHandle.GetTaggedValue())) {
THROW_TYPE_ERROR_AND_RETURN(thread, "this value not IsSharedArrayBuffer", JSTaggedValue::Exception());
}
// 5. Let len be the value of Os [[ArrayBufferByteLength]] internal slot.
int32_t len = shaArrBuf->GetArrayBufferByteLength();
JSHandle<JSTaggedValue> startHandle = GetCallArg(argv, 0);
// 6. Let relativeStart be ToInteger(start).
JSTaggedNumber relativeStart = JSTaggedValue::ToInteger(thread, startHandle);
// 7. ReturnIfAbrupt(relativeStart).
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
int32_t start = base::NumberHelper::DoubleInRangeInt32(relativeStart.GetNumber());
int32_t end;
int32_t first;
int32_t last;
// 8. If relativeStart < 0, let first be max((len + relativeStart),0); else let first be min(relativeStart, len).
if (start < 0) {
first = std::max((len + start), 0);
} else {
first = std::min(start, len);
}
// 9. If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end).
JSHandle<JSTaggedValue> endHandle = GetCallArg(argv, 1);
if (endHandle->IsUndefined()) {
end = len;
} else {
JSTaggedNumber relativeEnd = JSTaggedValue::ToInteger(thread, endHandle);
// 10. ReturnIfAbrupt(relativeEnd).
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
end = base::NumberHelper::DoubleInRangeInt32(relativeEnd.GetNumber());
}
// 11. If relativeEnd < 0, let final be max((len + relativeEnd),0); else let final be min(relativeEnd, len).
last = end < 0 ? std::max((len + end), 0) : std::min(end, len);
// 12. Let newLen be max(final-first,0).
uint32_t newLen = std::max((last - first), 0);
// 13. Let ctor be SpeciesConstructor(O, %SharedArrayBuffer%).
JSHandle<JSTaggedValue> defaultConstructor = env->GetSharedArrayBufferFunction();
JSHandle<JSObject> objHandle(thisHandle);
JSHandle<JSTaggedValue> constructor = JSObject::SpeciesConstructor(thread, objHandle, defaultConstructor);
// 14. ReturnIfAbrupt(ctor).
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
// 15. Let new be Construct(ctor, «newLen»).
JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
InternalCallParams *arguments = thread->GetInternalCallParams();
arguments->MakeArgv(JSTaggedValue(newLen));
JSTaggedValue taggedNewArrBuf = JSFunction::Construct(thread, constructor, 1, arguments->GetArgv(), undefined);
JSHandle<JSTaggedValue> newArrBuf(thread, taggedNewArrBuf);
// 16. ReturnIfAbrupt(new).
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
// 17. If new does not have an [[ArrayBufferData]] internal slot, throw a TypeError exception.
if (!newArrBuf->IsSharedArrayBuffer()) {
THROW_TYPE_ERROR_AND_RETURN(thread, "don't have bufferdata internal slot", JSTaggedValue::Exception());
}
// 18. If IsSharedArrayBuffer(new) is false, throw a TypeError exception.
if (!IsShared(newArrBuf.GetTaggedValue())) {
THROW_TYPE_ERROR_AND_RETURN(thread, "new arrayBuffer not IsSharedArrayBuffer", JSTaggedValue::Exception());
}
// 19. If SameValue(new, O) is true, throw a TypeError exception.
if (JSTaggedValue::SameValue(newArrBuf.GetTaggedValue(), thisHandle.GetTaggedValue())) {
THROW_TYPE_ERROR_AND_RETURN(thread, "value of new arraybuffer and this is same", JSTaggedValue::Exception());
}
JSHandle<JSArrayBuffer> newJsShaArrBuf(newArrBuf);
// 20. If the value of news [[ArrayBufferByteLength]] internal slot < newLen, throw a TypeError exception.
uint32_t newArrBufLen = newJsShaArrBuf->GetArrayBufferByteLength();
if (newArrBufLen < newLen) {
THROW_TYPE_ERROR_AND_RETURN(thread, "new array buffer length smaller than newlen", JSTaggedValue::Exception());
}
if (newLen > 0) {
// 23. Let fromBuf be the value of Os [[ArrayBufferData]] internal slot.
JSTaggedValue from = shaArrBuf->GetArrayBufferData();
// 24. Let toBuf be the value of news [[ArrayBufferData]] internal slot.
JSTaggedValue to = newJsShaArrBuf->GetArrayBufferData();
// 25. Perform CopyDataBlockBytes(toBuf, fromBuf, first, newLen).
JSArrayBuffer::CopyDataBlockBytes(to, from, first, newLen);
}
// Return new.
return newArrBuf.GetTaggedValue();
}
} // namespace panda::ecmascript::builtins

View File

@ -0,0 +1,45 @@
/*
* 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_SHAREDARRAYBUFFER_H
#define ECMASCRIPT_BUILTINS_BUILTINS_SHAREDARRAYBUFFER_H
#include "ecmascript/base/builtins_base.h"
#include "ecmascript/base/number_helper.h"
#include "ecmascript/js_dataview.h"
namespace panda::ecmascript::builtins {
class BuiltinsSharedArrayBuffer : public base::BuiltinsBase {
public:
// 25.2.2.1 SharedArrayBuffer ( [ length ] )
static JSTaggedValue SharedArrayBufferConstructor(EcmaRuntimeCallInfo *argv);
// 25.2.1.2 IsSharedArrayBuffer ( obj )
static JSTaggedValue IsSharedArrayBuffer(EcmaRuntimeCallInfo *argv);
// 24.2.3.2 get SharedArrayBuffer [ @@species ]
static JSTaggedValue Species(EcmaRuntimeCallInfo *argv);
// 25.2.4.1 get SharedArrayBuffer.prototype.byteLength
static JSTaggedValue GetByteLength(EcmaRuntimeCallInfo *argv);
// 25.2.4.3 SharedArrayBuffer.prototype.slice ( start, end )
static JSTaggedValue Slice(EcmaRuntimeCallInfo *argv);
static bool IsShared(JSTaggedValue arrayBuffer);
private:
// 25.2.1.1 AllocateSharedArrayBuffer ( constructor, byteLength )
static JSTaggedValue AllocateSharedArrayBuffer(JSThread *thread, const JSHandle<JSTaggedValue> &newTarget,
double byteLength);
};
} // namespace panda::ecmascript::builtins
#endif // ECMASCRIPT_BUILTINS_BUILTINS_SHAREDARRAYBUFFER_H

View File

@ -262,6 +262,8 @@ CString *HeapSnapShot::GenerateNodeName(TaggedObject *entry)
return GetString("StringIterator");
case JSType::JS_ARRAY_BUFFER:
return GetString("ArrayBuffer");
case JSType::JS_SHARED_ARRAY_BUFFER:
return GetString("SharedArrayBuffer");
case JSType::JS_PROXY_REVOC_FUNCTION:
return GetString("ProxyRevocFunction");
case JSType::PROMISE_REACTIONS:

View File

@ -197,6 +197,8 @@ CString JSHClass::DumpJSType(JSType type)
return "StringIterator";
case JSType::JS_ARRAY_BUFFER:
return "ArrayBuffer";
case JSType::JS_SHARED_ARRAY_BUFFER:
return "SharedArrayBuffer";
case JSType::JS_PROXY_REVOC_FUNCTION:
return "ProxyRevocFunction";
case JSType::PROMISE_REACTIONS:
@ -524,6 +526,9 @@ static void DumpObject(TaggedObject *obj, std::ostream &os)
case JSType::JS_ARRAY_BUFFER:
JSArrayBuffer::Cast(obj)->Dump(os);
break;
case JSType::JS_SHARED_ARRAY_BUFFER:
JSArrayBuffer::Cast(obj)->Dump(os);
break;
case JSType::PROMISE_REACTIONS:
PromiseReaction::Cast(obj)->Dump(os);
break;
@ -1579,6 +1584,8 @@ void GlobalEnv::Dump(std::ostream &os) const
GetInt16ArrayFunction().GetTaggedValue().Dump(os);
os << " - ArrayBufferFunction: ";
GetArrayBufferFunction().GetTaggedValue().Dump(os);
os << " - SharedArrayBufferFunction: ";
GetSharedArrayBufferFunction().GetTaggedValue().Dump(os);
os << " - SymbolFunction: ";
GetSymbolFunction().GetTaggedValue().Dump(os);
os << " - RangeErrorFunction: ";
@ -2793,6 +2800,9 @@ static void DumpObject(TaggedObject *obj,
case JSType::JS_ARRAY_BUFFER:
JSArrayBuffer::Cast(obj)->DumpForSnapshot(vec);
return;
case JSType::JS_SHARED_ARRAY_BUFFER:
JSArrayBuffer::Cast(obj)->DumpForSnapshot(vec);
return;
case JSType::JS_PROXY_REVOC_FUNCTION:
JSProxyRevocFunction::Cast(obj)->DumpForSnapshot(vec);
return;
@ -3407,6 +3417,8 @@ void GlobalEnv::DumpForSnapshot(std::vector<std::pair<CString, JSTaggedValue>> &
vec.push_back(std::make_pair(CString("Float32ArrayFunction"), GetFloat32ArrayFunction().GetTaggedValue()));
vec.push_back(std::make_pair(CString("Float64ArrayFunction"), GetFloat64ArrayFunction().GetTaggedValue()));
vec.push_back(std::make_pair(CString("ArrayBufferFunction"), GetArrayBufferFunction().GetTaggedValue()));
vec.push_back(
std::make_pair(CString("SharedArrayBufferFunction"), GetSharedArrayBufferFunction().GetTaggedValue()));
vec.push_back(std::make_pair(CString("SymbolFunction"), GetSymbolFunction().GetTaggedValue()));
vec.push_back(std::make_pair(CString("RangeErrorFunction"), GetRangeErrorFunction().GetTaggedValue()));
vec.push_back(std::make_pair(CString("ReferenceErrorFunction"), GetReferenceErrorFunction().GetTaggedValue()));

View File

@ -54,6 +54,7 @@ class JSThread;
V(JSTaggedValue, BigInt64ArrayFunction, BIGINT64_ARRAY_FUNCTION_INDEX) \
V(JSTaggedValue, BigUint64ArrayFunction, BIGUINT64_ARRAY_FUNCTION_INDEX) \
V(JSTaggedValue, ArrayBufferFunction, ARRAY_BUFFER_FUNCTION_INDEX) \
V(JSTaggedValue, SharedArrayBufferFunction, SHAREDARRAY_BUFFER_FUNCTION_INDEX) \
V(JSTaggedValue, ArrayProtoValuesFunction, ARRAY_PROTO_VALUES_FUNCTION_INDEX) \
V(JSTaggedValue, DataViewFunction, DATA_VIEW_FUNCTION_INDEX) \
V(JSTaggedValue, SymbolFunction, SYMBOL_FUNCTION_INDEX) \

View File

@ -114,6 +114,7 @@ class ProtoChangeDetails;
JS_DISPLAYNAMES, /* ///////////////////////////////////////////////////////////////////////////////-PADDING */ \
\
JS_ARRAY_BUFFER, /* ///////////////////////////////////////////////////////////////////////////////-PADDING */ \
JS_SHARED_ARRAY_BUFFER, /* ////////////////////////////////////////////////////////////////////////-PADDING */ \
JS_PROMISE, /* ///////////////////////////////////////////////////////////////////////////////-PADDING */ \
JS_DATA_VIEW, /* /////////////////////////////////////////////////////////////////////////////////////// */ \
JS_ARGUMENTS, /* //////////////////////////////////////////////////////////////////////////////////-PADDING */ \
@ -733,6 +734,11 @@ public:
return GetObjectType() == JSType::JS_ARRAY_BUFFER;
}
inline bool IsSharedArrayBuffer() const
{
return GetObjectType() == JSType::JS_SHARED_ARRAY_BUFFER;
}
inline bool IsDataView() const
{
return GetObjectType() == JSType::JS_DATA_VIEW;

View File

@ -27,6 +27,7 @@
#include "ecmascript/js_set.h"
#include "ecmascript/js_typed_array.h"
#include "ecmascript/linked_hash_table-inl.h"
#include "ecmascript/sharedMemoryManaged/sharedmemorymanager.h"
#include "libpandabase/mem/mem.h"
#include "securec.h"
@ -292,6 +293,7 @@ bool JSSerializer::WriteTaggedObject(const JSHandle<JSTaggedValue> &value)
case JSType::JS_BIGUINT64_ARRAY:
return WriteJSTypedArray(value, SerializationUID::JS_BIGUINT64_ARRAY);
case JSType::JS_ARRAY_BUFFER:
case JSType::JS_SHARED_ARRAY_BUFFER:
return WriteJSArrayBuffer(value);
case JSType::STRING:
return WriteEcmaString(value);
@ -602,8 +604,15 @@ bool JSSerializer::WriteJSArrayBuffer(const JSHandle<JSTaggedValue> &value)
return false;
}
if (!WriteType(SerializationUID::JS_ARRAY_BUFFER)) {
return false;
bool shared = arrayBuffer->GetShared();
if (shared) {
if (!WriteType(SerializationUID::JS_SHARED_ARRAY_BUFFER)) {
return false;
}
} else {
if (!WriteType(SerializationUID::JS_ARRAY_BUFFER)) {
return false;
}
}
// Write Accessors(ArrayBufferByteLength)
@ -614,7 +623,6 @@ bool JSSerializer::WriteJSArrayBuffer(const JSHandle<JSTaggedValue> &value)
}
// write Accessor shared which indicate the C memory is shared
bool shared = arrayBuffer->GetShared();
if (!WriteBoolean(shared)) {
bufferSize_ = oldSize;
return false;
@ -623,6 +631,7 @@ bool JSSerializer::WriteJSArrayBuffer(const JSHandle<JSTaggedValue> &value)
if (shared) {
JSHandle<JSNativePointer> np(thread_, arrayBuffer->GetArrayBufferData());
void *buffer = np->GetExternalPointer();
JSSharedMemoryManager::GetInstance()->CreateOrLoad(&buffer, arrayLength);
uint64_t bufferAddr = (uint64_t)buffer;
if (!WriteRawData(&bufferAddr, sizeof(uint64_t))) {
bufferSize_ = oldSize;
@ -895,6 +904,7 @@ JSHandle<JSTaggedValue> JSDeserializer::DeserializeJSTaggedValue()
return ReadJSTypedArray(SerializationUID::JS_BIGUINT64_ARRAY);
case SerializationUID::NATIVE_FUNCTION_POINTER:
return ReadNativeFunctionPointer();
case SerializationUID::JS_SHARED_ARRAY_BUFFER:
case SerializationUID::JS_ARRAY_BUFFER:
return ReadJSArrayBuffer();
case SerializationUID::TAGGED_OBJECT_REFERNCE:
@ -1243,7 +1253,7 @@ JSHandle<JSTaggedValue> JSDeserializer::ReadJSArrayBuffer()
if (shared) {
uint64_t *bufferAddr = reinterpret_cast<uint64_t*>(GetBuffer(sizeof(uint64_t)));
void* bufferData = ToVoidPtr(*bufferAddr);
JSHandle<JSArrayBuffer> arrayBuffer = factory_->NewJSArrayBuffer(bufferData, arrayLength, nullptr, nullptr);
JSHandle<JSArrayBuffer> arrayBuffer = factory_->NewJSSharedArrayBuffer(bufferData, arrayLength);
arrayBufferTag = JSHandle<JSTaggedValue>::Cast(arrayBuffer);
referenceMap_.insert(std::pair(objectId_++, arrayBufferTag));
} else {

View File

@ -54,6 +54,7 @@ enum class SerializationUID : uint8_t {
JS_MAP,
JS_ARRAY,
JS_ARRAY_BUFFER,
JS_SHARED_ARRAY_BUFFER,
// TypedArray begin
JS_UINT8_ARRAY,
JS_UINT8_CLAMPED_ARRAY,

View File

@ -980,6 +980,11 @@ inline bool JSTaggedValue::IsArrayBuffer() const
return IsHeapObject() && GetTaggedObject()->GetClass()->IsArrayBuffer();
}
inline bool JSTaggedValue::IsSharedArrayBuffer() const
{
return IsHeapObject() && GetTaggedObject()->GetClass()->IsSharedArrayBuffer();
}
inline bool JSTaggedValue::IsDataView() const
{
return IsHeapObject() && GetTaggedObject()->GetClass()->IsDataView();

View File

@ -293,6 +293,7 @@ public:
bool IsForinIterator() const;
bool IsStringIterator() const;
bool IsArrayBuffer() const;
bool IsSharedArrayBuffer() const;
bool IsJSSetIterator() const;
bool IsJSMapIterator() const;

View File

@ -168,6 +168,9 @@ void ObjectXRay::VisitObjectBody(TaggedObject *object, JSHClass *klass, const Ec
case JSType::JS_ARRAY_BUFFER:
JSArrayBuffer::Cast(object)->VisitRangeSlot(visitor);
break;
case JSType::JS_SHARED_ARRAY_BUFFER:
JSArrayBuffer::Cast(object)->VisitRangeSlot(visitor);
break;
case JSType::JS_PROMISE:
JSPromise::Cast(object)->VisitRangeSlot(visitor);
break;

View File

@ -84,6 +84,7 @@
#include "ecmascript/module/js_module_namespace.h"
#include "ecmascript/module/js_module_source_text.h"
#include "ecmascript/record.h"
#include "ecmascript/sharedMemoryManaged/sharedmemorymanager.h"
#include "ecmascript/symbol_table-inl.h"
#include "ecmascript/tagged_tree-inl.h"
#include "ecmascript/template_map.h"
@ -172,7 +173,23 @@ void ObjectFactory::NewJSArrayBufferData(const JSHandle<JSArrayBuffer> &array, i
}
JSHandle<JSNativePointer> pointer = NewJSNativePointer(newData, NativeAreaAllocator::FreeBufferFunc,
vm_->GetNativeAreaAllocator());
array->SetArrayBufferData(thread_, pointer.GetTaggedValue());
array->SetArrayBufferData(thread_, pointer);
}
void ObjectFactory::NewJSSharedArrayBufferData(const JSHandle<JSArrayBuffer> &array, int32_t length)
{
if (length == 0) {
return;
}
void *newData = nullptr;
JSSharedMemoryManager::GetInstance()->CreateOrLoad(&newData, length);
if (memset_s(newData, length, 0, length) != EOK) {
LOG_ECMA(FATAL) << "memset_s failed";
UNREACHABLE();
}
JSHandle<JSNativePointer> pointer = NewJSNativePointer(newData, JSSharedMemoryManager::RemoveSharedMemory,
JSSharedMemoryManager::GetInstance());
array->SetArrayBufferData(thread_, pointer);
}
JSHandle<JSArrayBuffer> ObjectFactory::NewJSArrayBuffer(int32_t length)
@ -234,6 +251,39 @@ JSHandle<JSDataView> ObjectFactory::NewJSDataView(JSHandle<JSArrayBuffer> buffer
return arrayBuffer;
}
JSHandle<JSArrayBuffer> ObjectFactory::NewJSSharedArrayBuffer(int32_t length)
{
JSHandle<GlobalEnv> env = vm_->GetGlobalEnv();
JSHandle<JSFunction> constructor(env->GetSharedArrayBufferFunction());
JSHandle<JSTaggedValue> newTarget(constructor);
JSHandle<JSArrayBuffer> sharedArrayBuffer(NewJSObjectByConstructor(constructor, newTarget));
sharedArrayBuffer->SetArrayBufferByteLength(length);
if (length > 0) {
NewJSSharedArrayBufferData(sharedArrayBuffer, length);
sharedArrayBuffer->SetShared(true);
}
return sharedArrayBuffer;
}
JSHandle<JSArrayBuffer> ObjectFactory::NewJSSharedArrayBuffer(void *buffer, int32_t length)
{
JSHandle<GlobalEnv> env = vm_->GetGlobalEnv();
JSHandle<JSFunction> constructor(env->GetSharedArrayBufferFunction());
JSHandle<JSTaggedValue> newTarget(constructor);
JSHandle<JSArrayBuffer> sharedArrayBuffer(NewJSObjectByConstructor(constructor, newTarget));
length = buffer == nullptr ? 0 : length;
sharedArrayBuffer->SetArrayBufferByteLength(length);
if (length > 0) {
JSHandle<JSNativePointer> pointer = NewJSNativePointer(buffer, JSSharedMemoryManager::RemoveSharedMemory,
JSSharedMemoryManager::GetInstance());
sharedArrayBuffer->SetArrayBufferData(thread_, pointer);
sharedArrayBuffer->SetShared(true);
}
return sharedArrayBuffer;
}
void ObjectFactory::NewJSRegExpByteCodeData(const JSHandle<JSRegExp> &regexp, void *buffer, size_t size)
{
if (buffer == nullptr) {
@ -782,6 +832,11 @@ JSHandle<JSObject> ObjectFactory::NewJSObjectByConstructor(const JSHandle<JSFunc
JSArrayBuffer::Cast(*obj)->SetArrayBufferByteLength(0);
JSArrayBuffer::Cast(*obj)->ClearBitField();
break;
case JSType::JS_SHARED_ARRAY_BUFFER:
JSArrayBuffer::Cast(*obj)->SetArrayBufferData(thread_, JSTaggedValue::Undefined());
JSArrayBuffer::Cast(*obj)->SetArrayBufferByteLength(0);
JSArrayBuffer::Cast(*obj)->SetShared(true);
break;
case JSType::JS_PROMISE:
JSPromise::Cast(*obj)->SetPromiseState(PromiseState::PENDING);
JSPromise::Cast(*obj)->SetPromiseResult(thread_, JSTaggedValue::Undefined());

View File

@ -325,6 +325,12 @@ public:
JSHandle<JSDataView> NewJSDataView(JSHandle<JSArrayBuffer> buffer, uint32_t offset, uint32_t length);
void NewJSSharedArrayBufferData(const JSHandle<JSArrayBuffer> &array, int32_t length);
JSHandle<JSArrayBuffer> NewJSSharedArrayBuffer(int32_t length);
JSHandle<JSArrayBuffer> NewJSSharedArrayBuffer(void *buffer, int32_t length);
void NewJSRegExpByteCodeData(const JSHandle<JSRegExp> &regexp, void *buffer, size_t size);
template<typename T, typename S>

View File

@ -270,6 +270,12 @@ namespace panda::ecmascript {
V(ArrayBuffer, SetValueInBuffer) \
V(ArrayBuffer, CloneArrayBuffer) \
V(ArrayBuffer, AllocateArrayBuffer) \
V(SharedArrayBuffer, Constructor) \
V(SharedArrayBuffer, Slice) \
V(SharedArrayBuffer, AllocateSharedArrayBuffer) \
V(SharedArrayBuffer, IsSharedArrayBuffer) \
V(SharedArrayBuffer, Species) \
V(SharedArrayBuffer, GetByteLength) \
V(AsyncFunction, Constructor) \
V(Boolean, Constructor) \
V(Boolean, ThisBooleanValue) \

View File

@ -0,0 +1,117 @@
/*
* 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/sharedMemoryManaged/sharedmemorymanager.h"
namespace panda::ecmascript {
static constexpr size_t MALLOC_SIZE_LIMIT = 2147483648; // Max internal memory used by the VM declared in options
JSSharedMemoryManager::~JSSharedMemoryManager()
{
os::memory::LockHolder lock(jsSharedMemoryLock_);
auto iter = loadedJSSharedMemory_.begin();
while (iter != loadedJSSharedMemory_.end()) {
const void *pointer = ToVoidPtr(iter->first);
FreeBuffer(const_cast<void *>(pointer));
iter = loadedJSSharedMemory_.erase(iter);
}
}
void JSSharedMemoryManager::CreateOrLoad(void **pointer, size_t size)
{
if (*pointer != nullptr) {
if (loadedJSSharedMemory_.find((uint64_t)*pointer) != loadedJSSharedMemory_.end()) {
IncreaseRefSharedMemory(*pointer);
}
return;
}
*pointer = AllocateBuffer(size);
InsertSharedMemory(*pointer);
}
void JSSharedMemoryManager::InsertSharedMemory(const void *pointer)
{
os::memory::LockHolder lock(jsSharedMemoryLock_);
if (loadedJSSharedMemory_.find((uint64_t)pointer) == loadedJSSharedMemory_.end()) {
loadedJSSharedMemory_[(uint64_t)pointer] = 1;
}
}
void JSSharedMemoryManager::IncreaseRefSharedMemory(const void *pointer)
{
os::memory::LockHolder lock(jsSharedMemoryLock_);
if (loadedJSSharedMemory_.find((uint64_t)pointer) != loadedJSSharedMemory_.end()) {
loadedJSSharedMemory_[(uint64_t)pointer]++;
}
}
void JSSharedMemoryManager::DecreaseRefSharedMemory(const void *pointer)
{
os::memory::LockHolder lock(jsSharedMemoryLock_);
auto iter = loadedJSSharedMemory_.find((uint64_t)pointer);
if (iter != loadedJSSharedMemory_.end()) {
if (iter->second > 1) {
iter->second--;
return;
}
loadedJSSharedMemory_.erase(iter);
FreeBuffer(const_cast<void *>(pointer));
}
}
void *JSSharedMemoryManager::AllocateBuffer(size_t size)
{
if (size == 0) {
LOG_ECMA_MEM(FATAL) << "size must have a size bigger than 0";
UNREACHABLE();
}
if (size >= MALLOC_SIZE_LIMIT) {
LOG_ECMA_MEM(FATAL) << "size must be less than the maximum";
UNREACHABLE();
}
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
void *ptr = malloc(size);
if (ptr == nullptr) {
LOG_ECMA_MEM(FATAL) << "malloc failed";
UNREACHABLE();
}
#if ECMASCRIPT_ENABLE_ZAP_MEM
if (memset_s(ptr, size, INVALID_VALUE, size) != EOK) {
LOG_ECMA_MEM(FATAL) << "memset failed";
UNREACHABLE();
}
#endif
return ptr;
}
void JSSharedMemoryManager::FreeBuffer(void *mem)
{
if (mem == nullptr) {
return;
}
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
free(mem);
}
void JSSharedMemoryManager::RemoveSharedMemory(void *pointer, void *data)
{
if (pointer == nullptr || data == nullptr) {
return;
}
// dec ref in menorymanager
JSSharedMemoryManager *jsSharedMemoryManager = static_cast<JSSharedMemoryManager *>(data);
jsSharedMemoryManager->DecreaseRefSharedMemory(pointer);
}
} // namespace panda::ecmascript

View File

@ -0,0 +1,50 @@
/*
* 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_SHARED_MEMORY_MANAGER_MANAGER_H
#define ECMASCRIPT_SHARED_MEMORY_MANAGER_MANAGER_H
#include "ecmascript/tooling/js_pt_extractor.h"
#include "libpandabase/utils/logger.h"
#include "os/mutex.h"
namespace panda {
class EcmaVm;
namespace ecmascript {
class JSSharedMemoryManager {
public:
PUBLIC_API ~JSSharedMemoryManager();
static JSSharedMemoryManager *GetInstance()
{
static JSSharedMemoryManager jsSharedMemoryManager;
return &jsSharedMemoryManager;
}
void CreateOrLoad(void **pointer, size_t size);
static void RemoveSharedMemory(void *pointer, void *data);
private:
JSSharedMemoryManager() = default;
void InsertSharedMemory(const void *pointer);
void IncreaseRefSharedMemory(const void *pointer);
void DecreaseRefSharedMemory(const void *pointer);
void FreeBuffer(void *mem);
void *AllocateBuffer(size_t size);
os::memory::RecursiveMutex jsSharedMemoryLock_;
CMap<const uint64_t, int32_t> loadedJSSharedMemory_;
};
} // namespace ecmascript
} // namespace panda
#endif // ECMASCRIPT_SHARED_MEMORY_MANAGER_MANAGER_H

View File

@ -460,6 +460,7 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump)
NEW_OBJECT_AND_DUMP(JSDisplayNames, JS_DISPLAYNAMES)
break;
}
case JSType::JS_SHARED_ARRAY_BUFFER:
case JSType::JS_ARRAY_BUFFER: {
CHECK_DUMP_FIELDS(JSObject::SIZE, JSArrayBuffer::SIZE, 2)
NEW_OBJECT_AND_DUMP(JSArrayBuffer, JS_ARRAY_BUFFER)

View File

@ -423,6 +423,38 @@ public:
Destroy();
}
void JSSharedArrayBufferTest(std::pair<uint8_t *, size_t> data,
const JSHandle<JSArrayBuffer> &originArrayBuffer, int32_t byteLength, const char *msg)
{
Init();
JSDeserializer deserializer(thread, data.first, data.second);
JSHandle<JSTaggedValue> res = deserializer.DeserializeJSTaggedValue();
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize JSArrayBuffer fail";
EXPECT_TRUE(res->IsSharedArrayBuffer()) << "[NotJSArrayBuffer] Deserialize JSArrayBuffer fail";
JSHandle<JSArrayBuffer> resJSArrayBuffer = JSHandle<JSArrayBuffer>::Cast(res);
int32_t resByteLength = resJSArrayBuffer->GetArrayBufferByteLength();
EXPECT_TRUE(resByteLength == byteLength) << "Not Same ByteLength";
JSHandle<JSTaggedValue> bufferData(thread, originArrayBuffer->GetArrayBufferData());
auto np = JSHandle<JSNativePointer>::Cast(bufferData);
void *buffer = np->GetExternalPointer();
ASSERT_NE(buffer, nullptr);
JSHandle<JSTaggedValue> resBufferData(thread, resJSArrayBuffer->GetArrayBufferData());
JSHandle<JSNativePointer> resNp = JSHandle<JSNativePointer>::Cast(resBufferData);
void *resBuffer = resNp->GetExternalPointer();
ASSERT_NE(resBuffer, nullptr);
EXPECT_TRUE((uint64_t)buffer == (uint64_t)resBuffer) << "Not Same pointer!";
for (int32_t i = 0; i < resByteLength; i++) {
EXPECT_TRUE(static_cast<char *>(resBuffer)[i] == static_cast<char *>(buffer)[i]) << "Not Same Buffer";
}
if (msg != nullptr) {
if (memcpy_s(resBuffer, byteLength, msg, byteLength) != EOK) {
EXPECT_TRUE(false) << " memcpy error!";
}
}
Destroy();
}
void JSRegexpTest(std::pair<uint8_t *, size_t> data)
{
Init();
@ -997,25 +1029,24 @@ HWTEST_F_L0(JSSerializerTest, SerializeJSArrayBufferShared2)
{
std::string msg = "hello world";
int msgBufferLen = msg.length() + 1;
char* msgBuffer = new char[msgBufferLen] { 0 };
if (memcpy_s(msgBuffer, msgBufferLen, msg.c_str(), msgBufferLen) != EOK) {
delete[] msgBuffer;
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSArrayBuffer> jsArrayBuffer = factory->NewJSSharedArrayBuffer(msgBufferLen);
JSHandle<JSTaggedValue> BufferData(thread, jsArrayBuffer->GetArrayBufferData());
JSHandle<JSNativePointer> resNp = JSHandle<JSNativePointer>::Cast(BufferData);
void *Buffer = resNp->GetExternalPointer();
if (memcpy_s(Buffer, msgBufferLen, msg.c_str(), msgBufferLen) != EOK) {
EXPECT_TRUE(false) << " memcpy error";
}
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSArrayBuffer> jsArrayBuffer = factory->NewJSArrayBuffer(msgBuffer, msgBufferLen, nullptr, nullptr, true);
JSSerializer *serializer = new JSSerializer(thread);
bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(jsArrayBuffer));
EXPECT_TRUE(success) << "Serialize JSArrayBuffer fail";
std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer();
JSDeserializerTest jsDeserializerTest;
std::string changeStr = "world hello";
std::thread t1(&JSDeserializerTest::JSArrayBufferTest,
std::thread t1(&JSDeserializerTest::JSSharedArrayBufferTest,
jsDeserializerTest, data, jsArrayBuffer, 12, changeStr.c_str());
t1.join();
EXPECT_TRUE(strcmp(msgBuffer, "world hello") == 0) << "Serialize JSArrayBuffer fail";
EXPECT_TRUE(strcmp((char *)Buffer, "world hello") == 0) << "Serialize JSArrayBuffer fail";
delete serializer;
};