mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 01:59:58 +00:00
Optimize Array.sort
Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IB106H?from=project-issue Signed-off-by: 刘智杰 <liuzhijie9@huawei.com> Change-Id: If301c6e3bfdff3381475f5728cb072b6bc65b1a6
This commit is contained in:
parent
c8a3605237
commit
c420bd1fe9
@ -2374,12 +2374,12 @@ JSTaggedValue BuiltinsArray::Sort(EcmaRuntimeCallInfo *argv)
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
||||
// Array sort
|
||||
if (thisHandle->IsStableJSArray(thread) && callbackFnHandle->IsUndefined()) {
|
||||
JSStableArray::Sort(thread, thisObjHandle, callbackFnHandle);
|
||||
if (thisHandle->IsStableJSArray(thread)) {
|
||||
JSStableArray::Sort(thread, thisHandle, callbackFnHandle);
|
||||
} else {
|
||||
JSArray::Sort(thread, JSHandle<JSTaggedValue>::Cast(thisObjHandle), callbackFnHandle);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
}
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
return thisObjHandle.GetTaggedValue();
|
||||
}
|
||||
|
||||
|
@ -1702,7 +1702,7 @@ JSTaggedValue BuiltinsSharedArray::Sort(EcmaRuntimeCallInfo *argv)
|
||||
|
||||
// Array sort
|
||||
if (thisHandle->IsStableJSArray(thread) && callbackFnHandle->IsUndefined()) {
|
||||
JSStableArray::Sort(thread, thisObjHandle, callbackFnHandle);
|
||||
JSStableArray::Sort(thread, thisHandle, callbackFnHandle);
|
||||
} else {
|
||||
JSSharedArray::Sort(thread, JSHandle<JSTaggedValue>::Cast(thisObjHandle), callbackFnHandle);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "ecmascript/compiler/aot_snapshot/aot_snapshot_constants.h"
|
||||
#include "ecmascript/js_file_path.h"
|
||||
#include "ecmascript/message_string.h"
|
||||
#include "ecmascript/ohos/framework_helper.h"
|
||||
#include "ecmascript/ohos/ohos_preload_app_info.h"
|
||||
#include "ecmascript/snapshot/mem/snapshot.h"
|
||||
|
@ -510,29 +510,11 @@ bool JSArray::TryFastCreateDataProperty(JSThread *thread, const JSHandle<JSObjec
|
||||
return true;
|
||||
}
|
||||
|
||||
// ecma2024 23.1.3.20 Array.prototype.sort(comparefn)
|
||||
JSTaggedValue JSArray::Sort(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &fn)
|
||||
JSTaggedValue JSArray::CopySortedListToReceiver(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
|
||||
JSHandle<TaggedArray> sortedList, uint32_t len)
|
||||
{
|
||||
ASSERT(fn->IsUndefined() || fn->IsCallable());
|
||||
// 3. Let len be ?LengthOfArrayLike(obj).
|
||||
int64_t len = ArrayHelper::GetArrayLength(thread, obj);
|
||||
// ReturnIfAbrupt(len).
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
// If len is 0 or 1, no need to sort
|
||||
if (len == 0 || len == 1) {
|
||||
return obj.GetTaggedValue();
|
||||
}
|
||||
|
||||
// 4. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparefn and performs
|
||||
// the following steps when called:
|
||||
// a. Return ? CompareArrayElements(x, y, comparefn).
|
||||
// 5. Let sortedList be ? SortIndexedProperties(O, len, SortCompare, SKIP-HOLES).
|
||||
JSHandle<TaggedArray> sortedList =
|
||||
ArrayHelper::SortIndexedProperties(thread, obj, len, fn, base::HolesType::SKIP_HOLES);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
// 6. Let itemCount be the number of elements in sortedList.
|
||||
uint32_t itemCount = sortedList->GetLength();
|
||||
|
||||
// 7. Let j be 0.
|
||||
uint32_t j = 0;
|
||||
// 8. Repeat, while j < itemCount,
|
||||
@ -556,7 +538,31 @@ JSTaggedValue JSArray::Sort(JSThread *thread, const JSHandle<JSTaggedValue> &obj
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
++j;
|
||||
}
|
||||
return obj.GetTaggedValue();
|
||||
}
|
||||
|
||||
// ecma2024 23.1.3.20 Array.prototype.sort(comparefn)
|
||||
JSTaggedValue JSArray::Sort(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &fn)
|
||||
{
|
||||
ASSERT(fn->IsUndefined() || fn->IsCallable());
|
||||
// 3. Let len be ?LengthOfArrayLike(obj).
|
||||
int64_t len = ArrayHelper::GetArrayLength(thread, obj);
|
||||
// ReturnIfAbrupt(len).
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
// If len is 0 or 1, no need to sort
|
||||
if (len == 0 || len == 1) {
|
||||
return obj.GetTaggedValue();
|
||||
}
|
||||
|
||||
// 4. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparefn and performs
|
||||
// the following steps when called:
|
||||
// a. Return ? CompareArrayElements(x, y, comparefn).
|
||||
// 5. Let sortedList be ? SortIndexedProperties(O, len, SortCompare, SKIP-HOLES).
|
||||
JSHandle<TaggedArray> sortedList =
|
||||
ArrayHelper::SortIndexedProperties(thread, obj, len, fn, base::HolesType::SKIP_HOLES);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
JSArray::CopySortedListToReceiver(thread, obj, sortedList, len);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
return obj.GetTaggedValue();
|
||||
}
|
||||
|
||||
|
@ -109,6 +109,8 @@ public:
|
||||
SCheckMode sCheckMode = SCheckMode::CHECK);
|
||||
|
||||
static JSTaggedValue Sort(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &fn);
|
||||
static JSTaggedValue CopySortedListToReceiver(JSThread *thread, const JSHandle<JSTaggedValue> &thisObjVal,
|
||||
JSHandle<TaggedArray> sortedList, uint32_t len);
|
||||
static bool IncludeInSortedValue(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
|
||||
const JSHandle<JSTaggedValue> &value);
|
||||
static JSHandle<TaggedArray> ToTaggedArray(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
|
||||
|
@ -679,8 +679,7 @@ bool CharCanFastCompareOrOutOfBounds(EcmaString* string, int stringLength, int i
|
||||
// 5. If all equal, return equal.
|
||||
// 6. Once some chars cannot be fastcompared, use icu.
|
||||
|
||||
std::optional<UCollationResult> TryFastCompareStrings([[maybe_unused]] const icu::Collator* icuCollator,
|
||||
EcmaString* string1, EcmaString* string2,
|
||||
std::optional<UCollationResult> TryFastCompareStrings(EcmaString* string1, EcmaString* string2,
|
||||
int& processedUntilOut)
|
||||
{
|
||||
processedUntilOut = 0;
|
||||
@ -719,17 +718,17 @@ std::optional<UCollationResult> TryFastCompareStrings([[maybe_unused]] const icu
|
||||
} // namespace
|
||||
|
||||
//StringPiece is similar to std::string_view
|
||||
icu::StringPiece ToICUStringPiece(const JSHandle<EcmaString>& string, int offset = 0)
|
||||
icu::StringPiece ToICUStringPiece(EcmaString* string, int offset = 0)
|
||||
{
|
||||
EcmaStringAccessor stringAcc(string);
|
||||
ASSERT(stringAcc.IsUtf8());
|
||||
ASSERT(!stringAcc.IsTreeString());
|
||||
return icu::StringPiece(reinterpret_cast<const char*>(EcmaStringAccessor::GetNonTreeUtf8Data(*string)) + offset,
|
||||
return icu::StringPiece(reinterpret_cast<const char*>(EcmaStringAccessor::GetNonTreeUtf8Data(string)) + offset,
|
||||
static_cast<int>(stringAcc.GetLength()) - offset);
|
||||
}
|
||||
|
||||
// Convert to a UTF16 string and partially convert to ICUUnicodeString
|
||||
icu::UnicodeString ToICUUnicodeString(const JSHandle<EcmaString> &string, int offset = 0)
|
||||
icu::UnicodeString ToICUUnicodeString(EcmaString* string, int offset = 0)
|
||||
{
|
||||
EcmaStringAccessor stringAcc(string);
|
||||
ASSERT(!stringAcc.IsTreeString());
|
||||
@ -741,38 +740,22 @@ icu::UnicodeString ToICUUnicodeString(const JSHandle<EcmaString> &string, int of
|
||||
// short string on stack
|
||||
UChar shortStringBuffer[shortStringLength];
|
||||
// utf8 is within ascii, std::copy_n from utf8 to utf16 is OK
|
||||
std::copy_n(EcmaStringAccessor::GetNonTreeUtf8Data(*string) + offset, partialLength, shortStringBuffer);
|
||||
std::copy_n(EcmaStringAccessor::GetNonTreeUtf8Data(string) + offset, partialLength, shortStringBuffer);
|
||||
return icu::UnicodeString(shortStringBuffer, partialLength);
|
||||
}
|
||||
CVector<uint16_t> ucharBuffer(partialLength);
|
||||
std::copy_n(EcmaStringAccessor::GetNonTreeUtf8Data(*string) + offset, partialLength, ucharBuffer.begin());
|
||||
std::copy_n(EcmaStringAccessor::GetNonTreeUtf8Data(string) + offset, partialLength, ucharBuffer.begin());
|
||||
return icu::UnicodeString(ucharBuffer.data(), partialLength);
|
||||
} else {
|
||||
return icu::UnicodeString(EcmaStringAccessor::GetNonTreeUtf16Data(*string) + offset, partialLength);
|
||||
return icu::UnicodeString(EcmaStringAccessor::GetNonTreeUtf16Data(string) + offset, partialLength);
|
||||
}
|
||||
}
|
||||
|
||||
JSTaggedValue JSCollator::CompareStrings(JSThread *thread, const icu::Collator *icuCollator,
|
||||
const JSHandle<EcmaString> &string1, const JSHandle<EcmaString> &string2,
|
||||
[[maybe_unused]]CompareStringsOption csOption)
|
||||
JSTaggedValue JSCollator::SlowCompareStrings(const icu::Collator *icuCollator,
|
||||
EcmaString* flatString1,
|
||||
EcmaString* flatString2,
|
||||
int processedUntil)
|
||||
{
|
||||
if (*string1 == *string2) {
|
||||
return JSTaggedValue(UCollationResult::UCOL_EQUAL);
|
||||
}
|
||||
|
||||
// Since Unicode has ignorable characters,
|
||||
// we cannot return early for 0-length strings.
|
||||
auto flatString1 = JSHandle<EcmaString>(thread, EcmaStringAccessor::Flatten(thread->GetEcmaVM(), string1));
|
||||
auto flatString2 = JSHandle<EcmaString>(thread, EcmaStringAccessor::Flatten(thread->GetEcmaVM(), string2));
|
||||
|
||||
int processedUntil = 0;
|
||||
if (csOption == CompareStringsOption::TRY_FAST_PATH) {
|
||||
auto maybeResult = TryFastCompareStrings(icuCollator, *flatString1, *flatString2, processedUntil);
|
||||
if (maybeResult.has_value()) {
|
||||
return JSTaggedValue(maybeResult.value());
|
||||
}
|
||||
}
|
||||
|
||||
UCollationResult result;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
if (EcmaStringAccessor(flatString1).IsUtf8() && EcmaStringAccessor(flatString2).IsUtf8()) {
|
||||
@ -790,7 +773,58 @@ JSTaggedValue JSCollator::CompareStrings(JSThread *thread, const icu::Collator *
|
||||
auto uString2 = ToICUUnicodeString(flatString2, processedUntil);
|
||||
result = icuCollator->compare(uString1, uString2, status);
|
||||
ASSERT(U_SUCCESS(status));
|
||||
|
||||
return JSTaggedValue(result);
|
||||
}
|
||||
|
||||
JSTaggedValue JSCollator::CompareStrings(JSThread *thread, const icu::Collator *icuCollator,
|
||||
const JSHandle<EcmaString> &string1, const JSHandle<EcmaString> &string2,
|
||||
[[maybe_unused]]CompareStringsOption csOption)
|
||||
{
|
||||
if (*string1 == *string2) {
|
||||
return JSTaggedValue(UCollationResult::UCOL_EQUAL);
|
||||
}
|
||||
|
||||
// Since Unicode has ignorable characters,
|
||||
// we cannot return early for 0-length strings.
|
||||
auto flatString1 = JSHandle<EcmaString>(thread, EcmaStringAccessor::Flatten(thread->GetEcmaVM(), string1));
|
||||
auto flatString2 = JSHandle<EcmaString>(thread, EcmaStringAccessor::Flatten(thread->GetEcmaVM(), string2));
|
||||
|
||||
int processedUntil = 0;
|
||||
if (csOption == CompareStringsOption::TRY_FAST_PATH) {
|
||||
auto maybeResult = TryFastCompareStrings(*flatString1, *flatString2, processedUntil);
|
||||
if (maybeResult.has_value()) {
|
||||
return JSTaggedValue(maybeResult.value());
|
||||
}
|
||||
}
|
||||
return SlowCompareStrings(icuCollator, *flatString1, *flatString2, processedUntil);
|
||||
}
|
||||
|
||||
JSTaggedValue JSCollator::FastCachedCompareStrings(JSThread *thread, JSHandle<JSTaggedValue> locales,
|
||||
const JSHandle<EcmaString> &string1,
|
||||
const JSHandle<EcmaString> &string2,
|
||||
CompareStringsOption csOption)
|
||||
{
|
||||
if (*string1 == *string2) {
|
||||
return JSTaggedValue(UCollationResult::UCOL_EQUAL);
|
||||
}
|
||||
|
||||
// Since Unicode has ignorable characters,
|
||||
// we cannot return early for 0-length strings.
|
||||
auto flatString1 = JSHandle<EcmaString>(thread, EcmaStringAccessor::Flatten(thread->GetEcmaVM(), string1));
|
||||
auto flatString2 = JSHandle<EcmaString>(thread, EcmaStringAccessor::Flatten(thread->GetEcmaVM(), string2));
|
||||
|
||||
int processedUntil = 0;
|
||||
if (csOption == CompareStringsOption::TRY_FAST_PATH) {
|
||||
auto maybeResult = TryFastCompareStrings(*flatString1, *flatString2, processedUntil);
|
||||
if (maybeResult.has_value()) {
|
||||
return JSTaggedValue(maybeResult.value());
|
||||
}
|
||||
}
|
||||
|
||||
auto icuCollator = JSCollator::GetCachedIcuCollator(thread, locales);
|
||||
if (icuCollator != nullptr) {
|
||||
return SlowCompareStrings(icuCollator, *flatString1, *flatString2, processedUntil);
|
||||
}
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -122,6 +122,16 @@ public:
|
||||
const JSHandle<EcmaString> &string1, const JSHandle<EcmaString> &string2,
|
||||
CompareStringsOption csOption = CompareStringsOption::NONE);
|
||||
|
||||
static JSTaggedValue FastCachedCompareStrings(JSThread *thread, JSHandle<JSTaggedValue> locales,
|
||||
const JSHandle<EcmaString> &string1,
|
||||
const JSHandle<EcmaString> &string2,
|
||||
CompareStringsOption csOption = CompareStringsOption::NONE);
|
||||
|
||||
static JSTaggedValue SlowCompareStrings(const icu::Collator *icuCollator,
|
||||
EcmaString* flatString1,
|
||||
EcmaString* flatString2,
|
||||
int processedUntil);
|
||||
|
||||
private:
|
||||
static CaseFirstOption StringToCaseFirstOption(const std::string &str);
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "ecmascript/js_stable_array.h"
|
||||
|
||||
#include "ecmascript/base/sort_helper.h"
|
||||
#include "ecmascript/base/typed_array_helper-inl.h"
|
||||
#include "ecmascript/interpreter/fast_runtime_stub-inl.h"
|
||||
|
||||
@ -1672,11 +1672,108 @@ JSTaggedValue JSStableArray::Slice(JSThread *thread, JSHandle<JSObject> thisObjH
|
||||
return arrayObj.GetTaggedValue();
|
||||
}
|
||||
|
||||
JSTaggedValue JSStableArray::Sort(JSThread *thread, const JSHandle<JSObject> &thisObj,
|
||||
JSHandle<TaggedArray> JSStableArray::SortIndexedProperties(JSThread *thread, const JSHandle<JSTaggedValue> &thisObjVal,
|
||||
int64_t len, const JSHandle<JSTaggedValue> &callbackFnHandle,
|
||||
base::HolesType holes)
|
||||
{
|
||||
JSHandle<JSObject> thisObj(thread, thisObjVal.GetTaggedValue());
|
||||
JSHandle<TaggedArray> elements(thread, thisObj->GetElements());
|
||||
ElementsKind kind = thisObj->GetClass()->GetElementsKind();
|
||||
if (!elements->GetClass()->IsMutantTaggedArray()) {
|
||||
kind = ElementsKind::GENERIC;
|
||||
}
|
||||
// 1. fill elements into items.
|
||||
JSHandle<TaggedArray> items(thread->GetEcmaVM()->GetFactory()->NewTaggedArray(len));
|
||||
bool kRead = false;
|
||||
int64_t tmp = 0;
|
||||
for (int k = 0; k < len; k++) {
|
||||
JSTaggedValue kValue = ElementAccessor::FastGet(elements, k, kind);
|
||||
if (holes == base::HolesType::SKIP_HOLES) {
|
||||
kRead = (kValue != JSTaggedValue::Hole());
|
||||
} else {
|
||||
ASSERT(holes == base::HolesType::READ_THROUGH_HOLES);
|
||||
kRead = true;
|
||||
}
|
||||
if (kRead) {
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, items);
|
||||
items->Set(thread, tmp++, kValue);
|
||||
}
|
||||
}
|
||||
// 2. trim
|
||||
if (len > tmp) {
|
||||
items->Trim(thread, tmp);
|
||||
}
|
||||
// 3. Sort items using an implementation-defined sequence of calls to SortCompare.
|
||||
// If any such call returns an abrupt completion,
|
||||
// stop before performing any further calls to SortCompare and return that Completion Record.
|
||||
base::TimSort::Sort(thread, items, callbackFnHandle);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, items);
|
||||
// 4. Return items.
|
||||
return items;
|
||||
}
|
||||
|
||||
JSTaggedValue JSStableArray::CopySortedListToReceiver(JSThread *thread, const JSHandle<JSTaggedValue> &thisObjVal,
|
||||
JSHandle<TaggedArray> sortedList, uint32_t len)
|
||||
{
|
||||
// 6. Let itemCount be the number of elements in sortedList.
|
||||
uint32_t itemCount = sortedList->GetLength();
|
||||
|
||||
// grow elements if len > newLength.
|
||||
JSHandle<JSObject> thisObj(thisObjVal);
|
||||
uint32_t newLength = std::max(JSHandle<JSArray>::Cast(thisObjVal)->GetArrayLength(), itemCount);
|
||||
TaggedArray *elements = TaggedArray::Cast(thisObj->GetElements().GetTaggedObject());
|
||||
if (newLength > ElementAccessor::GetElementsLength(thisObj)) {
|
||||
elements = *JSObject::GrowElementsCapacity(thread, thisObj, newLength, true);
|
||||
}
|
||||
|
||||
JSMutableHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue::Undefined());
|
||||
bool needTransition = true;
|
||||
// 7. Let j be 0.
|
||||
// 8. Repeat, while j < itemCount,
|
||||
// a. Perform ! Set(obj, ! ToString((j)), sortedList[j], true).
|
||||
// b. Set j to j + 1.
|
||||
for (int j = 0; j < itemCount; j++) {
|
||||
valueHandle.Update(sortedList->Get(j));
|
||||
ElementAccessor::Set(thread, thisObj, j, valueHandle, needTransition);
|
||||
}
|
||||
// 9. NOTE: The call to SortIndexedProperties in step 5 uses SKIP-HOLES.The remaining indices are deleted to
|
||||
// preserve the number of holes that were detected and excluded from the sort.
|
||||
// 10. Repeat, while j < len,
|
||||
// a. Perform ? DeletePropertyOrThrow(obj, ! ToString((j))).
|
||||
// b. Set j to j + 1.
|
||||
valueHandle.Update(JSTaggedValue::Hole());
|
||||
for (int j = itemCount; j < len; j++) {
|
||||
ElementAccessor::Set(thread, thisObj, j, valueHandle, needTransition);
|
||||
}
|
||||
JSHandle<JSArray>::Cast(thisObj)->SetArrayLength(thread, newLength);
|
||||
return thisObj.GetTaggedValue();
|
||||
}
|
||||
|
||||
JSTaggedValue JSStableArray::Sort(JSThread *thread, const JSHandle<JSTaggedValue> &thisObjVal,
|
||||
const JSHandle<JSTaggedValue> &callbackFnHandle)
|
||||
{
|
||||
JSArray::SortElementsByObject(thread, thisObj, callbackFnHandle);
|
||||
return thisObj.GetTaggedValue();
|
||||
// 3. Let len be ?LengthOfArrayLike(obj).
|
||||
uint32_t len = JSHandle<JSArray>::Cast(thisObjVal)->GetArrayLength();
|
||||
// ReturnIfAbrupt(len).
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
// If len is 0 or 1, no need to sort
|
||||
if (len == 0 || len == 1) {
|
||||
return thisObjVal.GetTaggedValue();
|
||||
}
|
||||
if (callbackFnHandle->IsUndefined()) {
|
||||
JSArray::SortElementsByObject(thread, JSHandle<JSObject>::Cast(thisObjVal), callbackFnHandle);
|
||||
return thisObjVal.GetTaggedValue();
|
||||
}
|
||||
JSHandle<TaggedArray> sortedList = JSStableArray::SortIndexedProperties(
|
||||
thread, thisObjVal, len, callbackFnHandle, base::HolesType::SKIP_HOLES);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
if (thisObjVal->IsStableJSArray(thread)) {
|
||||
CopySortedListToReceiver(thread, thisObjVal, sortedList, len);
|
||||
} else {
|
||||
JSArray::CopySortedListToReceiver(thread, thisObjVal, sortedList, len);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
}
|
||||
return thisObjVal.GetTaggedValue();
|
||||
}
|
||||
|
||||
JSTaggedValue JSStableArray::Fill(JSThread *thread, const JSHandle<JSObject> &thisObj,
|
||||
|
@ -16,6 +16,7 @@
|
||||
#ifndef ECMASCRIPT_JS_STABLE_ARRAY_H
|
||||
#define ECMASCRIPT_JS_STABLE_ARRAY_H
|
||||
|
||||
#include "ecmascript/base/array_helper.h"
|
||||
#include "ecmascript/base/typed_array_helper.h"
|
||||
#include "ecmascript/js_array.h"
|
||||
#include "ecmascript/js_dataview.h"
|
||||
@ -86,9 +87,13 @@ public:
|
||||
JSHandle<JSTaggedValue> callbackFnHandle,
|
||||
JSMutableHandle<JSTaggedValue> accumulator, int64_t &k, int64_t &len);
|
||||
static JSTaggedValue Slice(JSThread *thread, JSHandle<JSObject> thisObjHandle, int64_t &k, int64_t &count);
|
||||
|
||||
static JSTaggedValue Sort(JSThread *thread, const JSHandle<JSObject> &thisObj,
|
||||
static JSHandle<TaggedArray> SortIndexedProperties(JSThread *thread, const JSHandle<JSTaggedValue> &thisObj,
|
||||
int64_t len, const JSHandle<JSTaggedValue> &callbackFnHandle,
|
||||
base::HolesType holes);
|
||||
static JSTaggedValue Sort(JSThread *thread, const JSHandle<JSTaggedValue> &thisObjVal,
|
||||
const JSHandle<JSTaggedValue> &callbackFnHandle);
|
||||
static JSTaggedValue CopySortedListToReceiver(JSThread *thread, const JSHandle<JSTaggedValue> &thisObjVal,
|
||||
JSHandle<TaggedArray> sortedList, uint32_t len);
|
||||
static JSTaggedValue Fill(JSThread *thread, const JSHandle<JSObject> &thisObj,
|
||||
const JSHandle<JSTaggedValue> &value,
|
||||
int64_t start, int64_t end, int64_t len);
|
||||
|
@ -3902,6 +3902,10 @@ DEF_RUNTIME_STUBS(LocaleCompareCacheable)
|
||||
JSHandle<JSTaggedValue> locales = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
|
||||
JSHandle<EcmaString> thisHandle = GetHArg<EcmaString>(argv, argc, 1); // 1: means the first parameter
|
||||
JSHandle<EcmaString> thatHandle = GetHArg<EcmaString>(argv, argc, 2); // 2: means the second parameter
|
||||
#if ENABLE_NEXT_OPTIMIZATION
|
||||
const CompareStringsOption csOption = JSCollator::CompareStringsOptionFor(thread, locales);
|
||||
JSTaggedValue result = JSCollator::FastCachedCompareStrings(thread, locales, thisHandle, thatHandle, csOption);
|
||||
#else
|
||||
auto collator = JSCollator::GetCachedIcuCollator(thread, locales);
|
||||
JSTaggedValue result = JSTaggedValue::Undefined();
|
||||
if (collator != nullptr) {
|
||||
@ -3909,6 +3913,7 @@ DEF_RUNTIME_STUBS(LocaleCompareCacheable)
|
||||
thread, locales);
|
||||
result = JSCollator::CompareStrings(thread, collator, thisHandle, thatHandle, csOption);
|
||||
}
|
||||
#endif
|
||||
return result.GetRawData();
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,10 @@
|
||||
|
||||
group("ark_aot_builtin_inlining_String_test") {
|
||||
testonly = true
|
||||
test_list = [ "CharCodeAt" ]
|
||||
test_list = [
|
||||
"CharCodeAt",
|
||||
"LocaleCompare",
|
||||
]
|
||||
|
||||
deps = []
|
||||
foreach(test, test_list) {
|
||||
|
17
test/aottest/builtin_inlining/String/LocaleCompare/BUILD.gn
Normal file
17
test/aottest/builtin_inlining/String/LocaleCompare/BUILD.gn
Normal file
@ -0,0 +1,17 @@
|
||||
# Copyright (c) 2024 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.
|
||||
|
||||
import("//arkcompiler/ets_runtime/test/test_helper.gni")
|
||||
|
||||
host_aot_builtin_inlining_test_action("builtinStringLocaleCompare") {
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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.
|
||||
*/
|
||||
declare function print(arg:any):string;
|
||||
|
||||
function func() {
|
||||
let a = "hijklmn";
|
||||
let b = "abcdefg";
|
||||
//aot: [trace] aot inline function name: #*#func@builtinStringLocaleCompare caller function name: func_main_0@builtinStringLocaleCompare
|
||||
//: 1
|
||||
print(a.localeCompare(b));
|
||||
}
|
||||
func();
|
@ -376,3 +376,110 @@ print("sort Test Success!");
|
||||
array1[0] = `g`;
|
||||
print(array1.toSorted());
|
||||
}
|
||||
|
||||
// Test sort if array has hole
|
||||
function HoleSort()
|
||||
{
|
||||
let sortNumber= [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
sortNumber.push(parseInt(i));
|
||||
}
|
||||
sortNumber[100] = parseInt(100);
|
||||
print(sortNumber.length);
|
||||
print(sortNumber);
|
||||
|
||||
sortNumber.sort((a, b) => {
|
||||
return a < b;
|
||||
});
|
||||
|
||||
print(sortNumber.length);
|
||||
print(sortNumber);
|
||||
}
|
||||
|
||||
HoleSort();
|
||||
|
||||
let sortNumber = [0,3,2,,4,5,6];
|
||||
sortNumber.sort((a,b) => {
|
||||
sortNumber[10000] = 1;
|
||||
return a-b;
|
||||
});
|
||||
print(sortNumber.length);
|
||||
print(sortNumber);
|
||||
|
||||
let sortNumber2 = [0,3,2,,4,5,6];
|
||||
sortNumber2.sort((a,b) => {
|
||||
sortNumber2[3] = 1;
|
||||
return a-b;
|
||||
});
|
||||
print(sortNumber2.length);
|
||||
print(sortNumber2);
|
||||
|
||||
let sortNumber3 = [0,3,2,,4,5,6];
|
||||
sortNumber3.sort((a,b) => {
|
||||
sortNumber3 = 1; // stlexvar
|
||||
return a-b;
|
||||
});
|
||||
print(sortNumber3.length);
|
||||
print(sortNumber3[0]);
|
||||
print(sortNumber3[2]);
|
||||
print(sortNumber3[4]);
|
||||
print(sortNumber3[6]);
|
||||
|
||||
let sortNumber4 = [0,3,2,,4,5,6];
|
||||
sortNumber4.sort((a,b) => {
|
||||
sortNumber4.push(1);
|
||||
return a-b;
|
||||
});
|
||||
print(sortNumber4.length);
|
||||
print(sortNumber4[0]);
|
||||
print(sortNumber4[2]);
|
||||
print(sortNumber4[4]);
|
||||
print(sortNumber4[6]);
|
||||
|
||||
let sortNumber5 = [-1, 2, 4, 1, 0];
|
||||
sortNumber5.sort((x, y) => {
|
||||
Object.defineProperty(sortNumber5, '2', {
|
||||
get() {
|
||||
print("get second element:");
|
||||
return this.value;
|
||||
},
|
||||
set(newValue) {
|
||||
print("set second element:", newValue);
|
||||
this.value = newValue;
|
||||
}
|
||||
});
|
||||
return x - y;
|
||||
})
|
||||
print(sortNumber5.length);
|
||||
print(sortNumber5.value);
|
||||
print(sortNumber5);
|
||||
|
||||
let sortNumber6 = [-1, 2, 4, 1, 0];
|
||||
sortNumber6.sort((x, y) => {
|
||||
Object.defineProperty(sortNumber6, '100', {
|
||||
get() {
|
||||
print("get 10000th element:");
|
||||
return this.value;
|
||||
},
|
||||
set(newValue) {
|
||||
print("set 10000th element:", newValue);
|
||||
this.value = newValue;
|
||||
},
|
||||
configurable: true // 允许重新定义
|
||||
});
|
||||
return x - y;
|
||||
})
|
||||
print(sortNumber6.length);
|
||||
print(sortNumber6.value);
|
||||
print(sortNumber6);
|
||||
|
||||
let sortNumber7 = [0,3,2,,4,5,6];
|
||||
sortNumber7.sort((a,b) => {
|
||||
sortNumber7.pop();
|
||||
return a-b;
|
||||
});
|
||||
print(sortNumber7.length);
|
||||
print(sortNumber7[0]);
|
||||
print(sortNumber7[2]);
|
||||
print(sortNumber7[4]);
|
||||
print(sortNumber7[6]);
|
||||
|
File diff suppressed because one or more lines are too long
@ -1613,6 +1613,10 @@ template("host_aot_js_test_action") {
|
||||
" --aot-file=" + rebase_path(_test_aot_arg_litecg_) +
|
||||
" --asm-interpreter=true" + " --entry-point=${_target_name_}"
|
||||
|
||||
_icu_data_path_options_ =
|
||||
" --icu-data-path=" + rebase_path("//third_party/icu/ohos_icu4j/data")
|
||||
_aot_run_options_ += _icu_data_path_options_
|
||||
|
||||
if (defined(invoker.is_enable_enableArkTools) &&
|
||||
invoker.is_enable_enableArkTools) {
|
||||
_aot_run_options_ += " --enable-ark-tools=true"
|
||||
@ -1682,6 +1686,10 @@ template("host_aot_js_test_action") {
|
||||
" --aot-file=" + rebase_path(_test_aot_arg_litecg_) +
|
||||
" --asm-interpreter=true" + " --entry-point=${_target_name_}"
|
||||
|
||||
_icu_data_path_options_ =
|
||||
" --icu-data-path=" + rebase_path("//third_party/icu/ohos_icu4j/data")
|
||||
_aot_run_options_ += _icu_data_path_options_
|
||||
|
||||
if (defined(invoker.is_enable_enableArkTools) &&
|
||||
invoker.is_enable_enableArkTools) {
|
||||
_aot_run_options_ += " --enable-ark-tools=true"
|
||||
@ -1880,6 +1888,10 @@ template("host_aot_js_test_action") {
|
||||
" --aot-file=" + rebase_path(_test_aot_arg_litecg_) +
|
||||
" --asm-interpreter=true" + " --entry-point=${_target_name_}"
|
||||
|
||||
_icu_data_path_options_ =
|
||||
" --icu-data-path=" + rebase_path("//third_party/icu/ohos_icu4j/data")
|
||||
_aot_run_options_ += _icu_data_path_options_
|
||||
|
||||
if (defined(invoker.is_enable_enableArkTools) &&
|
||||
invoker.is_enable_enableArkTools) {
|
||||
_aot_run_options_ += " --enable-ark-tools=true"
|
||||
@ -2513,6 +2525,10 @@ template("host_aot_test_action") {
|
||||
" --enable-pgo-profiler=true" + " --compiler-pgo-profiler-path=" +
|
||||
rebase_path(_test_profiler_path_)
|
||||
|
||||
_icu_data_path_options_ =
|
||||
" --icu-data-path=" + rebase_path("//third_party/icu/ohos_icu4j/data")
|
||||
_aot_run_options_ += _icu_data_path_options_
|
||||
|
||||
if (defined(invoker.is_enable_enableArkTools) &&
|
||||
invoker.is_enable_enableArkTools) {
|
||||
_aot_run_options_ += " --enable-ark-tools=true"
|
||||
|
Loading…
Reference in New Issue
Block a user