!7623 [新需求]: Function.prototype.call IR化

Merge pull request !7623 from 李晨帅/FunctionIR
This commit is contained in:
openharmony_ci 2024-06-12 08:57:03 +00:00 committed by Gitee
commit 79f69baee9
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
14 changed files with 194 additions and 3 deletions

View File

@ -98,6 +98,7 @@ int AssemblerModule::GetArgcFromJSCallMode(JSCallMode mode)
case JSCallMode::CALL_ARG2:
case JSCallMode::CALL_THIS_ARG2:
case JSCallMode::DEPRECATED_CALL_ARG2:
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
return 2; // 2: arg2
case JSCallMode::CALL_ARG3:
case JSCallMode::CALL_THIS_ARG3:
@ -149,6 +150,7 @@ bool AssemblerModule::IsCallNew(JSCallMode mode)
case JSCallMode::CALL_SETTER:
case JSCallMode::CALL_ENTRY:
case JSCallMode::CALL_FROM_AOT:
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
return false;
@ -192,6 +194,7 @@ bool AssemblerModule::JSModeHaveThisArg(JSCallMode mode)
case JSCallMode::CALL_FROM_AOT:
case JSCallMode::CALL_GETTER:
case JSCallMode::CALL_SETTER:
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
return true;
@ -218,6 +221,7 @@ bool AssemblerModule::JSModeHaveNewTargetArg(JSCallMode mode)
case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
case JSCallMode::CALL_GETTER:
case JSCallMode::CALL_SETTER:
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
case JSCallMode::CALL_THIS_ARG0:
case JSCallMode::CALL_THIS_ARG1:
@ -264,6 +268,7 @@ bool AssemblerModule::IsJumpToCallCommonEntry(JSCallMode mode)
return true;
case JSCallMode::CALL_GETTER:
case JSCallMode::CALL_SETTER:
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
case JSCallMode::CALL_ENTRY:
case JSCallMode::CALL_GENERATOR:

View File

