mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-27 12:10:47 +00:00
Array ReduceRight IR 化
Signed-off-by: liujia178 <liujia178@huawei.com>
This commit is contained in:
parent
bd96654b3f
commit
69499c2d59
@ -1826,6 +1826,17 @@ JSTaggedValue BuiltinsArray::ReduceRight(EcmaRuntimeCallInfo *argv)
|
||||
// e. Decrease k by 1.
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
JSTaggedValue callResult = JSTaggedValue::Undefined();
|
||||
|
||||
JSHandle<JSTaggedValue> thisArgHandle = globalConst->GetHandledUndefined();
|
||||
if (thisObjVal->IsStableJSArray(thread)) {
|
||||
JSTaggedValue ret = JSStableArray::HandleReduceRightOfStable(thread, thisObjHandle,
|
||||
callbackFnHandle, accumulator, thisArgHandle, k);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
if (ret.ToBoolean()) {
|
||||
return accumulator.GetTaggedValue();
|
||||
}
|
||||
}
|
||||
|
||||
while (k >= 0) {
|
||||
key.Update(JSTaggedValue(k));
|
||||
bool exists = (thisHandle->IsTypedArray() || JSTaggedValue::HasProperty(thread, thisObjVal, key));
|
||||
@ -1833,7 +1844,6 @@ JSTaggedValue BuiltinsArray::ReduceRight(EcmaRuntimeCallInfo *argv)
|
||||
if (exists) {
|
||||
JSHandle<JSTaggedValue> kValue = JSArray::FastGetPropertyByValue(thread, thisObjVal, key);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
JSHandle<JSTaggedValue> thisArgHandle = globalConst->GetHandledUndefined();
|
||||
const uint32_t argsLength = 4; // 4: «accumulator, kValue, k, O»
|
||||
JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
|
||||
EcmaRuntimeCallInfo *info =
|
||||
|
@ -81,7 +81,7 @@
|
||||
/* Array.prototype.reduce ( callbackfn [ , initialValue ] ) */ \
|
||||
V("reduce", Reduce, 1, ArrayReduce) \
|
||||
/* Array.prototype.reduceRight ( callbackfn [ , initialValue ] ) */ \
|
||||
V("reduceRight", ReduceRight, 1, INVALID) \
|
||||
V("reduceRight", ReduceRight, 1, ArrayReduceRight) \
|
||||
/* Array.prototype.reverse ( ) */ \
|
||||
V("reverse", Reverse, 0, ArrayReverse) \
|
||||
/* Array.prototype.shift ( ) */ \
|
||||
|
@ -2535,6 +2535,211 @@ void BuiltinsArrayStubBuilder::Every(GateRef glue, GateRef thisValue, GateRef nu
|
||||
}
|
||||
}
|
||||
|
||||
void BuiltinsArrayStubBuilder::ReduceRight(GateRef glue, GateRef thisValue, GateRef numArgs,
|
||||
Variable *result, Label *exit, Label *slowPath)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label thisExists(env);
|
||||
Label isHeapObject(env);
|
||||
Label isJsArray(env);
|
||||
Label defaultConstr(env);
|
||||
Label isStability(env);
|
||||
Label notCOWArray(env);
|
||||
Label equalCls(env);
|
||||
BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
|
||||
Bind(&thisExists);
|
||||
BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
|
||||
Bind(&isHeapObject);
|
||||
BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
|
||||
Bind(&isJsArray);
|
||||
BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
|
||||
Bind(&defaultConstr);
|
||||
BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
|
||||
Bind(&isStability);
|
||||
BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray);
|
||||
Bind(¬COWArray);
|
||||
GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
|
||||
GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
|
||||
auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
|
||||
GateRef intialHClass = Load(VariableType::JS_ANY(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
|
||||
GateRef arrayCls = LoadHClass(thisValue);
|
||||
BRANCH(Equal(intialHClass, arrayCls), &equalCls, slowPath);
|
||||
Bind(&equalCls);
|
||||
|
||||
DEFVARIABLE(thisLen, VariableType::INT32(), Int32(0));
|
||||
DEFVARIABLE(accumulator, VariableType::JS_ANY(), Undefined());
|
||||
DEFVARIABLE(k, VariableType::INT32(), Int32(0));
|
||||
Label atLeastOneArg(env);
|
||||
Label callbackFnHandleHeapObject(env);
|
||||
Label callbackFnHandleCallable(env);
|
||||
Label noTypeError(env);
|
||||
Label updateAccumulator(env);
|
||||
Label thisIsStable(env);
|
||||
Label thisNotStable(env);
|
||||
thisLen = GetArrayLength(thisValue);
|
||||
BRANCH(Int64GreaterThanOrEqual(numArgs, IntPtr(1)), &atLeastOneArg, slowPath);
|
||||
Bind(&atLeastOneArg);
|
||||
GateRef callbackFnHandle = GetCallArg0(numArgs);
|
||||
BRANCH(TaggedIsHeapObject(callbackFnHandle), &callbackFnHandleHeapObject, slowPath);
|
||||
Bind(&callbackFnHandleHeapObject);
|
||||
BRANCH(IsCallable(callbackFnHandle), &callbackFnHandleCallable, slowPath);
|
||||
Bind(&callbackFnHandleCallable);
|
||||
GateRef thisLenIsZero = Int32Equal(*thisLen, Int32(0));
|
||||
GateRef numArgsLessThanTwo = Int64LessThan(numArgs, IntPtr(2)); // 2: callbackFn initialValue
|
||||
BRANCH(BoolAnd(thisLenIsZero, numArgsLessThanTwo), slowPath, &noTypeError);
|
||||
Bind(&noTypeError);
|
||||
k = Int32Sub(*thisLen, Int32(1));
|
||||
BRANCH(Int64Equal(numArgs, IntPtr(2)), &updateAccumulator, slowPath); // 2: callbackFn initialValue
|
||||
Bind(&updateAccumulator);
|
||||
accumulator = GetCallArg1(numArgs);
|
||||
Jump(&thisIsStable);
|
||||
|
||||
Bind(&thisIsStable);
|
||||
{
|
||||
DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
|
||||
GateRef argsLength = Int32(4);
|
||||
NewObjectStubBuilder newBuilder(this);
|
||||
GateRef argList = newBuilder.NewTaggedArray(glue, argsLength);
|
||||
Label loopHead(env);
|
||||
Label next(env);
|
||||
Label loopEnd(env);
|
||||
Label loopExit(env);
|
||||
Jump(&loopHead);
|
||||
LoopBegin(&loopHead);
|
||||
{
|
||||
Label nextStep(env);
|
||||
Label kValueIsHole(env);
|
||||
Label callDispatch(env);
|
||||
Label hasProperty(env);
|
||||
Label hasException0(env);
|
||||
Label notHasException0(env);
|
||||
Label hasException1(env);
|
||||
Label notHasException1(env);
|
||||
GateRef newLen = GetArrayLength(thisValue);
|
||||
BRANCH(BoolAnd(IsStableJSArray(glue, thisValue), Int32Equal(*thisLen, newLen)),
|
||||
&nextStep, &thisNotStable);
|
||||
Bind(&nextStep);
|
||||
BRANCH(Int32GreaterThanOrEqual(*k, Int32(0)), &next, &loopExit);
|
||||
Bind(&next);
|
||||
kValue = GetTaggedValueWithElementsKind(thisValue, *k);
|
||||
BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch);
|
||||
Bind(&kValueIsHole);
|
||||
{
|
||||
GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*k) });
|
||||
BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd);
|
||||
Bind(&hasProperty);
|
||||
kValue = FastGetPropertyByIndex(glue, thisValue, *k, ProfileOperation());
|
||||
BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
|
||||
Bind(&hasException0);
|
||||
result->WriteVariable(Exception());
|
||||
Jump(exit);
|
||||
Bind(¬HasException0);
|
||||
BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch);
|
||||
}
|
||||
Bind(&callDispatch);
|
||||
{
|
||||
// callback param 0: accumulator
|
||||
SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(0), *accumulator);
|
||||
// callback param 1: currentValue
|
||||
SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(1), *kValue);
|
||||
// callback param 2: index
|
||||
SetValueToTaggedArray(VariableType::INT32(), glue, argList, Int32(2), IntToTaggedInt(*k));
|
||||
// callback param 3: array
|
||||
SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(3), thisValue);
|
||||
GateRef argv = PtrAdd(argList, IntPtr(TaggedArray::DATA_OFFSET));
|
||||
GateRef callResult = JSCallDispatch(glue, callbackFnHandle, argsLength, 0,
|
||||
Circuit::NullGate(), JSCallMode::CALL_THIS_ARGV_WITH_RETURN,
|
||||
{argsLength, argv, Undefined()});
|
||||
BRANCH(HasPendingException(glue), &hasException1, ¬HasException1);
|
||||
Bind(&hasException1);
|
||||
{
|
||||
result->WriteVariable(Exception());
|
||||
Jump(exit);
|
||||
}
|
||||
|
||||
Bind(¬HasException1);
|
||||
{
|
||||
accumulator = callResult;
|
||||
Jump(&loopEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
Bind(&loopEnd);
|
||||
k = Int32Sub(*k, Int32(1));
|
||||
LoopEnd(&loopHead);
|
||||
Bind(&loopExit);
|
||||
result->WriteVariable(*accumulator);
|
||||
Jump(exit);
|
||||
}
|
||||
|
||||
Bind(&thisNotStable);
|
||||
{
|
||||
DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
|
||||
GateRef argsLength = Int32(4);
|
||||
NewObjectStubBuilder newBuilder(this);
|
||||
GateRef argList = newBuilder.NewTaggedArray(glue, argsLength);
|
||||
Label loopHead(env);
|
||||
Label next(env);
|
||||
Label loopEnd(env);
|
||||
Label loopExit(env);
|
||||
Jump(&loopHead);
|
||||
LoopBegin(&loopHead);
|
||||
{
|
||||
Label hasProperty(env);
|
||||
Label hasException0(env);
|
||||
Label notHasException0(env);
|
||||
Label callDispatch(env);
|
||||
Label hasException1(env);
|
||||
Label notHasException1(env);
|
||||
BRANCH(Int32GreaterThanOrEqual(*k, Int32(0)), &next, &loopExit);
|
||||
Bind(&next);
|
||||
GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*k) });
|
||||
BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd);
|
||||
Bind(&hasProperty);
|
||||
kValue = FastGetPropertyByIndex(glue, thisValue, *k, ProfileOperation());
|
||||
BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
|
||||
Bind(&hasException0);
|
||||
result->WriteVariable(Exception());
|
||||
Jump(exit);
|
||||
Bind(¬HasException0);
|
||||
BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch);
|
||||
Bind(&callDispatch);
|
||||
{
|
||||
// callback param 0: accumulator
|
||||
SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(0), *accumulator);
|
||||
// callback param 1: currentValue
|
||||
SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(1), *kValue);
|
||||
// callback param 2: index
|
||||
SetValueToTaggedArray(VariableType::INT32(), glue, argList, Int32(2), IntToTaggedInt(*k));
|
||||
// callback param 3: array
|
||||
SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(3), thisValue);
|
||||
GateRef argv = PtrAdd(argList, IntPtr(TaggedArray::DATA_OFFSET));
|
||||
GateRef callResult = JSCallDispatch(glue, callbackFnHandle, argsLength, 0,
|
||||
Circuit::NullGate(), JSCallMode::CALL_THIS_ARGV_WITH_RETURN,
|
||||
{argsLength, argv, Undefined()});
|
||||
BRANCH(HasPendingException(glue), &hasException1, ¬HasException1);
|
||||
Bind(&hasException1);
|
||||
{
|
||||
result->WriteVariable(Exception());
|
||||
Jump(exit);
|
||||
}
|
||||
|
||||
Bind(¬HasException1);
|
||||
{
|
||||
accumulator = callResult;
|
||||
Jump(&loopEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
Bind(&loopEnd);
|
||||
k = Int32Sub(*k, Int32(1));
|
||||
LoopEnd(&loopHead);
|
||||
Bind(&loopExit);
|
||||
result->WriteVariable(*accumulator);
|
||||
Jump(exit);
|
||||
}
|
||||
}
|
||||
|
||||
void BuiltinsArrayStubBuilder::FindLastIndex(GateRef glue, GateRef thisValue, GateRef numArgs,
|
||||
Variable *result, Label *exit, Label *slowPath)
|
||||
{
|
||||
|
@ -83,6 +83,8 @@ public:
|
||||
void Every(GateRef glue, GateRef thisValue, GateRef numArgs,
|
||||
Variable *result, Label *exit, Label *slowPath);
|
||||
|
||||
void ReduceRight(GateRef glue, GateRef thisValue, GateRef numArgs, Variable *result, Label *exit, Label *slowPath);
|
||||
|
||||
void Map(GateRef glue, GateRef thisValue, GateRef numArgs, Variable *result, Label *exit, Label *slowPath);
|
||||
|
||||
void FindLastIndex(GateRef glue, GateRef thisValue, GateRef numArgs,
|
||||
|
@ -84,6 +84,7 @@ namespace panda::ecmascript::kungfu {
|
||||
V(ArrayIncludes) \
|
||||
V(ArrayFrom) \
|
||||
V(ArraySplice) \
|
||||
V(ArrayReduceRight) \
|
||||
V(ArrayCopyWithin) \
|
||||
V(ArrayEvery) \
|
||||
V(ArrayFindLastIndex) \
|
||||
|
@ -343,6 +343,7 @@ DECLARE_BUILTINS(Array##Method)
|
||||
V(Every, JS_ANY) \
|
||||
V(FindLastIndex, JS_ANY) \
|
||||
V(FindLast, JS_ANY) \
|
||||
V(ReduceRight, JS_ANY) \
|
||||
V(Map, JS_ANY)
|
||||
|
||||
DECLARE_BUILTINS(SORT)
|
||||
|
@ -1226,4 +1226,54 @@ JSTaggedValue JSStableArray::HandleFindLastOfStable(JSThread *thread, JSHandle<J
|
||||
}
|
||||
return callResult;
|
||||
}
|
||||
|
||||
JSTaggedValue JSStableArray::HandleReduceRightOfStable(JSThread *thread, JSHandle<JSObject> thisObjHandle,
|
||||
JSHandle<JSTaggedValue> callbackFnHandle,
|
||||
JSMutableHandle<JSTaggedValue> &accumulator,
|
||||
JSHandle<JSTaggedValue> thisArgHandle, int64_t &k)
|
||||
{
|
||||
JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
|
||||
JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Hole());
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
JSTaggedValue callResult = JSTaggedValue::Undefined();
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
const int32_t argsLength = 4; // 4: «accumulator, kValue, k, O»
|
||||
int64_t len = static_cast<int64_t>(base::ArrayHelper::GetArrayLength(thread, thisObjVal));
|
||||
while (k >= 0) {
|
||||
key.Update(JSTaggedValue(k));
|
||||
kValue.Update(ElementAccessor::Get(thisObjHandle, k));
|
||||
if (!kValue.GetTaggedValue().IsHole()) {
|
||||
EcmaRuntimeCallInfo *info =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
info->SetCallArg(accumulator.GetTaggedValue(), kValue.GetTaggedValue(),
|
||||
key.GetTaggedValue(), thisObjVal.GetTaggedValue());
|
||||
callResult = JSFunction::Call(info);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
accumulator.Update(callResult);
|
||||
} else {
|
||||
bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, key);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
if (exists) {
|
||||
auto res = JSArray::FastGetPropertyByValue(thread, thisObjVal, key).GetTaggedValue();
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
kValue.Update(res);
|
||||
EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle,
|
||||
thisArgHandle, undefined, argsLength);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
info->SetCallArg(accumulator.GetTaggedValue(), kValue.GetTaggedValue(),
|
||||
key.GetTaggedValue(), thisObjVal.GetTaggedValue());
|
||||
callResult = JSFunction::Call(info);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
accumulator.Update(callResult);
|
||||
}
|
||||
}
|
||||
k--;
|
||||
int64_t newLen = static_cast<int64_t>(base::ArrayHelper::GetArrayLength(thread, thisObjVal));
|
||||
if (!thisObjVal->IsStableJSArray(thread) || newLen != len) {
|
||||
return base::BuiltinsBase::GetTaggedBoolean(false);
|
||||
}
|
||||
}
|
||||
return base::BuiltinsBase::GetTaggedBoolean(true);
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -79,6 +79,10 @@ public:
|
||||
JSHandle<JSTaggedValue> callbackFnHandle,
|
||||
JSHandle<JSTaggedValue> thisArgHandle,
|
||||
JSMutableHandle<JSTaggedValue> &kValue, int64_t &k);
|
||||
static JSTaggedValue HandleReduceRightOfStable(JSThread *thread, JSHandle<JSObject> thisObjHandle,
|
||||
JSHandle<JSTaggedValue> callbackFnHandle,
|
||||
JSMutableHandle<JSTaggedValue> &accumulator,
|
||||
JSHandle<JSTaggedValue> thisArgHandle, int64_t &k);
|
||||
|
||||
private:
|
||||
static void SetSepValue(JSHandle<EcmaString> sepStringHandle, int &sep, uint32_t &sepLength);
|
||||
|
@ -530,4 +530,37 @@ print(result_every2);
|
||||
var result_every3 = arr_every3.every(testEvery);
|
||||
print(result_every3);
|
||||
var result_every4 = arr_every4.every(testEvery4);
|
||||
print(result_every4);
|
||||
print(result_every4);
|
||||
|
||||
// Test case for reduceRight()
|
||||
var arr_reduceRight1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
var arr_reduceRight2 = new Array();
|
||||
function testReduceRight(accumulator, element, index, array) {
|
||||
if (index == 0) {
|
||||
array.length = 6;
|
||||
}
|
||||
return accumulator + element;
|
||||
}
|
||||
function testReduceRight4(accumulator, element, index, array) {
|
||||
array.pop();
|
||||
array.pop();
|
||||
return accumulator + element;
|
||||
}
|
||||
for (let i = 0; i < 10; i++) arr_reduceRight2[i] = i;
|
||||
var arr_reduceRight3 = new Array();
|
||||
for (let i = 0; i < 10; i++) {
|
||||
if (i < 9) {
|
||||
continue;
|
||||
}
|
||||
arr_reduceRight3[i] = i;
|
||||
}
|
||||
var arr_reduceRight4 = new Array();
|
||||
for (let i = 0; i < 10; i++) arr_reduceRight4[i] = i;
|
||||
var result_reduceRight1 = arr_reduceRight1.reduceRight(testReduceRight, 100);
|
||||
print(result_reduceRight1);
|
||||
var result_reduceRight2 = arr_reduceRight2.reduceRight(testReduceRight, 100);
|
||||
print(result_reduceRight2);
|
||||
var result_reduceRight3 = arr_reduceRight3.reduceRight(testReduceRight, 100);
|
||||
print(result_reduceRight3);
|
||||
var result_reduceRight4 = arr_reduceRight4.reduceRight(testReduceRight4, 100);
|
||||
print(result_reduceRight4);
|
@ -155,3 +155,7 @@ true
|
||||
true
|
||||
true
|
||||
true
|
||||
145
|
||||
145
|
||||
109
|
||||
125
|
||||
|
Loading…
Reference in New Issue
Block a user