mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
commit
e802f8e5e3
2
BUILD.gn
2
BUILD.gn
@ -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",
|
||||
|
@ -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);
|
||||
|
@ -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_);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
257
ecmascript/builtins/builtins_sharedarraybuffer.cpp
Normal file
257
ecmascript/builtins/builtins_sharedarraybuffer.cpp
Normal 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 arrayBuffer’s [[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 obj’s [[ArrayBufferData]] internal slot to block.
|
||||
factory->NewJSSharedArrayBufferData(sharedArrayBuffer, byteLength);
|
||||
// 7. Set obj’s [[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 O’s [[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 O’s [[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 new’s [[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 O’s [[ArrayBufferData]] internal slot.
|
||||
JSTaggedValue from = shaArrBuf->GetArrayBufferData();
|
||||
// 24. Let toBuf be the value of new’s [[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
|
45
ecmascript/builtins/builtins_sharedarraybuffer.h
Normal file
45
ecmascript/builtins/builtins_sharedarraybuffer.h
Normal 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
|
@ -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:
|
||||
|
@ -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()));
|
||||
|
@ -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) \
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -293,6 +293,7 @@ public:
|
||||
bool IsForinIterator() const;
|
||||
bool IsStringIterator() const;
|
||||
bool IsArrayBuffer() const;
|
||||
bool IsSharedArrayBuffer() const;
|
||||
|
||||
bool IsJSSetIterator() const;
|
||||
bool IsJSMapIterator() const;
|
||||
|
@ -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;
|
||||
|
@ -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> ®exp, 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());
|
||||
|
@ -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> ®exp, void *buffer, size_t size);
|
||||
|
||||
template<typename T, typename S>
|
||||
|
@ -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) \
|
||||
|
117
ecmascript/sharedMemoryManaged/sharedmemorymanager.cpp
Normal file
117
ecmascript/sharedMemoryManaged/sharedmemorymanager.cpp
Normal 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
|
50
ecmascript/sharedMemoryManaged/sharedmemorymanager.h
Normal file
50
ecmascript/sharedMemoryManaged/sharedmemorymanager.h
Normal 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
|
@ -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)
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user