Optimize jsapi encodeInto

Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IAL8WP

Signed-off-by: hewei <hewei215@huawei.com>
Change-Id: Ica2189d0f330f5ce6652e499a3d0506bca9013f8
This commit is contained in:
hewei 2024-08-20 20:21:02 +08:00
parent dfc2b50b76
commit 1f49cf34ff
6 changed files with 127 additions and 0 deletions

View File

@ -435,4 +435,26 @@ HWTEST_F_L0(TypedArrayHelperTest, SortCompare)
result = TypedArrayHelper::SortCompare(thread, callbackfnHandle, buffer, pZero, eZero);
EXPECT_EQ(result, 1);
}
HWTEST_F_L0(TypedArrayHelperTest, FastCreateTypedArray) {
uint8_t first = static_cast<uint8_t>(DataViewType::BIGINT64);
uint8_t last = static_cast<uint8_t>(DataViewType::UINT8_CLAMPED);
for (uint8_t type = first; type <= last; ++type) {
DataViewType arrayType = static_cast<DataViewType>(type);
JSHandle<JSTaggedValue> constructorName = TypedArrayHelper::GetConstructorNameFromType(thread, arrayType);
JSHandle<JSObject> arrayObj =
TypedArrayHelper::FastCreateTypedArray(thread, constructorName, 0, arrayType);
JSTypedArray *jsTypedArray = JSTypedArray::Cast(*arrayObj);
if (arrayType == DataViewType::BIGINT64 ||
arrayType == DataViewType::BIGUINT64) {
EXPECT_EQ(jsTypedArray->GetContentType(), ContentType::BigInt);
} else {
EXPECT_EQ(jsTypedArray->GetContentType(), ContentType::Number);
}
EXPECT_EQ(jsTypedArray->GetTypedArrayName().GetRawData(), constructorName.GetTaggedValue().GetRawData());
EXPECT_EQ(jsTypedArray->GetByteLength(), 0U);
EXPECT_EQ(jsTypedArray->GetByteOffset(), 0U);
EXPECT_EQ(jsTypedArray->GetArrayLength(), 0U);
}
}
} // namespace panda::test

View File

@ -133,6 +133,56 @@ JSTaggedValue TypedArrayHelper::SharedTypedArrayConstructor(EcmaRuntimeCallInfo
return TypedArrayHelper::CreateFromOrdinaryObject<TypedArrayKind::SHARED>(argv, obj, arrayType);
}
// Fastpath for create a typedarray. Do not need to create an EcmaRuntimeCallInfo.
JSHandle<JSObject> TypedArrayHelper::FastCreateTypedArray(JSThread *thread,
const JSHandle<JSTaggedValue> &constructorName,
uint32_t length,
const DataViewType arrayType)
{
JSHandle<JSObject> exception(thread, JSTaggedValue::Exception());
if (length > JSTypedArray::MAX_TYPED_ARRAY_INDEX) {
THROW_RANGE_ERROR_AND_RETURN(thread, "array length must less than 2^32 - 1", exception);
}
// Create TypedArray
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSFunction> typedArrayFunc = TypedArrayHelper::GetConstructorFromType(thread, arrayType);
JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(typedArrayFunc,
JSHandle<JSTaggedValue>::Cast(typedArrayFunc));
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSHandle<JSObject>(thread, JSTaggedValue::Exception()));
JSTypedArray::Cast(*obj)->SetTypedArrayName(thread, constructorName);
// Create ArrayBuffer
uint32_t elementSize = TypedArrayHelper::GetSizeFromType(arrayType);
uint32_t arrayLength = static_cast<uint32_t>(length);
uint64_t byteLength = static_cast<uint64_t>(elementSize) * length;
JSHandle<JSTaggedValue> data;
JSHandle<JSTaggedValue> constructor = thread->GetEcmaVM()->GetGlobalEnv()->GetArrayBufferFunction();
data = JSHandle<JSTaggedValue>(thread,
BuiltinsArrayBuffer::AllocateArrayBuffer(thread, constructor, byteLength));
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, exception);
// Assign ArrayBuffer to TypedArray
JSTypedArray *jsTypedArray = JSTypedArray::Cast(*obj);
if (arrayType == DataViewType::BIGINT64 ||
arrayType == DataViewType::BIGUINT64) {
jsTypedArray->SetContentType(ContentType::BigInt);
} else {
jsTypedArray->SetContentType(ContentType::Number);
}
// Set O.[[ViewedArrayBuffer]] to data.
// Set O.[[ByteLength]] to byteLength.
// Set O.[[ByteOffset]] to 0.
// Set O.[[ArrayLength]] to length.
jsTypedArray->SetViewedArrayBufferOrByteArray(thread, data);
jsTypedArray->SetByteLength(byteLength);
jsTypedArray->SetByteOffset(0);
jsTypedArray->SetArrayLength(arrayLength);
// Return O.
return obj;
}
template<>
JSHandle<JSObject> TypedArrayHelper::AllocateTypedArrayBuffer<TypedArrayKind::NON_SHARED>(
JSThread *thread, const JSHandle<JSObject> &obj, uint64_t length, const DataViewType arrayType)

