!9598 [ets_runtime] Realise the FastCreateDataProperty for Array.from

Merge pull request !9598 from xingshunxiang/addFastCreateDataProperty
This commit is contained in:
openharmony_ci 2024-10-18 12:56:10 +00:00 committed by Gitee
commit 0d6411ecca
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
7 changed files with 248 additions and 6 deletions

View File

@ -259,7 +259,7 @@ JSTaggedValue BuiltinsArray::From(EcmaRuntimeCallInfo *argv)
} else {
mapValue.Update(kValue.GetTaggedValue());
}
JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, k, mapValue);
JSArray::TryFastCreateDataProperty(thread, newArrayHandle, k, mapValue);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
k++;
len = ArrayHelper::GetArrayLength(thread, arrayLike);
@ -308,8 +308,11 @@ JSTaggedValue BuiltinsArray::From(EcmaRuntimeCallInfo *argv)
// ix. Let defineStatus be CreateDataPropertyOrThrow(A, Pk, mappedValue).
// x. If defineStatus is an abrupt completion, return IteratorClose(iterator, defineStatus).
// xi. Increase k by 1.
JSHandle<JSTaggedValue> defineStatus(
thread, JSTaggedValue(JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, key, mapValue)));
bool createRes = newArrayHandle->IsJSArray() ?
JSArray::TryFastCreateDataProperty(thread, newArrayHandle, k, mapValue) :
JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, key, mapValue);
JSHandle<JSTaggedValue> defineStatus(thread, JSTaggedValue(createRes));
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread,
JSIterator::IteratorClose(thread, iterator, defineStatus).GetTaggedValue());
k++;
@ -373,7 +376,7 @@ JSTaggedValue BuiltinsArray::From(EcmaRuntimeCallInfo *argv)
} else {
mapValue.Update(kValue.GetTaggedValue());
}
JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, k, mapValue);
JSArray::TryFastCreateDataProperty(thread, newArrayHandle, k, mapValue);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
k++;
thread->CheckSafepointIfSuspended();

View File

@ -475,6 +475,41 @@ bool JSArray::FastSetPropertyByValue(JSThread *thread, const JSHandle<JSTaggedVa
value.GetTaggedValue());
}
bool JSArray::TryFastCreateDataProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index,
const JSHandle<JSTaggedValue> &value, SCheckMode sCheckMode)
{
JSHandle<JSTaggedValue> objVal(obj);
if (!objVal->IsStableJSArray(thread)) {
// if JSArray is DictionaryMode goto slowPath
return JSObject::CreateDataPropertyOrThrow(thread, obj, index, value, sCheckMode);
}
uint32_t capacity = TaggedArray::Cast(obj->GetElements())->GetLength();
ElementsKind kind = obj->GetJSHClass()->GetElementsKind();
uint32_t len = JSHandle<JSArray>::Cast(obj)->GetArrayLength();
if (index > len || kind != ElementsKind::HOLE_TAGGED) {
// goto slowPath
return JSObject::CreateDataPropertyOrThrow(thread, obj, index, value, sCheckMode);
}
if (index == len) {
// append situation
if (!IsArrayLengthWritable(thread, obj)) {
THROW_TYPE_ERROR_AND_RETURN(thread, "UnWritable ArrayLength", false);
}
uint32_t newLen = index + 1;
if (newLen > capacity) {
// needs to expand the capacity
return JSObject::CreateDataPropertyOrThrow(thread, obj, index, value, sCheckMode);
}
JSHandle<JSArray>::Cast(obj)->SetArrayLength(thread, newLen);
}
TaggedArray::Cast(obj->GetElements())->Set(thread, index, value);
return true;
}
// ecma2024 23.1.3.20 Array.prototype.sort(comparefn)
JSTaggedValue JSArray::Sort(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &fn)
{

View File

@ -104,6 +104,10 @@ public:
static bool FastSetPropertyByValue(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value);
static bool TryFastCreateDataProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index,
const JSHandle<JSTaggedValue> &value,
SCheckMode sCheckMode = SCheckMode::CHECK);
static JSTaggedValue Sort(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &fn);
static bool IncludeInSortedValue(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
const JSHandle<JSTaggedValue> &value);

View File