@ -139,7 +139,8 @@ namespace panda::ecmascript::kungfu {
#define BUILTINS_WITH_FUNCTION_STUB_BUILDER(V) \
V(PrototypeApply, Function, Undefined()) \
V(PrototypeBind, Function, Undefined())
V(PrototypeBind, Function, Undefined()) \
V(PrototypeCall, Function, Undefined())
#define BUILTINS_WITH_NUMBER_STUB_BUILDER(V) \
V(ParseFloat, Number, Undefined()) \
@ -295,7 +296,6 @@ namespace panda::ecmascript::kungfu {
V(ReflectHas) \
V(ReflectConstruct) \
V(ReflectApply) \
V(FunctionPrototypeCall) \
V(FunctionPrototypeHasInstance) \
V(TYPED_BUILTINS_INLINE_FIRST = MathAcos) \
V(TYPED_BUILTINS_INLINE_LAST = FunctionPrototypeHasInstance)

View File

@ -165,6 +165,67 @@ void BuiltinsFunctionStubBuilder::PrototypeBind(GateRef glue, GateRef thisValue,
}
}
void BuiltinsFunctionStubBuilder::PrototypeCall(GateRef glue, GateRef thisValue,
GateRef numArgs, Variable* res, Label *exit, Label *slowPath)
{
auto env = GetEnvironment();
Label funcIsHeapObject(env);
Label funcIsCallable(env);
// 1. If IsCallable(func) is false, throw a TypeError exception.
GateRef func = thisValue;
BRANCH(TaggedIsHeapObject(func), &funcIsHeapObject, slowPath);
Bind(&funcIsHeapObject);
BRANCH(IsCallable(func), &funcIsCallable, slowPath);
Bind(&funcIsCallable);
{
Label call0(env);
Label moreThan0(env);
Label call1(env);
Label moreThan1(env);
Label call2(env);
Label moreThan2(env);
Label createTaggedArray(env);
GateRef thisArg = GetCallArg0(numArgs);
// 2. Let argList be an empty List.
// 3. If this method was called with more than one argument then in left to right order,
// starting with the second argument, append each argument as the last element of argList.
// 5. Return Call(func, thisArg, argList).
BRANCH(Int64LessThanOrEqual(numArgs, Int64(1)), &call0, &moreThan0); // 1: thisArg
Bind(&call0);
{
res->WriteVariable(JSCallDispatch(glue, func, Int32(0), 0, Circuit::NullGate(), // 0: call 0
JSCallMode::CALL_GETTER, { thisArg }));
Jump(exit);
}
Bind(&moreThan0);
BRANCH(Int64Equal(numArgs, Int64(2)), &call1, &moreThan1); // 2: thisArg + 1 arg
Bind(&call1);
{
res->WriteVariable(JSCallDispatch(glue, func, Int32(1), 0, Circuit::NullGate(), // 1: call 1
JSCallMode::CALL_SETTER, { thisArg, GetCallArg1(numArgs) }));
Jump(exit);
}
Bind(&moreThan1);
BRANCH(Int64Equal(numArgs, Int64(3)), &call2, &moreThan2); // 3: thisArg + 2 args
Bind(&call2);
{
res->WriteVariable(JSCallDispatch(glue, func, Int32(2), 0, Circuit::NullGate(), // 2: call 2
JSCallMode::CALL_THIS_ARG2_WITH_RETURN, { thisArg, GetCallArg1(numArgs), GetCallArg2(numArgs) }));
Jump(exit);
}
Bind(&moreThan2);
{
// currently argv will not be used in builtins IR except constructor
GateRef argsLength = Int32Sub(TruncInt64ToInt32(numArgs), Int32(1)); // 1: thisArg
GateRef elementArgv = PtrAdd(GetArgv(), IntPtr(JSTaggedValue::TaggedTypeSize()));
res->WriteVariable(JSCallDispatch(glue, func, argsLength, 0, Circuit::NullGate(),
JSCallMode::CALL_THIS_ARGV_WITH_RETURN, { argsLength, elementArgv, thisArg }));
Jump(exit);
}
}
}
// return elements
GateRef BuiltinsFunctionStubBuilder::BuildArgumentsListFastElements(GateRef glue, GateRef arrayObj)
{

View File

@ -1820,6 +1820,11 @@ DEF_CALL_SIGNATURE(CallSetter)
PUSH_CALL_ARGS_AND_DISPATCH_NATIVE_RANGE_SIGNATURE(CallSetter)
}
DEF_CALL_SIGNATURE(CallContainersArgs2)
{
PUSH_CALL_ARGS_AND_DISPATCH_NATIVE_RANGE_SIGNATURE(CallContainersArgs2)
}
DEF_CALL_SIGNATURE(CallContainersArgs3)
{
PUSH_CALL_ARGS_AND_DISPATCH_NATIVE_RANGE_SIGNATURE(CallContainersArgs3)

View File

@ -440,6 +440,7 @@ private:
V(PushSuperCallAndDispatch) \
V(CallGetter) \
V(CallSetter) \
V(CallContainersArgs2) \
V(CallContainersArgs3) \
V(JSCallWithArgV) \
V(JSFastCallWithArgV) \

View File

@ -7594,6 +7594,7 @@ bool StubBuilder::IsCallModeSupportPGO(JSCallMode mode)
case JSCallMode::CALL_GENERATOR:
case JSCallMode::CALL_GETTER:
case JSCallMode::CALL_SETTER:
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
return false;
@ -7764,6 +7765,10 @@ void StubBuilder::JSCallDispatchForBaseline(GateRef glue, GateRef func, GateRef
ret = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
{ nativeCode, glue, numArgs, func, newTarget, data[0], data[1] });
break;
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
ret = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
{ nativeCode, glue, numArgs, func, newTarget, data[0], data[1], data[2] });
break;
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
ret = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
{ nativeCode, glue, numArgs, func, newTarget, data[0], data[1], data[2], data[3] });
@ -7886,6 +7891,9 @@ void StubBuilder::JSCallDispatchForBaseline(GateRef glue, GateRef func, GateRef
case JSCallMode::CALL_SETTER:
ret = FastCallOptimized(glue, code, { glue, func, data[0], data[1] });
break;
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
ret = FastCallOptimized(glue, code, { glue, func, data[0], data[1], data[2] });
break;
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
ret = FastCallOptimized(glue, code, { glue, func, data[0], data[1], data[2], data[3] });
break;
@ -7962,6 +7970,10 @@ void StubBuilder::JSCallDispatchForBaseline(GateRef glue, GateRef func, GateRef
ret = CallNGCRuntime(glue, RTSTUB_ID(OptimizedFastCallAndPushArgv),
{ glue, realNumArgs, IntPtr(0), func, newTarget, data[0], data[1]});
break;
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
ret = CallNGCRuntime(glue, RTSTUB_ID(OptimizedFastCallAndPushArgv),
{ glue, realNumArgs, IntPtr(0), func, newTarget, data[0], data[1], data[2] });
break;
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
ret = CallNGCRuntime(glue, RTSTUB_ID(OptimizedFastCallAndPushArgv),
{ glue, realNumArgs, IntPtr(0), func, newTarget, data[0], data[1], data[2], data[3] });
@ -8050,6 +8062,10 @@ void StubBuilder::JSCallDispatchForBaseline(GateRef glue, GateRef func, GateRef
ret = CallOptimized(glue, code,
{ glue, realNumArgs, IntPtr(0), func, newTarget, data[0], data[1] });
break;
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
ret = CallOptimized(glue, code,
{ glue, realNumArgs, IntPtr(0), func, newTarget, data[0], data[1], data[2] });
break;
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
ret = CallOptimized(glue, code,
{ glue, realNumArgs, IntPtr(0), func, newTarget, data[0], data[1], data[2], data[3] });
@ -8127,6 +8143,10 @@ void StubBuilder::JSCallDispatchForBaseline(GateRef glue, GateRef func, GateRef
ret = CallNGCRuntime(glue, RTSTUB_ID(OptimizedCallAndPushArgv),
{ glue, realNumArgs, IntPtr(0), func, newTarget, data[0], data[1]});
break;
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
ret = CallNGCRuntime(glue, RTSTUB_ID(OptimizedCallAndPushArgv),
{ glue, realNumArgs, IntPtr(0), func, newTarget, data[0], data[1], data[2] });
break;
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
ret = CallNGCRuntime(glue, RTSTUB_ID(OptimizedCallAndPushArgv),
{ glue, realNumArgs, IntPtr(0), func, newTarget, data[0], data[1], data[2], data[3] });
@ -8224,6 +8244,10 @@ void StubBuilder::JSCallDispatchForBaseline(GateRef glue, GateRef func, GateRef
ret = CallNGCRuntime(glue, RTSTUB_ID(CallSetter),
{ glue, func, method, callField, data[1], data[0] });
break;
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
ret = CallNGCRuntime(glue, RTSTUB_ID(CallContainersArgs2),
{ glue, func, method, callField, data[1], data[2], data[0] });
break;
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
ret = CallNGCRuntime(glue, RTSTUB_ID(CallContainersArgs3),
{ glue, func, method, callField, data[1], data[2], data[3], data[0] });
@ -8320,6 +8344,10 @@ void StubBuilder::JSCallDispatchForBaseline(GateRef glue, GateRef func, GateRef
ret = CallNGCRuntime(glue, RTSTUB_ID(CallSetter),
{ glue, func, method, callField, data[1], data[0] });
break;
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
ret = CallNGCRuntime(glue, RTSTUB_ID(CallContainersArgs2),
{ glue, func, method, callField, data[1], data[2], data[0] });
break;
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
ret = CallNGCRuntime(glue, RTSTUB_ID(CallContainersArgs3),
{ glue, func, method, callField, data[1], data[2], data[3], data[0] });
@ -8495,6 +8523,10 @@ GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNu
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
{ nativeCode, glue, numArgs, func, newTarget, data[0], data[1] });
break;
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
{ nativeCode, glue, numArgs, func, newTarget, data[0], data[1], data[2] });
break;
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
{ nativeCode, glue, numArgs, func, newTarget, data[0], data[1], data[2], data[3] });
@ -8623,6 +8655,10 @@ GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNu
result = FastCallOptimized(glue, code, { glue, func, data[0], data[1] });
Jump(&exit);
break;
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
result = FastCallOptimized(glue, code, { glue, func, data[0], data[1], data[2] });
Jump(&exit);
break;
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
result = FastCallOptimized(glue, code, { glue, func, data[0], data[1], data[2], data[3] });
Jump(&exit);
@ -8708,6 +8744,11 @@ GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNu
{ glue, realNumArgs, IntPtr(0), func, newTarget, data[0], data[1]});
Jump(&exit);
break;
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
result = CallNGCRuntime(glue, RTSTUB_ID(OptimizedFastCallAndPushArgv),
{ glue, realNumArgs, IntPtr(0), func, newTarget, data[0], data[1], data[2] });
Jump(&exit);
break;
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
result = CallNGCRuntime(glue, RTSTUB_ID(OptimizedFastCallAndPushArgv),
{ glue, realNumArgs, IntPtr(0), func, newTarget, data[0], data[1], data[2], data[3] });
@ -8806,6 +8847,11 @@ GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNu
{ glue, realNumArgs, IntPtr(0), func, newTarget, data[0], data[1] });
Jump(&exit);
break;
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
result = CallOptimized(glue, code,
{ glue, realNumArgs, IntPtr(0), func, newTarget, data[0], data[1], data[2] });
Jump(&exit);
break;
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
result = CallOptimized(glue, code,
{ glue, realNumArgs, IntPtr(0), func, newTarget, data[0], data[1], data[2], data[3] });
@ -8892,6 +8938,11 @@ GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNu
{ glue, realNumArgs, IntPtr(0), func, newTarget, data[0], data[1]});
Jump(&exit);
break;
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
result = CallNGCRuntime(glue, RTSTUB_ID(OptimizedCallAndPushArgv),
{ glue, realNumArgs, IntPtr(0), func, newTarget, data[0], data[1], data[2] });
Jump(&exit);
break;
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
result = CallNGCRuntime(glue, RTSTUB_ID(OptimizedCallAndPushArgv),
{ glue, realNumArgs, IntPtr(0), func, newTarget, data[0], data[1], data[2], data[3] });
@ -8994,6 +9045,9 @@ GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNu
case JSCallMode::CALL_SETTER:
Jump(&methodNotAot);
break;
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
Jump(&methodNotAot);
break;
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
Jump(&methodNotAot);
break;
@ -9090,6 +9144,11 @@ GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNu
{ glue, func, method, callField, data[1], data[0] });
Jump(&exit);
break;
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
result = CallNGCRuntime(glue, RTSTUB_ID(CallContainersArgs2),
{ glue, func, method, callField, data[1], data[2], data[0] });
Jump(&exit);
break;
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
result = CallNGCRuntime(glue, RTSTUB_ID(CallContainersArgs3),
{ glue, func, method, callField, data[1], data[2], data[3], data[0] });

