Optimize filter, reverse and sort in Array

Optimize filter, reverse and sort in Array

issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I5LWPV

Signed-off-by: xdmal <maxiaodong16@huawei.com>
This commit is contained in:
xdmal 2022-08-11 16:52:48 +08:00 committed by xmdal
parent 494f699de4
commit 46dd7d0add
3 changed files with 181 additions and 9 deletions

View File

@ -430,6 +430,9 @@ JSTaggedValue BuiltinsArray::Concat(EcmaRuntimeCallInfo *argv)
THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception());
}
double k = 0;
if (thisObjVal->IsStableJSArray(thread)) {
JSStableArray::Concat(thread, newArrayHandle, thisObjHandle, k, n);
}
while (k < thisLen) {
fromKey.Update(JSTaggedValue(k));
toKey.Update(JSTaggedValue(n));
@ -474,6 +477,10 @@ JSTaggedValue BuiltinsArray::Concat(EcmaRuntimeCallInfo *argv)
THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception());
}
double k = 0;
JSHandle<JSTaggedValue> addObjVal(addObjHandle);
if (addObjVal->IsStableJSArray(thread)) {
JSStableArray::Concat(thread, newArrayHandle, addObjHandle, k, n);
}
// v. Repeat, while k < len
while (k < len) {
fromKey.Update(JSTaggedValue(k));
@ -880,6 +887,12 @@ JSTaggedValue BuiltinsArray::Filter(EcmaRuntimeCallInfo *argv)
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> toIndexHandle(thread, JSTaggedValue::Undefined());
uint32_t k = 0;
if (thisObjVal->IsStableJSArray(thread)) {
JSStableArray::Filter(newArrayHandle, thisObjHandle, argv, k, toIndex);
}
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
const int32_t argsLength = 3; // 3: «kValue, k, O»
JSTaggedValue callResult = GetTaggedBoolean(true);
while (k < len) {
bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, k);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
@ -887,16 +900,12 @@ JSTaggedValue BuiltinsArray::Filter(EcmaRuntimeCallInfo *argv)
JSHandle<JSTaggedValue> kValue = JSArray::FastGetPropertyByValue(thread, thisObjVal, k);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
key.Update(JSTaggedValue(k));
const int32_t argsLength = 3; // 3: «kValue, k, O»
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
EcmaRuntimeCallInfo *info =
EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue());
JSTaggedValue callResult = JSFunction::Call(info);
bool boolResult = callResult.ToBoolean();
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
if (boolResult) {
callResult = JSFunction::Call(info);
if (callResult.ToBoolean()) {
toIndexHandle.Update(JSTaggedValue(toIndex));
JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, toIndexHandle, kValue);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
@ -1425,9 +1434,14 @@ JSTaggedValue BuiltinsArray::Map(EcmaRuntimeCallInfo *argv)
// v. Let status be CreateDataPropertyOrThrow (A, Pk, mappedValue).
// vi. ReturnIfAbrupt(status).
// e. Increase k by 1.
uint32_t k = 0;
if (thisObjVal->IsStableJSArray(thread)) {
JSStableArray::Map(newArrayHandle, thisObjHandle, argv, k, len);
}
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> mapResultHandle(thread, JSTaggedValue::Undefined());
uint32_t k = 0;
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
const int32_t argsLength = 3; // 3: «kValue, k, O»
while (k < len) {
bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, k);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
@ -1435,8 +1449,6 @@ JSTaggedValue BuiltinsArray::Map(EcmaRuntimeCallInfo *argv)
JSHandle<JSTaggedValue> kValue = JSArray::FastGetPropertyByValue(thread, thisObjVal, k);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
key.Update(JSTaggedValue(k));
const int32_t argsLength = 3; // 3: «kValue, k, O»
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
EcmaRuntimeCallInfo *info =
EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
@ -1839,6 +1851,9 @@ JSTaggedValue BuiltinsArray::Reverse(EcmaRuntimeCallInfo *argv)
JSMutableHandle<JSTaggedValue> upperP(thread, JSTaggedValue::Undefined());
JSHandle<JSTaggedValue> lowerValueHandle(thread, JSTaggedValue::Undefined());
JSHandle<JSTaggedValue> upperValueHandle(thread, JSTaggedValue::Undefined());
if (thisObjVal->IsStableJSArray(thread)) {
JSStableArray::Reverse(thread, thisObjHandle, thisHandle, lower, len);
}
while (lower != middle) {
double upper = len - lower - 1;
lowerP.Update(JSTaggedValue(lower));

View File

@ -420,4 +420,153 @@ JSTaggedValue JSStableArray::IndexOf(JSThread *thread, JSHandle<JSTaggedValue> r
}
return JSTaggedValue(-1);
}
JSTaggedValue JSStableArray::Filter(JSHandle<JSObject> newArrayHandle, JSHandle<JSObject> thisObjHandle,
EcmaRuntimeCallInfo *argv, uint32_t &k, double &toIndex)
{
JSThread *thread = argv->GetThread();
JSHandle<JSTaggedValue> callbackFnHandle = base::BuiltinsBase::GetCallArg(argv, 0);
JSHandle<JSTaggedValue> thisArgHandle = base::BuiltinsBase::GetCallArg(argv, 1);
JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> toIndexHandle(thread, JSTaggedValue::Undefined());
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
const int32_t argsLength = 3; // 3: ?kValue, k, O?
double len = base::ArrayHelper::GetArrayLength(thread, thisObjVal);
JSHandle<TaggedArray> array(thread, thisObjHandle->GetElements());
while (k < len) {
JSTaggedValue kValue = array->Get(k);
if (!kValue.IsHole()) {
key.Update(JSTaggedValue(k));
EcmaRuntimeCallInfo *info =
EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
info->SetCallArg(kValue, key.GetTaggedValue(), thisObjVal.GetTaggedValue());
JSTaggedValue callResult = JSFunction::Call(info);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
if (array->GetLength() < len) {
len = array->GetLength();
}
bool boolResult = callResult.ToBoolean();
if (boolResult) {
toIndexHandle.Update(JSTaggedValue(toIndex));
JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle,
toIndexHandle, JSHandle<JSTaggedValue>(thread, kValue));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
toIndex++;
}
}
k++;
if (!thisObjVal->IsStableJSArray(thread)) {
break;
}
}
return base::BuiltinsBase::GetTaggedDouble(true);
}
JSTaggedValue JSStableArray::Map(JSHandle<JSObject> newArrayHandle, JSHandle<JSObject> thisObjHandle,
EcmaRuntimeCallInfo *argv, uint32_t &k, uint32_t len)
{
JSThread *thread = argv->GetThread();
JSHandle<JSTaggedValue> callbackFnHandle = base::BuiltinsBase::GetCallArg(argv, 0);
JSHandle<JSTaggedValue> thisArgHandle = base::BuiltinsBase::GetCallArg(argv, 1);
JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
JSMutableHandle<JSTaggedValue> mapResultHandle(thread, JSTaggedValue::Undefined());
const int32_t argsLength = 3; // 3: ?kValue, k, O?
JSHandle<TaggedArray> array(thread, thisObjHandle->GetElements());
while (k < len) {
JSTaggedValue kValue = array->Get(k);
if (!kValue.IsHole()) {
key.Update(JSTaggedValue(k));
EcmaRuntimeCallInfo *info =
EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
info->SetCallArg(kValue, key.GetTaggedValue(), thisObjVal.GetTaggedValue());
JSTaggedValue mapResult = JSFunction::Call(info);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
mapResultHandle.Update(mapResult);
JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, k, mapResultHandle);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
if (array->GetLength() < len) {
len = array->GetLength();
}
}
k++;
if (!thisObjVal->IsStableJSArray(thread)) {
break;
}
}
return base::BuiltinsBase::GetTaggedDouble(true);
}
JSTaggedValue JSStableArray::Reverse(JSThread *thread, JSHandle<JSObject> thisObjHandle,
JSHandle<JSTaggedValue> thisHandle, double &lower, uint32_t len)
{
JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
JSHandle<TaggedArray> array(thread, thisObjHandle->GetElements());
JSMutableHandle<JSTaggedValue> lowerP(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> upperP(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> lowerValueHandle(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> upperValueHandle(thread, JSTaggedValue::Undefined());
double middle = std::floor(len / 2);
while (lower != middle) {
if (array->GetLength() != len) {
break;
}
double upper = len - lower - 1;
lowerP.Update(JSTaggedValue(lower));
upperP.Update(JSTaggedValue(upper));
bool lowerExists = (thisHandle->IsTypedArray() || JSTaggedValue::HasProperty(thread, thisObjVal, lowerP));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
if (lowerExists) {
lowerValueHandle.Update(array->Get(lower));
}
bool upperExists = (thisHandle->IsTypedArray() || JSTaggedValue::HasProperty(thread, thisObjVal, upperP));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
if (upperExists) {
upperValueHandle.Update(array->Get(upper));
}
if (lowerExists && upperExists) {
array->Set(thread, lower, upperValueHandle.GetTaggedValue());
array->Set(thread, upper, lowerValueHandle.GetTaggedValue());
} else if (upperExists) {
array->Set(thread, lower, upperValueHandle.GetTaggedValue());
JSTaggedValue::SetProperty(thread, thisObjVal, lowerP, upperValueHandle, true);
JSTaggedValue::DeletePropertyOrThrow(thread, thisObjVal, upperP);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
} else if (lowerExists) {
array->Set(thread, upper, lowerValueHandle.GetTaggedValue());
JSTaggedValue::SetProperty(thread, thisObjVal, upperP, lowerValueHandle, true);
JSTaggedValue::DeletePropertyOrThrow(thread, thisObjVal, lowerP);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
}
lower++;
}
return base::BuiltinsBase::GetTaggedDouble(true);
}
JSTaggedValue JSStableArray::Concat(JSThread *thread, JSHandle<JSObject> newArrayHandle,
JSHandle<JSObject> thisObjHandle, double &k, double &n)
{
JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
double thisLen = base::ArrayHelper::GetArrayLength(thread, thisObjVal);
JSHandle<TaggedArray> arrayFrom(thread, thisObjHandle->GetElements());
JSMutableHandle<JSTaggedValue> toKey(thread, JSTaggedValue::Undefined());
while (k < thisLen) {
if (arrayFrom->GetLength() != thisLen) {
break;
}
toKey.Update(JSTaggedValue(n));
JSTaggedValue kValue = arrayFrom->Get(k);
if (!kValue.IsHole()) {
JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, toKey, JSHandle<JSTaggedValue>(thread, kValue));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
}
n++;
k++;
}
return base::BuiltinsBase::GetTaggedDouble(true);
}
} // namespace panda::ecmascript

View File

@ -42,6 +42,14 @@ public:
JSHandle<JSTaggedValue> thisArgHandle, uint32_t &k);
static JSTaggedValue IndexOf(JSThread *thread, JSHandle<JSTaggedValue> receiver,
JSHandle<JSTaggedValue> searchElement, uint32_t from, uint32_t len);
static JSTaggedValue Filter(JSHandle<JSObject> newArrayHandle, JSHandle<JSObject> thisObjHandle,
EcmaRuntimeCallInfo *argv, uint32_t &k, double &toIndex);
static JSTaggedValue Map(JSHandle<JSObject> newArrayHandle, JSHandle<JSObject> thisObjHandle,
EcmaRuntimeCallInfo *argv, uint32_t &k, uint32_t len);
static JSTaggedValue Reverse(JSThread *thread, JSHandle<JSObject> thisObjHandle,
JSHandle<JSTaggedValue> thisHandle, double &lower, uint32_t len);
static JSTaggedValue Concat(JSThread *thread, JSHandle<JSObject> newArrayHandle,
JSHandle<JSObject> thisObjHandle, double &k, double &n);
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_JS_STABLE_ARRAY_H