@ -1176,7 +1176,7 @@ JSTaggedValue ObjectFastOperator::AddPropertyByIndex(JSThread *thread, JSTaggedV
INTERPRETER_TRACE(thread, AddPropertyByIndex);
[[maybe_unused]] EcmaHandleScope handleScope(thread);
// fixme(hzzhouzebin) this makes SharedArray's frozen no sense.
if (UNLIKELY(!JSObject::Cast(receiver)->IsExtensible()) && !receiver.IsJSSharedArray()) {
if (UNLIKELY(!JSObject::Cast(receiver)->IsExtensible()) && !receiver.IsJSSharedArray()) {
THROW_TYPE_ERROR_AND_RETURN(thread, GET_MESSAGE_STRING(SetPropertyWhenNotExtensible),
JSTaggedValue::Exception());
}

View File

@ -53,6 +53,6 @@ print(cpu.add(b));
//this is a case from a fuzz test
let v0 = 2 >= 1;
let v1 = "hello"
let v2 = v1.substring(1, v1);
let v2 = v1.substring(v0, v1);
print(v2)

View File

@ -203,3 +203,179 @@ print(Array.from(v1.keys()))
print(JSON.stringify(res));
}
// array.from by arrayLike with mapFunc
{
let res = Array.from({length : 3}, () => {});
print(JSON.stringify(res));
}
{
let res = Array.from({length : 3}, () => ({}));
print(JSON.stringify(res));
}
{
let res = Array.from({length : 3}, () => []);
print(JSON.stringify(res));
}
{
let res = Array.from({length : 3}, () => [1,2,3]);
print(JSON.stringify(res));
}
{
let res = Array.from({length : 3}, () => 0);
print(JSON.stringify(res));
}
{
let num = 1;
let len = 1025;
let res = Array.from({length : len}, () => num);
print(res.length == len);
let flag = true;
for (let i = 0; i < res.length; ++i) {
if (res[i] != num) {
flag = false;
break;
}
}
if (flag) {
print("get JSArray from arrayLike Success");
}
}
{
function example() {
let res = Array.from(arguments);
print(JSON.stringify(res));
}
example(1, 2, 3);
}
{
let arrayLike = {0:1.1, 1:12, 2:'ss', length: 3}
let res = Array.from(arrayLike, x => x + x);
print(JSON.stringify(res));
}
{
let res = Array.from({length : 3}, (_, index) => [index * 2]);
print(JSON.stringify(res));
}
{
const nonConstructor = {}
let res = Array.from.call(nonConstructor, {length : 3}, (_, index) => [index * 2]);
print(JSON.stringify(res));
}
//array.from by JSArray
{
const nonConstructor = {}
let num = 1
let len = 1025 // may transfer to dictionary elements type
let myArray = new Array(1025).fill(num)
let res = Array.from.call(nonConstructor, myArray);
print(res.length == len);
let flag = true;
for (let i = 0; i < res.length; ++i) {
if (res[i] != num || res.at(i) != num) {
flag = false;
break;
}
}
if (flag) {
print("get JSArray from JSArray Success!")
}
}
{
const nonConstructor = {}
let myArray = new Array(1,2,3,4,5)
let res = Array.from.call(nonConstructor, myArray);
print(JSON.stringify(res));
}
{
let res = Array.from([1,2,3,4,5]);
print(JSON.stringify(res));
}
// test for String with mapFunc
{
let str = 'a'.repeat(10)
let res = Array.from(str, x => x + 's');
print(JSON.stringify(res));
}
{
let len = 1025
const head = 'h'
const tail = '_tail'
let str = head.repeat(len)
let res = Array.from(str, x => x + tail);
let flag = true;
for (let i = 0; i < res.length; ++i) {
if (res[i] != head + tail) {
flag = false;
break;
}
}
if (res.length == len && flag) {
print("result check successfully");
} else {
print("result check failed");
}
}
// test for Set with mapFunc
{
let set = new Set(['test', 'for', 'array', 'from', 'set'])
let res = Array.from(set, x => x);
print(JSON.stringify(res));
}
// test for Map with mapFunc
{
let map = new Map([[1, 'test'], [2, 'for'], [3, 'array'], [4, 'from'], [5, 'map']]);
let res = Array.from(map, x => x);
print(JSON.stringify(res));
}
// test for TypedArray with mapFunc
{
let mapFunc = x => x + x;
let uint8Array = new Uint8Array([1, 2, 3, 4, 5, 6]);
let res = Array.from(uint8Array, mapFunc);
print(JSON.stringify(res));
}
{
let mapFunc = x => x + x;
let uint16Array = new Uint16Array([1, 2, 3, 4, 5, 6]);
let res = Array.from(uint16Array, mapFunc);
print(JSON.stringify(res));
}
{
let mapFunc = x => x + x;
let uint32Array = new Uint32Array([1, 2, 3, 4, 5, 6]);
let res = Array.from(uint32Array, mapFunc);
print(JSON.stringify(res));
}
{
let mapFunc = x => x + x;
let float32Array = new Float32Array([1, 2, 3, 4, 5, 6]);
let res = Array.from(float32Array, mapFunc);
print(JSON.stringify(res));
}
{
let mapFunc = x => x + x;
let float64Array = new Float64Array([1, 2, 3, 4, 5, 6]);
let res = Array.from(float64Array, mapFunc);
print(JSON.stringify(res));
}

View File

@ -87,3 +87,27 @@ get length
get length
[0,1,2,null,null,null,null,null,null,null]
[1,2,3]
[null,null,null]
[{},{},{}]
[[],[],[]]
[[1,2,3],[1,2,3],[1,2,3]]
[0,0,0]
true
get JSArray from arrayLike Success
[1,2,3]
[2.2,24,"ssss"]
[[0],[2],[4]]
[[0],[2],[4]]
true
get JSArray from JSArray Success!
[1,2,3,4,5]
[1,2,3,4,5]
["as","as","as","as","as","as","as","as","as","as"]
result check successfully
["test","for","array","from","set"]
[[1,"test"],[2,"for"],[3,"array"],[4,"from"],[5,"map"]]
[2,4,6,8,10,12]
[2,4,6,8,10,12]
[2,4,6,8,10,12]
[2,4,6,8,10,12]
[2,4,6,8,10,12]