View File

@ -319,6 +319,7 @@ Register AsmInterpreterCall::GetThisRegsiter(ExtendedAssembler *assembler, JSCal
case JSCallMode::CALL_THIS_ARG1:
return __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1);
case JSCallMode::CALL_THIS_ARG2:
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
case JSCallMode::SUPER_CALL_WITH_ARGV:
case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
@ -1042,6 +1043,21 @@ void AsmInterpreterCall::CallSetter(ExtendedAssembler *assembler)
}
}
void AsmInterpreterCall::CallContainersArgs2(ExtendedAssembler *assembler)
{
__ BindAssemblerStub(RTSTUB_ID(CallContainersArgs2));
Label target;
PushAsmInterpBridgeFrame(assembler);
__ Bl(&target);
PopAsmInterpBridgeFrame(assembler);
__ Ret();
__ Bind(&target);
{
JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARG2_WITH_RETURN,
FrameTransitionType::OTHER_TO_OTHER);
}
}
void AsmInterpreterCall::CallContainersArgs3(ExtendedAssembler *assembler)
{
__ BindAssemblerStub(RTSTUB_ID(CallContainersArgs3));

View File

@ -205,6 +205,8 @@ public:
static void CallSetter(ExtendedAssembler *assembler);
static void CallContainersArgs2(ExtendedAssembler *assembler);
static void CallContainersArgs3(ExtendedAssembler *assembler);
static void CallReturnWithArgv([[maybe_unused]] ExtendedAssembler *assembler);

View File

@ -578,6 +578,7 @@ Register AsmInterpreterCall::GetThisRegsiter(ExtendedAssembler *assembler, JSCal
}
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
return __ CppJSCallAvailableRegister2();
case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
case JSCallMode::CALL_THIS_ARGV_WITH_RETURN: {
return __ CppJSCallAvailableRegister1();
}
@ -1184,6 +1185,22 @@ void AsmInterpreterCall::CallReturnWithArgv(ExtendedAssembler *assembler)
}
}
void AsmInterpreterCall::CallContainersArgs2(ExtendedAssembler *assembler)
{
__ BindAssemblerStub(RTSTUB_ID(CallContainersArgs2));
Label target;
PushAsmInterpBridgeFrame(assembler);
GetArgvAtStack(assembler);
__ Callq(&target);
PopAsmInterpBridgeFrame(assembler);
__ Ret();
__ Bind(&target);
{
JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARG2_WITH_RETURN,
FrameTransitionType::OTHER_TO_OTHER);
}
}
void AsmInterpreterCall::CallContainersArgs3(ExtendedAssembler *assembler)
{
__ BindAssemblerStub(RTSTUB_ID(CallContainersArgs3));

View File

@ -169,6 +169,8 @@ public:
static void CallSetter(ExtendedAssembler *assembler);
static void CallContainersArgs2(ExtendedAssembler *assembler);
static void CallContainersArgs3(ExtendedAssembler *assembler);
static void CallReturnWithArgv(ExtendedAssembler *assembler);

View File

@ -168,6 +168,7 @@ enum class JSCallMode : uintptr_t {
DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV,
CALL_GETTER,
CALL_SETTER,
CALL_THIS_ARG2_WITH_RETURN,
CALL_THIS_ARG3_WITH_RETURN,
CALL_THIS_ARGV_WITH_RETURN,
CALL_ENTRY,

View File

@ -77,6 +77,7 @@ using FastCallAotEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, co
V(ResumeRspAndRollback) \
V(CallSetter) \
V(CallGetter) \
V(CallContainersArgs2) \
V(CallContainersArgs3) \
V(CallReturnWithArgv)

View File

@ -120,4 +120,15 @@ try {
print(v1);
} catch (e) {
print(e);
}
}
function prototypeCallTest(...arr) {
print(this);
print(arr);
}
prototypeCallTest.call(0);
prototypeCallTest.call(0, 1);
prototypeCallTest.call(0, 1, 2);
prototypeCallTest.call(0, 1, 2, 3);
prototypeCallTest.call(0, 1, 2, 3, 4);

View File

@ -25,3 +25,13 @@ newobj native
setter 555
getter 555
undefined
0
0
1
0
1,2
0
1,2,3
0
1,2,3,4