From b4c01e436cedd82ad6e67bfec0ad4cc9e8361dcb Mon Sep 17 00:00:00 2001 From: chenjingxiang Date: Mon, 1 Sep 2025 20:17:32 +0800 Subject: [PATCH] Fix Array.prototype.every Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/ICVRKV?from=project-issue Signed-off-by: chenjingxiang Change-Id: I48cf3988ef03ad3aa6de60f2a9c1eb016844391e --- .../builtins/builtins_array_stub_builder.cpp | 26 ++++----------- ...s_array_stub_builder_next_optimization.cpp | 15 +-------- ecmascript/js_stable_array.cpp | 9 ++++-- test/moduletest/arrayEvery/arrayEvery.js | 32 +++++++++++++++++++ test/moduletest/arrayEvery/expect_output.txt | 6 ++++ 5 files changed, 52 insertions(+), 36 deletions(-) diff --git a/ecmascript/compiler/builtins/builtins_array_stub_builder.cpp b/ecmascript/compiler/builtins/builtins_array_stub_builder.cpp index 81ce3b244e..ef8fa25725 100644 --- a/ecmascript/compiler/builtins/builtins_array_stub_builder.cpp +++ b/ecmascript/compiler/builtins/builtins_array_stub_builder.cpp @@ -4237,7 +4237,6 @@ void BuiltinsArrayStubBuilder::Every(GateRef glue, GateRef thisValue, GateRef nu DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole()); Label loopHead(env); Label loopEnd(env); - Label next(env); Label loopExit(env); Jump(&loopHead); LoopBegin(&loopHead); @@ -4250,10 +4249,11 @@ void BuiltinsArrayStubBuilder::Every(GateRef glue, GateRef thisValue, GateRef nu Label notHasException0(env); Label hasException1(env); Label notHasException1(env); + Label doCall(env); BRANCH(IsStableJSArray(glue, thisValue), &nextStep, &thisNotStable); Bind(&nextStep); - BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit); - Bind(&next); + BRANCH_LIKELY(Int64LessThan(*i, ZExtInt32ToInt64(GetArrayLength(thisValue))), &doCall, &loopExit); + Bind(&doCall); kValue = GetTaggedValueWithElementsKind(glue, thisValue, *i); BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch); Bind(&kValueIsHole); @@ -4288,23 +4288,11 @@ void BuiltinsArrayStubBuilder::Every(GateRef glue, GateRef thisValue, GateRef nu } Bind(¬HasException1); { - DEFVARIABLE(newLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue))); - Label changeThisLen(env); - Label afterChangeLen(env); Label retValueIsFalse(env); - BRANCH(Int64LessThan(*newLen, *thisArrLen), &changeThisLen, &afterChangeLen); - Bind(&changeThisLen); - { - thisArrLen = *newLen; - Jump(&afterChangeLen); - } - Bind(&afterChangeLen); - { - BRANCH(TaggedIsFalse(FastToBoolean(glue, retValue)), &retValueIsFalse, &loopEnd); - Bind(&retValueIsFalse); - result->WriteVariable(TaggedFalse()); - Jump(exit); - } + BRANCH(TaggedIsFalse(FastToBoolean(glue, retValue)), &retValueIsFalse, &loopEnd); + Bind(&retValueIsFalse); + result->WriteVariable(TaggedFalse()); + Jump(exit); } } } diff --git a/ecmascript/compiler/builtins/builtins_array_stub_builder_next_optimization.cpp b/ecmascript/compiler/builtins/builtins_array_stub_builder_next_optimization.cpp index ecd6dea47f..9299ca1034 100644 --- a/ecmascript/compiler/builtins/builtins_array_stub_builder_next_optimization.cpp +++ b/ecmascript/compiler/builtins/builtins_array_stub_builder_next_optimization.cpp @@ -1479,20 +1479,7 @@ void BuiltinsArrayStubBuilder::EveryOptimised(GateRef glue, GateRef thisValue, G BRANCH_LIKELY(IsJsArray(glue, thisValue), &isJsArray, slowPath); Bind(&isJsArray); result->WriteVariable(TaggedTrue()); - GateRef isStandard = LogicOrBuilder(env) - .Or(HasConstructor(glue, thisValue)) - .Or(BoolNot(IsStableJSArray(glue, thisValue))) - .Or(IsJsCOWArray(glue, thisValue)) - .Done(); - BRANCH_NO_WEIGHT(isStandard, &standardPath, &compatiblePath); - Bind(&standardPath); - { - VisitAll(glue, thisValue, numArgs, result, exit, slowPath, {Option::MethodEvery, Option::Standard}); - } - Bind(&compatiblePath); - { - VisitAll(glue, thisValue, numArgs, result, exit, slowPath, {Option::MethodEvery, Option::Compatible5_0_0}); - } + VisitAll(glue, thisValue, numArgs, result, exit, slowPath, {Option::MethodEvery, Option::Standard}); }; void BuiltinsArrayStubBuilder::SomeOptimised(GateRef glue, GateRef thisValue, GateRef numArgs, diff --git a/ecmascript/js_stable_array.cpp b/ecmascript/js_stable_array.cpp index 6ad5a1df3f..40bb6e3311 100644 --- a/ecmascript/js_stable_array.cpp +++ b/ecmascript/js_stable_array.cpp @@ -872,6 +872,12 @@ JSTaggedValue JSStableArray::HandleEveryOfStable(JSThread *thread, JSHandle kValue(thread, JSTaggedValue::Undefined()); while (k < len) { + // thisObj.length may change and needs to be rechecked. If the thisObj is stableArray and k >= current length, + // thisObj will have no chance to change and we can directly exit the entire loop. + if (UNLIKELY(k >= base::ArrayHelper::GetArrayLength(thread, thisObjVal))) { + k = len; + break; + } // Elements of thisObjHandle may change. kValue.Update(ElementAccessor::Get(thread, thisObjHandle, k)); if (!kValue.GetTaggedValue().IsHole()) { @@ -881,9 +887,6 @@ JSTaggedValue JSStableArray::HandleEveryOfStable(JSThread *thread, JSHandleSetCallArg(kValue.GetTaggedValue(), JSTaggedValue(k), thisObjVal.GetTaggedValue()); callResult = JSFunction::Call(info); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - if (ElementAccessor::GetElementsLength(thread, thisObjHandle) < len) { - len = ElementAccessor::GetElementsLength(thread, thisObjHandle); - } } else if (JSTaggedValue::HasProperty(thread, thisObjVal, k)) { JSHandle kValue1 = JSArray::FastGetPropertyByValue(thread, thisObjVal, k); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); diff --git a/test/moduletest/arrayEvery/arrayEvery.js b/test/moduletest/arrayEvery/arrayEvery.js index 61dbe803a9..675b87cba4 100644 --- a/test/moduletest/arrayEvery/arrayEvery.js +++ b/test/moduletest/arrayEvery/arrayEvery.js @@ -204,6 +204,38 @@ const testCases = [ }); print("Log:", JSON.stringify(log), "Result:", result); }, + + () => { + let arr = new Array(10000); + arr.fill(1); + const res = arr.every((e, idx) => { + if (idx == 1) { + for (let j = 0; j < 9990; ++j) { + arr.pop(); + } + } + if (idx == 2) { + arr.push(100); + } + return e < 50; + }, 0); + print(res); + }, + + () => { + let arr = new Array(10000); + arr.fill(1); + const res = arr.every((e, idx) => { + if (idx == 1) { + for (let j = 0; j < 9990; ++j) { + arr.pop(); + } + arr[1100] = 51; + } + return e < 50; + }, 0); + print(res); + } ]; testCases.forEach((test, i) => { diff --git a/test/moduletest/arrayEvery/expect_output.txt b/test/moduletest/arrayEvery/expect_output.txt index 082bb3c1ee..67bc68ba3c 100644 --- a/test/moduletest/arrayEvery/expect_output.txt +++ b/test/moduletest/arrayEvery/expect_output.txt @@ -68,3 +68,9 @@ Log: [{"value":{"id":1},"index":0,"array":[{"id":1},{"id":2}]},{"value":{"id":2} Test case 19: Log: [{"value":1,"index":0,"array":[1,2,3,4]},{"value":2,"index":1,"array":[1,2,3,4]},{"value":3,"index":2,"array":[1,2,3]},{"value":5,"index":3,"array":[1,2,3,5]}] Result: true --- +Test case 20: +false +--- +Test case 21: +false +--- \ No newline at end of file -- Gitee