View File

@ -45,6 +45,10 @@ public:
static JSTaggedValue SharedTypedArrayConstructor(EcmaRuntimeCallInfo *argv,
const JSHandle<JSTaggedValue> &constructorName,
const DataViewType arrayType);
static JSHandle<JSObject> FastCreateTypedArray(JSThread *thread,
const JSHandle<JSTaggedValue> &constructorName,
uint32_t length,
const DataViewType arrayType);
static JSHandle<JSObject> AllocateTypedArray(JSThread *thread,
const JSHandle<JSTaggedValue> &constructorName,
const JSHandle<JSTaggedValue> &newTarget,

View File

@ -63,6 +63,7 @@ class MapIteratorRef;
class SendableMapIteratorRef;
class BooleanRef;
class NativePointerRef;
class TypedArrayRef;
class JsiRuntimeCallInfo;
class RuntimeOption;
namespace test {
@ -868,6 +869,7 @@ public:
int WriteUtf16(const EcmaVM *vm, char16_t *buffer, int length);
int WriteLatin1(const EcmaVM *vm, char *buffer, int length);
static Local<StringRef> GetNapiWrapperString(const EcmaVM *vm);
Local<TypedArrayRef> EncodeIntoUint8Array(const EcmaVM *vm);
};
class ECMA_PUBLIC_API PromiseRejectInfo {

View File

@ -47,6 +47,7 @@ namespace panda {
using ecmascript::AccessorData;
using ecmascript::BigInt;
using ecmascript::ByteArray;
using ecmascript::DataViewType;
using ecmascript::ECMAObject;
using ecmascript::EcmaRuntimeCallInfo;
using ecmascript::EcmaString;
@ -2168,6 +2169,30 @@ Local<StringRef> StringRef::GetNapiWrapperString(const EcmaVM *vm)
return JSNApiHelper::ToLocal<StringRef>(napiWapperString);
}
Local<TypedArrayRef> StringRef::EncodeIntoUint8Array(const EcmaVM *vm)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
JSHandle<JSTaggedValue> string = JSNApiHelper::ToJSHandle(this);
uint32_t length = this->Utf8Length(vm, true);
// 1 because Utf8Length adds 1 for the return value
if (length <= 1) {
return Undefined(vm);
}
JSHandle<JSObject> obj =
TypedArrayHelper::FastCreateTypedArray(thread, thread->GlobalConstants()->GetHandledUint8ArrayString(),
length - 1, DataViewType::UINT8);
JSHandle<JSObject> arrayBuffer(thread, JSTypedArray::Cast(*obj)->GetViewedArrayBufferOrByteArray());
JSTaggedValue bufferData = JSHandle<JSArrayBuffer>::Cast(arrayBuffer)->GetArrayBufferData();
void *buffer = JSNativePointer::Cast(bufferData.GetTaggedObject())->GetExternalPointer();
JSHandle<EcmaString> stringHandle = JSHandle<EcmaString>::Cast(string);
EcmaStringAccessor(stringHandle).WriteToFlatUtf8(reinterpret_cast<uint8_t*>(buffer), length - 1, true);
JSHandle<JSTaggedValue> typedArrayTag = JSHandle<JSTaggedValue>::Cast(obj);
return JSNApiHelper::ToLocal<TypedArrayRef>(typedArrayTag);
}
// ---------------------------------- PromiseRejectInfo ---------------------------------
PromiseRejectInfo::PromiseRejectInfo(Local<JSValueRef> promise, Local<JSValueRef> reason,
PromiseRejectInfo::PROMISE_REJECTION_EVENT operation, void* data)

View File

@ -381,6 +381,30 @@ HWTEST_F_L0(JSNApiTests, StringUtf8_003)
EXPECT_EQ(buffer2[2], 'b');
}
HWTEST_F_L0(JSNApiTests, StringEncodeIntoUint8_001) {
LocalScope scope(vm_);
std::string test = "";
Local<StringRef> testString1 =
StringRef::NewFromUtf8(vm_, test.c_str(), test.length());
Local<TypedArrayRef> typedArray = testString1->EncodeIntoUint8Array(vm_);
EXPECT_TRUE(typedArray->IsUndefined());
}
HWTEST_F_L0(JSNApiTests, StringEncodeIntoUint8_002) {
LocalScope scope(vm_);
std::string test = "abc123";
char excepted[7] = {0x61, 0x62, 0x63, 0x31, 0x32, 0x33, 0};
Local<StringRef> testString1 =
StringRef::NewFromUtf8(vm_, test.c_str(), test.length());
Local<TypedArrayRef> typedArray = testString1->EncodeIntoUint8Array(vm_);
char *res = reinterpret_cast<char *>(typedArray->GetArrayBuffer(vm_)->GetBuffer(vm_));
ASSERT_STREQ(res, excepted);
}
/**
* @tc.number: ffi_interface_api_007
* @tc.name: StringLatin1_001