From c1aa7ecd82a4266acff6dd0fec6eca982139b56b Mon Sep 17 00:00:00 2001 From: wupengyong Date: Sun, 23 Apr 2023 17:42:26 +0800 Subject: [PATCH] Reason:add function apply builtins ir Description:add function apply ir Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I6Y5E4?from=project-issue Signed-off-by: wupengyong Change-Id: Ie5ade286a56c5237175476a6a0b915558b87c454 --- ecmascript/builtins/builtins.cpp | 3 +- ecmascript/compiler/assembler_module.cpp | 5 + .../builtins/builtins_call_signature.h | 1 + .../compiler/builtins/builtins_stubs.cpp | 122 +++- ecmascript/compiler/builtins/builtins_stubs.h | 58 +- .../builtins/containers_stub_builder.cpp | 24 +- ecmascript/compiler/call_signature.cpp | 15 +- ecmascript/compiler/call_signature.h | 1 + ecmascript/compiler/circuit_builder-inl.h | 35 ++ ecmascript/compiler/circuit_builder.h | 4 + ecmascript/compiler/stub_builder-inl.h | 27 + ecmascript/compiler/stub_builder.cpp | 519 +++++++++++++++++- ecmascript/compiler/stub_builder.h | 17 +- .../aarch64/asm_interpreter_call.cpp | 33 +- .../compiler/trampoline/aarch64/common_call.h | 2 + .../trampoline/x64/asm_interpreter_call.cpp | 35 +- .../compiler/trampoline/x64/common_call.h | 2 + ecmascript/frames.cpp | 19 + ecmascript/frames.h | 2 + ecmascript/interpreter/frame_handler.cpp | 3 + ecmascript/js_tagged_value-inl.h | 1 - ecmascript/js_tagged_value.h | 2 + ecmascript/message_string.h | 8 +- ecmascript/stubs/runtime_stubs.h | 3 +- test/moduletest/builtins/builtinsir.js | 11 + test/moduletest/builtins/expect_output.txt | 1 + 26 files changed, 892 insertions(+), 61 deletions(-) diff --git a/ecmascript/builtins/builtins.cpp b/ecmascript/builtins/builtins.cpp index 19b3b9e0b2..63d8dd2a22 100644 --- a/ecmascript/builtins/builtins.cpp +++ b/ecmascript/builtins/builtins.cpp @@ -449,7 +449,8 @@ void Builtins::InitializeFunction(const JSHandle &env, const JSHandle // Function.prototype method // 19.2.3.1 Function.prototype.apply ( thisArg, argArray ) - SetFunction(env, funcFuncPrototypeObj, "apply", Function::FunctionPrototypeApply, FunctionLength::TWO); + SetFunction(env, funcFuncPrototypeObj, "apply", Function::FunctionPrototypeApply, FunctionLength::TWO, + BUILTINS_STUB_ID(FunctionPrototypeApply)); // 19.2.3.2 Function.prototype.bind ( thisArg , ...args) SetFunction(env, funcFuncPrototypeObj, "bind", Function::FunctionPrototypeBind, FunctionLength::ONE); // 19.2.3.3 Function.prototype.call (thisArg , ...args) diff --git a/ecmascript/compiler/assembler_module.cpp b/ecmascript/compiler/assembler_module.cpp index 43d420e197..c00ddf9652 100644 --- a/ecmascript/compiler/assembler_module.cpp +++ b/ecmascript/compiler/assembler_module.cpp @@ -107,6 +107,7 @@ int AssemblerModule::GetArgcFromJSCallMode(JSCallMode mode) case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV: case JSCallMode::CALL_ENTRY: case JSCallMode::CALL_FROM_AOT: + case JSCallMode::CALL_THIS_ARGV_WITH_RETURN: return -1; case JSCallMode::CALL_GETTER: return 0; @@ -142,6 +143,7 @@ bool AssemblerModule::IsCallNew(JSCallMode mode) case JSCallMode::CALL_ENTRY: case JSCallMode::CALL_FROM_AOT: case JSCallMode::CALL_THIS_ARG3_WITH_RETURN: + case JSCallMode::CALL_THIS_ARGV_WITH_RETURN: return false; case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV: case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV: @@ -180,6 +182,7 @@ bool AssemblerModule::JSModeHaveThisArg(JSCallMode mode) case JSCallMode::CALL_GETTER: case JSCallMode::CALL_SETTER: case JSCallMode::CALL_THIS_ARG3_WITH_RETURN: + case JSCallMode::CALL_THIS_ARGV_WITH_RETURN: return true; default: LOG_ECMA(FATAL) << "this branch is unreachable"; @@ -209,6 +212,7 @@ bool AssemblerModule::JSModeHaveNewTargetArg(JSCallMode mode) case JSCallMode::CALL_THIS_ARG1: case JSCallMode::CALL_THIS_ARG2: case JSCallMode::CALL_THIS_ARG3: + case JSCallMode::CALL_THIS_ARGV_WITH_RETURN: return false; case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV: case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV: @@ -249,6 +253,7 @@ bool AssemblerModule::IsJumpToCallCommonEntry(JSCallMode mode) case JSCallMode::CALL_ENTRY: case JSCallMode::CALL_GENERATOR: case JSCallMode::CALL_FROM_AOT: + case JSCallMode::CALL_THIS_ARGV_WITH_RETURN: return false; default: LOG_ECMA(FATAL) << "this branch is unreachable"; diff --git a/ecmascript/compiler/builtins/builtins_call_signature.h b/ecmascript/compiler/builtins/builtins_call_signature.h index b8f8c19396..6ead8cd140 100644 --- a/ecmascript/compiler/builtins/builtins_call_signature.h +++ b/ecmascript/compiler/builtins/builtins_call_signature.h @@ -50,6 +50,7 @@ namespace panda::ecmascript::kungfu { V(ListForEach) \ V(ArrayListForEach) \ V(ArrayListReplaceAllElements) \ + V(FunctionPrototypeApply) \ #define BUILTINS_CONSTRUCTOR_STUB_LIST(V) \ V(BooleanConstructor) \ diff --git a/ecmascript/compiler/builtins/builtins_stubs.cpp b/ecmascript/compiler/builtins/builtins_stubs.cpp index 660a9acc35..3e425b58a8 100644 --- a/ecmascript/compiler/builtins/builtins_stubs.cpp +++ b/ecmascript/compiler/builtins/builtins_stubs.cpp @@ -107,7 +107,7 @@ GateRef BuiltinsStubBuilder::CallSlowPath(GateRef nativeCode, GateRef glue, Gate Branch(Int64Equal(numArgs, IntPtr(1)), &callThis1, ¬callThis1); Bind(&callThis1); { - GateRef arg0 = GetCallArg0(); + GateRef arg0 = GetCallArg0(numArgs); result = CallBuiltinRuntime(glue, { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0 }); Jump(&exit); @@ -117,17 +117,17 @@ GateRef BuiltinsStubBuilder::CallSlowPath(GateRef nativeCode, GateRef glue, Gate Branch(Int64Equal(numArgs, IntPtr(2)), &callThis2, &callThis3); // 2: args2 Bind(&callThis2); { - GateRef arg0 = GetCallArg0(); - GateRef arg1 = GetCallArg1(); + GateRef arg0 = GetCallArg0(numArgs); + GateRef arg1 = GetCallArg1(numArgs); result = CallBuiltinRuntime(glue, { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0, arg1 }); Jump(&exit); } Bind(&callThis3); { - GateRef arg0 = GetCallArg0(); - GateRef arg1 = GetCallArg1(); - GateRef arg2 = GetCallArg2(); + GateRef arg0 = GetCallArg0(numArgs); + GateRef arg1 = GetCallArg1(numArgs); + GateRef arg2 = GetCallArg2(numArgs); result = CallBuiltinRuntime(glue, { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0, arg1, arg2 }); Jump(&exit); @@ -172,7 +172,7 @@ DECLARE_BUILTINS(CharCodeAt) Branch(Int64GreaterThanOrEqual(IntPtr(0), numArgs), &next, &posTagNotUndefined); Bind(&posTagNotUndefined); { - GateRef posTag = GetCallArg0(); + GateRef posTag = GetCallArg0(numArgs); Branch(TaggedIsInt(posTag), &posTagIsInt, &posTagNotInt); Bind(&posTagIsInt); pos = GetInt32OfTInt(posTag); @@ -238,7 +238,7 @@ DECLARE_BUILTINS(IndexOf) Branch(IsString(thisValue), &isString, &slowPath); Bind(&isString); { - GateRef searchTag = GetCallArg0(); + GateRef searchTag = GetCallArg0(numArgs); Branch(TaggedIsHeapObject(searchTag), &searchTagIsHeapObject, &slowPath); Bind(&searchTagIsHeapObject); Branch(IsString(searchTag), &isSearchString, &slowPath); @@ -248,7 +248,7 @@ DECLARE_BUILTINS(IndexOf) Branch(Int64GreaterThanOrEqual(IntPtr(1), numArgs), &next, &posTagNotUndefined); Bind(&posTagNotUndefined); { - GateRef posTag = GetCallArg1(); + GateRef posTag = GetCallArg1(numArgs); Branch(TaggedIsInt(posTag), &posTagIsInt, &posTagNotInt); Bind(&posTagIsInt); pos = GetInt32OfTInt(posTag); @@ -356,7 +356,7 @@ DECLARE_BUILTINS(Substring) Branch(Int64GreaterThanOrEqual(IntPtr(0), numArgs), &next, &startTagNotUndefined); Bind(&startTagNotUndefined); { - GateRef startTag = GetCallArg0(); + GateRef startTag = GetCallArg0(numArgs); Branch(TaggedIsInt(startTag), &posTagIsInt, &posTagNotInt); Bind(&posTagIsInt); start = GetInt32OfTInt(startTag); @@ -377,7 +377,7 @@ DECLARE_BUILTINS(Substring) } Bind(&endTagNotUndefined); { - GateRef endTag = GetCallArg1(); + GateRef endTag = GetCallArg1(numArgs); Branch(TaggedIsInt(endTag), &endTagIsInt, &endTagNotInt); Bind(&endTagIsInt); end = GetInt32OfTInt(endTag); @@ -504,7 +504,7 @@ DECLARE_BUILTINS(CharAt) Branch(Int64GreaterThanOrEqual(IntPtr(0), numArgs), &next, &posTagNotUndefined); Bind(&posTagNotUndefined); { - GateRef posTag = GetCallArg0(); + GateRef posTag = GetCallArg0(numArgs); Branch(TaggedIsInt(posTag), &posTagIsInt, &posTagNotInt); Bind(&posTagIsInt); pos = GetInt32OfTInt(posTag); @@ -826,6 +826,102 @@ DECLARE_BUILTINS(ArrayListReplaceAllElements) Return(*res); } +DECLARE_BUILTINS(FunctionPrototypeApply) +{ + auto env = GetEnvironment(); + DEFVARIABLE(res, VariableType::JS_ANY(), Undefined()); + Label exit(env); + Label slowPath(env); + Label targetIsCallable(env); + Label targetIsUndefined(env); + Label targetNotUndefined(env); + Label isHeapObject(env); + //1. If IsCallable(func) is false, throw a TypeError exception + Branch(TaggedIsHeapObject(thisValue), &isHeapObject, &slowPath); + Bind(&isHeapObject); + { + Branch(IsCallable(thisValue), &targetIsCallable, &slowPath); + Bind(&targetIsCallable); + { + GateRef thisArg = GetCallArg0(numArgs); + GateRef arrayObj = GetCallArg1(numArgs); + // 2. If argArray is null or undefined, then + Branch(TaggedIsUndefined(arrayObj), &targetIsUndefined, &targetNotUndefined); + Bind(&targetIsUndefined); + { + // a. Return Call(func, thisArg). + res = JSCallDispatch(glue, thisValue, Int32(0), 0, Circuit::NullGate(), + JSCallMode::CALL_GETTER, { thisArg }); + Jump(&exit); + } + Bind(&targetNotUndefined); + { + // 3. Let argList be CreateListFromArrayLike(argArray). + GateRef elements = BuildArgumentsListFastElements(glue, arrayObj); + Label targetIsHole(env); + Label targetNotHole(env); + Branch(TaggedIsHole(elements), &targetIsHole, &targetNotHole); + Bind(&targetIsHole); + { + GateRef argList = CreateListFromArrayLike(glue, arrayObj); + // 4. ReturnIfAbrupt(argList). + Label isPendingException(env); + Label noPendingException(env); + Branch(HasPendingException(glue), &isPendingException, &noPendingException); + Bind(&isPendingException); + { + Jump(&slowPath); + } + Bind(&noPendingException); + { + GateRef argsLength = GetLengthOfTaggedArray(argList); + GateRef argv = PtrAdd(argList, IntPtr(TaggedArray::DATA_OFFSET)); + res = JSCallDispatch(glue, thisValue, argsLength, 0, Circuit::NullGate(), + JSCallMode::CALL_THIS_ARGV_WITH_RETURN, { argsLength, argv, thisArg }); + Jump(&exit); + } + } + Bind(&targetNotHole); + { + // 6. Return Call(func, thisArg, argList). + Label taggedIsStableJsArg(env); + Label taggedNotStableJsArg(env); + Branch(IsStableJSArguments(glue, arrayObj), &taggedIsStableJsArg, &taggedNotStableJsArg); + Bind(&taggedIsStableJsArg); + { + GateRef hClass = LoadHClass(arrayObj); + GateRef PropertyInlinedPropsOffset = IntPtr(JSArguments::LENGTH_INLINE_PROPERTY_INDEX); + GateRef result = GetPropertyInlinedProps(arrayObj, hClass, PropertyInlinedPropsOffset); + GateRef length = TaggedGetInt(result); + GateRef argsLength = MakeArgListWithHole(glue, elements, length); + GateRef elementArgv = PtrAdd(elements, IntPtr(TaggedArray::DATA_OFFSET)); + res = JSCallDispatch(glue, thisValue, argsLength, 0, Circuit::NullGate(), + JSCallMode::CALL_THIS_ARGV_WITH_RETURN, { argsLength, elementArgv, thisArg }); + Jump(&exit); + } + Bind(&taggedNotStableJsArg); + { + GateRef length = GetLengthOfJsArray(glue, arrayObj); + GateRef argsLength = MakeArgListWithHole(glue, elements, length); + GateRef elementArgv = PtrAdd(elements, IntPtr(TaggedArray::DATA_OFFSET)); + res = JSCallDispatch(glue, thisValue, argsLength, 0, Circuit::NullGate(), + JSCallMode::CALL_THIS_ARGV_WITH_RETURN, { argsLength, elementArgv, thisArg }); + Jump(&exit); + } + } + } + } + } + + Bind(&slowPath); + { + res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget); + Jump(&exit); + } + Bind(&exit); + Return(*res); +} + DECLARE_BUILTINS(BooleanConstructor) { auto env = GetEnvironment(); @@ -965,7 +1061,7 @@ DECLARE_BUILTINS(ArrayConstructor) 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); - Branch(Equal(arrayFunc, newTarget), &fastGetHclass, &slowPath); + Branch(Equal(arrayFunc, newTarget), &fastGetHclass, &slowPath); Bind(&fastGetHclass); GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); DEFVARIABLE(arrayLength, VariableType::INT64(), Int64(0)); diff --git a/ecmascript/compiler/builtins/builtins_stubs.h b/ecmascript/compiler/builtins/builtins_stubs.h index fab2b2835d..2bb547a136 100644 --- a/ecmascript/compiler/builtins/builtins_stubs.h +++ b/ecmascript/compiler/builtins/builtins_stubs.h @@ -64,19 +64,65 @@ public: return Load(VariableType::JS_ANY(), info, thisOffset); } - inline GateRef GetCallArg0() + inline GateRef GetCallArg0(GateRef numArg) { - return TaggedArgument(static_cast(BuiltinsArgs::ARG0_OR_ARGV)); + auto env = GetEnvironment(); + Label subentry(env); + env->SubCfgEntry(&subentry); + DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); + Label isValid(env); + Label exit(env); + Branch(Int32GreaterThan(TruncPtrToInt32(numArg), Int32(0)), &isValid, &exit); + Bind(&isValid); + { + result = TaggedArgument(static_cast(BuiltinsArgs::ARG0_OR_ARGV)); + Jump(&exit); + } + Bind(&exit); + auto res = *result; + env->SubCfgExit(); + return res; } - inline GateRef GetCallArg1() + inline GateRef GetCallArg1(GateRef numArg) { - return TaggedArgument(static_cast(BuiltinsArgs::ARG1)); + auto env = GetEnvironment(); + Label subentry(env); + env->SubCfgEntry(&subentry); + DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); + Label isValid(env); + Label exit(env); + Branch(Int32GreaterThan(TruncPtrToInt32(numArg), Int32(1)), &isValid, &exit); + Bind(&isValid); + { + result = TaggedArgument(static_cast(BuiltinsArgs::ARG1)); + Jump(&exit); + } + Bind(&exit); + auto res = *result; + env->SubCfgExit(); + return res; } - inline GateRef GetCallArg2() + inline GateRef GetCallArg2(GateRef numArg) { - return TaggedArgument(static_cast(BuiltinsArgs::ARG2)); + auto env = GetEnvironment(); + Label subentry(env); + env->SubCfgEntry(&subentry); + DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); + Label isValid(env); + Label exit(env); + // 2: 2 args + Branch(Int32GreaterThan(TruncPtrToInt32(numArg), Int32(2)), &isValid, &exit); + Bind(&isValid); + { + result = TaggedArgument(static_cast(BuiltinsArgs::ARG2)); + Jump(&exit); + } + Bind(&exit); + auto res = *result; + env->SubCfgExit(); + return res; } inline GateRef GetArgv() diff --git a/ecmascript/compiler/builtins/containers_stub_builder.cpp b/ecmascript/compiler/builtins/containers_stub_builder.cpp index 935d1ee5dd..1a9c403276 100644 --- a/ecmascript/compiler/builtins/containers_stub_builder.cpp +++ b/ecmascript/compiler/builtins/containers_stub_builder.cpp @@ -70,7 +70,7 @@ void ContainersStubBuilder::ContainersCommonFuncCall(GateRef glue, GateRef thisV Label isCall(env); Label notCall(env); Label isHeapObj(env); - callbackFnHandle = GetCallArg0(); + callbackFnHandle = GetCallArg0(numArgs); Branch(TaggedIsHeapObject(callbackFnHandle), &isHeapObj, slowPath); Bind(&isHeapObj); Branch(IsCallable(callbackFnHandle), &isCall, ¬Call); @@ -82,7 +82,7 @@ void ContainersStubBuilder::ContainersCommonFuncCall(GateRef glue, GateRef thisV Bind(&thisArgUndefined); Jump(&nextCount); Bind(&thisArgNotUndefined); - thisArg = GetCallArg1(); + thisArg = GetCallArg1(numArgs); Jump(&nextCount); } } @@ -188,7 +188,7 @@ void ContainersStubBuilder::QueueCommonFuncCall(GateRef glue, GateRef thisValue, Label isCall(env); Label notCall(env); Label isHeapObj(env); - callbackFnHandle = GetCallArg0(); + callbackFnHandle = GetCallArg0(numArgs); Branch(TaggedIsHeapObject(callbackFnHandle), &isHeapObj, slowPath); Bind(&isHeapObj); Branch(IsCallable(callbackFnHandle), &isCall, ¬Call); @@ -200,7 +200,7 @@ void ContainersStubBuilder::QueueCommonFuncCall(GateRef glue, GateRef thisValue, Bind(&thisArgUndefined); Jump(&nextCount); Bind(&thisArgNotUndefined); - thisArg = GetCallArg1(); + thisArg = GetCallArg1(numArgs); Jump(&nextCount); } } @@ -294,7 +294,7 @@ void ContainersStubBuilder::DequeCommonFuncCall(GateRef glue, GateRef thisValue, Label isCall(env); Label notCall(env); Label isHeapObj(env); - callbackFnHandle = GetCallArg0(); + callbackFnHandle = GetCallArg0(numArgs); Branch(TaggedIsHeapObject(callbackFnHandle), &isHeapObj, slowPath); Bind(&isHeapObj); Branch(IsCallable(callbackFnHandle), &isCall, ¬Call); @@ -306,7 +306,7 @@ void ContainersStubBuilder::DequeCommonFuncCall(GateRef glue, GateRef thisValue, Bind(&thisArgUndefined); Jump(&nextCount); Bind(&thisArgNotUndefined); - thisArg = GetCallArg1(); + thisArg = GetCallArg1(numArgs); Jump(&nextCount); } } @@ -402,7 +402,7 @@ void ContainersStubBuilder::ContainersLightWeightCall(GateRef glue, GateRef this Label isCall(env); Label notCall(env); Label isHeapObj(env); - callbackFnHandle = GetCallArg0(); + callbackFnHandle = GetCallArg0(numArgs); Branch(TaggedIsHeapObject(callbackFnHandle), &isHeapObj, slowPath); Bind(&isHeapObj); Branch(IsCallable(callbackFnHandle), &isCall, ¬Call); @@ -414,7 +414,7 @@ void ContainersStubBuilder::ContainersLightWeightCall(GateRef glue, GateRef this Bind(&thisArgUndefined); Jump(&nextCount); Bind(&thisArgNotUndefined); - thisArg = GetCallArg1(); + thisArg = GetCallArg1(numArgs); Jump(&nextCount); } } @@ -514,7 +514,7 @@ void ContainersStubBuilder::ContainersHashCall(GateRef glue, GateRef thisValue, Label isCall(env); Label notCall(env); Label isHeapObj(env); - callbackFnHandle = GetCallArg0(); + callbackFnHandle = GetCallArg0(numArgs); Branch(TaggedIsHeapObject(callbackFnHandle), &isHeapObj, ¬Call); Bind(&isHeapObj); Branch(IsCallable(callbackFnHandle), &isCall, ¬Call); @@ -526,7 +526,7 @@ void ContainersStubBuilder::ContainersHashCall(GateRef glue, GateRef thisValue, Bind(&thisArgUndefined); Jump(&nextCount); Bind(&thisArgNotUndefined); - thisArg = GetCallArg1(); + thisArg = GetCallArg1(numArgs); Jump(&nextCount); } } @@ -646,7 +646,7 @@ void ContainersStubBuilder::ContainersLinkedListCall(GateRef glue, GateRef thisV Label isCall(env); Label notCall(env); Label isHeapObj(env); - callbackFnHandle = GetCallArg0(); + callbackFnHandle = GetCallArg0(numArgs); Branch(TaggedIsHeapObject(callbackFnHandle), &isHeapObj, ¬Call); Bind(&isHeapObj); Branch(IsCallable(callbackFnHandle), &isCall, ¬Call); @@ -658,7 +658,7 @@ void ContainersStubBuilder::ContainersLinkedListCall(GateRef glue, GateRef thisV Bind(&thisArgUndefined); Jump(&nextCount); Bind(&thisArgNotUndefined); - thisArg = GetCallArg1(); + thisArg = GetCallArg1(numArgs); Jump(&nextCount); } } diff --git a/ecmascript/compiler/call_signature.cpp b/ecmascript/compiler/call_signature.cpp index 1d8e19c872..bc6528f8ca 100644 --- a/ecmascript/compiler/call_signature.cpp +++ b/ecmascript/compiler/call_signature.cpp @@ -1205,21 +1205,26 @@ DEF_CALL_SIGNATURE(CallContainersArgs3) PUSH_CALL_ARGS_AND_DISPATCH_NATIVE_RANGE_SIGNATURE(CallContainersArgs3) } +DEF_CALL_SIGNATURE(CallReturnWithArgv) +{ + PUSH_CALL_ARGS_AND_DISPATCH_NATIVE_RANGE_SIGNATURE(CallReturnWithArgv) +} + DEF_CALL_SIGNATURE(JSCallWithArgV) { - // 6 : 6 input parameters - CallSignature jSCallWithArgV("JSCallWithArgV", 0, 6, + // 5 : 5 input parameters + CallSignature jSCallWithArgV("JSCallWithArgV", 0, 5, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY()); *callSign = jSCallWithArgV; - // 6 : 6 input parameters - std::array params = { + // 5 : 5 input parameters + std::array params = { VariableType::NATIVE_POINTER(), // glue VariableType::INT64(), // actualNumArgs VariableType::JS_ANY(), // jsfunc VariableType::JS_ANY(), // newTarget VariableType::JS_ANY(), // this - VariableType::NATIVE_POINTER(), // argV }; + callSign->SetVariadicArgs(true); callSign->SetParameters(params.data()); callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC); callSign->SetCallConv(CallSignature::CallConv::CCallConv); diff --git a/ecmascript/compiler/call_signature.h b/ecmascript/compiler/call_signature.h index 9b7fa51c2d..17b9463f64 100644 --- a/ecmascript/compiler/call_signature.h +++ b/ecmascript/compiler/call_signature.h @@ -439,6 +439,7 @@ private: V(JSCallNewWithArgV) \ V(TimeClip) \ V(SetDateValues) \ + V(CallReturnWithArgv) \ TEST_STUB_SIGNATRUE_LIST(V) #define DECL_CALL_SIGNATURE(name) \ diff --git a/ecmascript/compiler/circuit_builder-inl.h b/ecmascript/compiler/circuit_builder-inl.h index 3d3516a314..1274c214b0 100644 --- a/ecmascript/compiler/circuit_builder-inl.h +++ b/ecmascript/compiler/circuit_builder-inl.h @@ -378,6 +378,15 @@ GateRef CircuitBuilder::TaggedIsAsyncGeneratorObject(GateRef x) return LogicAnd(isHeapObj, isAsyncGeneratorObj); } +GateRef CircuitBuilder::TaggedIsJSGlobalObject(GateRef x) +{ + GateRef isHeapObj = TaggedIsHeapObject(x); + GateRef objType = GetObjectType(LoadHClass(x)); + GateRef isGlobal = Equal(objType, + Int32(static_cast(JSType::JS_GLOBAL_OBJECT))); + return LogicAnd(isHeapObj, isGlobal); +} + GateRef CircuitBuilder::TaggedIsGeneratorObject(GateRef x) { GateRef isHeapObj = TaggedIsHeapObject(x); @@ -639,6 +648,32 @@ GateRef CircuitBuilder::IsDictionaryElement(GateRef hClass) Int32(0)); } +GateRef CircuitBuilder::IsStableElements(GateRef hClass) +{ + GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET); + GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset); + return NotEqual(Int32And(Int32LSR(bitfield, + Int32(JSHClass::IsStableElementsBit::START_BIT)), + Int32((1LU << JSHClass::IsStableElementsBit::SIZE) - 1)), + Int32(0)); +} + +GateRef CircuitBuilder::IsStableArguments(GateRef hClass) +{ + GateRef objectType = GetObjectType(hClass); + GateRef isJsArguments = Int32Equal(objectType, Int32(static_cast(JSType::JS_ARGUMENTS))); + GateRef isStableElements = IsStableElements(hClass); + return BoolAnd(isStableElements, isJsArguments); +} + +GateRef CircuitBuilder::IsStableArray(GateRef hClass) +{ + GateRef objectType = GetObjectType(hClass); + GateRef isJsArray = Int32Equal(objectType, Int32(static_cast(JSType::JS_ARRAY))); + GateRef isStableElements = IsStableElements(hClass); + return BoolAnd(isStableElements, isJsArray); +} + GateRef CircuitBuilder::IsClassConstructor(GateRef object) { GateRef hClass = LoadHClass(object); diff --git a/ecmascript/compiler/circuit_builder.h b/ecmascript/compiler/circuit_builder.h index dbb6db1f96..0035364fc2 100644 --- a/ecmascript/compiler/circuit_builder.h +++ b/ecmascript/compiler/circuit_builder.h @@ -402,6 +402,7 @@ public: inline GateRef TaggedIsSpecial(GateRef x); inline GateRef TaggedIsHeapObject(GateRef x); inline GateRef TaggedIsAsyncGeneratorObject(GateRef x); + inline GateRef TaggedIsJSGlobalObject(GateRef x); inline GateRef TaggedIsGeneratorObject(GateRef x); inline GateRef TaggedIsPropertyBox(GateRef x); inline GateRef TaggedIsWeak(GateRef x); @@ -493,6 +494,9 @@ public: inline GateRef GetObjectType(GateRef hClass); inline GateRef IsDictionaryModeByHClass(GateRef hClass); inline GateRef IsIsStableElementsByHClass(GateRef hClass); + inline GateRef IsStableElements(GateRef hClass); + inline GateRef IsStableArguments(GateRef hClass); + inline GateRef IsStableArray(GateRef hClass); inline GateRef DoubleIsINF(GateRef x); inline GateRef IsDictionaryElement(GateRef hClass); inline GateRef IsClassConstructor(GateRef object); diff --git a/ecmascript/compiler/stub_builder-inl.h b/ecmascript/compiler/stub_builder-inl.h index e6343e1477..ead75c38f4 100644 --- a/ecmascript/compiler/stub_builder-inl.h +++ b/ecmascript/compiler/stub_builder-inl.h @@ -608,6 +608,10 @@ inline GateRef StubBuilder::TaggedIsAsyncGeneratorObject(GateRef x) return env_->GetBuilder()->TaggedIsAsyncGeneratorObject(x); } +inline GateRef StubBuilder::TaggedIsJSGlobalObject(GateRef x) +{ + return env_->GetBuilder()->TaggedIsJSGlobalObject(x); +} inline GateRef StubBuilder::TaggedIsWeak(GateRef x) { @@ -2226,5 +2230,28 @@ inline void StubBuilder::Comment(GateRef glue, const std::string &str) { CallNGCRuntime(glue, RTSTUB_ID(Comment), { StringPtr(str) }); } + +inline GateRef StubBuilder::IsStableElements(GateRef hClass) +{ + return env_->GetBuilder()->IsStableElements(hClass); +} + +inline GateRef StubBuilder::IsStableArguments(GateRef hClass) +{ + return env_->GetBuilder()->IsStableArguments(hClass); +} + +inline GateRef StubBuilder::IsStableArray(GateRef hClass) +{ + return env_->GetBuilder()->IsStableArray(hClass); +} + +inline GateRef StubBuilder::IsTypedArray(GateRef obj) +{ + GateRef jsHclass = LoadHClass(obj); + GateRef jsType = GetObjectType(jsHclass); + return BoolAnd(Int32GreaterThan(jsType, Int32(static_cast(JSType::JS_TYPED_ARRAY_FIRST))), + Int32GreaterThanOrEqual(Int32(static_cast(JSType::JS_TYPED_ARRAY_LAST)), jsType)); +} } // namespace panda::ecmascript::kungfu #endif // ECMASCRIPT_COMPILER_STUB_INL_H diff --git a/ecmascript/compiler/stub_builder.cpp b/ecmascript/compiler/stub_builder.cpp index ec615ade78..c06a7b07ad 100644 --- a/ecmascript/compiler/stub_builder.cpp +++ b/ecmascript/compiler/stub_builder.cpp @@ -19,11 +19,13 @@ #include "ecmascript/compiler/access_object_stub_builder.h" #include "ecmascript/compiler/interpreter_stub.h" #include "ecmascript/compiler/llvm_ir_builder.h" +#include "ecmascript/compiler/new_object_stub_builder.h" #include "ecmascript/compiler/rt_call_signature.h" #include "ecmascript/compiler/typed_array_stub_builder.h" #include "ecmascript/js_api/js_api_arraylist.h" #include "ecmascript/js_api/js_api_vector.h" #include "ecmascript/js_object.h" +#include "ecmascript/js_arguments.h" #include "ecmascript/mem/remembered_set.h" #include "ecmascript/message_string.h" #include "ecmascript/pgo_profiler/pgo_profiler_type.h" @@ -3268,6 +3270,35 @@ GateRef StubBuilder::FastGetPropertyByName(GateRef glue, GateRef obj, GateRef ke return ret; } +GateRef StubBuilder::FastGetPropertyByIndex(GateRef glue, GateRef obj, GateRef index) +{ + auto env = GetEnvironment(); + Label entry(env); + env->SubCfgEntry(&entry); + DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); + Label exit(env); + Label fastPath(env); + Label slowPath(env); + + Branch(TaggedIsHeapObject(obj), &fastPath, &slowPath); + Bind(&fastPath); + { + result = GetPropertyByIndex(glue, obj, index); + Label notHole(env); + Branch(TaggedIsHole(*result), &slowPath, &exit); + } + Bind(&slowPath); + { + result = CallRuntime(glue, RTSTUB_ID(LdObjByIndex), + { obj, IntToTaggedInt(index), TaggedFalse(), Undefined() }); + Jump(&exit); + } + Bind(&exit); + auto ret = *result; + env->SubCfgExit(); + return ret; +} + GateRef StubBuilder::OrdinaryHasInstance(GateRef glue, GateRef target, GateRef obj) { auto env = GetEnvironment(); @@ -4402,6 +4433,121 @@ GateRef StubBuilder::GetObjectLiteralFromConstPool(GateRef glue, GateRef constpo ConstPoolType::OBJECT_LITERAL); } +// return elements +GateRef StubBuilder::BuildArgumentsListFastElements(GateRef glue, GateRef arrayObj) +{ + auto env = GetEnvironment(); + Label subentry(env); + env->SubCfgEntry(&subentry); + DEFVARIABLE(res, VariableType::JS_ANY(), Hole()); + Label exit(env); + Label hasStableElements(env); + Label targetIsStableJSArguments(env); + Label targetNotStableJSArguments(env); + Label targetIsInt(env); + Label hClassEqual(env); + Label targetIsStableJSArray(env); + Label targetNotStableJSArray(env); + + Branch(HasStableElements(glue, arrayObj), &hasStableElements, &exit); + Bind(&hasStableElements); + { + Branch(IsStableJSArguments(glue, arrayObj), &targetIsStableJSArguments, &targetNotStableJSArguments); + Bind(&targetIsStableJSArguments); + { + GateRef hClass = LoadHClass(arrayObj); + GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); + GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); + GateRef argmentsClass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, + GlobalEnv::ARGUMENTS_CLASS); + Branch(Int32Equal(hClass, argmentsClass), &hClassEqual, &exit); + Bind(&hClassEqual); + { + GateRef PropertyInlinedPropsOffset = IntPtr(JSArguments::LENGTH_INLINE_PROPERTY_INDEX); + GateRef result = GetPropertyInlinedProps(arrayObj, hClass, PropertyInlinedPropsOffset); + Branch(TaggedIsInt(result), &targetIsInt, &exit); + Bind(&targetIsInt); + { + res = GetElementsArray(arrayObj); + Jump(&exit); + } + } + } + Bind(&targetNotStableJSArguments); + { + Branch(IsStableJSArray(glue, arrayObj), &targetIsStableJSArray, &targetNotStableJSArray); + Bind(&targetIsStableJSArray); + { + res = GetElementsArray(arrayObj); + Jump(&exit); + } + Bind(&targetNotStableJSArray); + { + FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) }); + Jump(&exit); + } + } + } + Bind(&exit); + auto ret = *res; + env->SubCfgExit(); + return ret; +} + +GateRef StubBuilder::MakeArgListWithHole(GateRef glue, GateRef argv, GateRef length) +{ + auto env = GetEnvironment(); + Label subentry(env); + env->SubCfgEntry(&subentry); + DEFVARIABLE(res, VariableType::INT32(), length); + DEFVARIABLE(i, VariableType::INT32(), Int32(0)); + Label exit(env); + + GateRef argsLength = GetLengthOfTaggedArray(argv); + + Label lengthGreaterThanArgsLength(env); + Label lengthLessThanArgsLength(env); + Branch(Int32GreaterThan(length, argsLength), &lengthGreaterThanArgsLength, &lengthLessThanArgsLength); + Bind(&lengthGreaterThanArgsLength); + { + res = argsLength; + Jump(&lengthLessThanArgsLength); + } + Bind(&lengthLessThanArgsLength); + { + Label loopHead(env); + Label loopEnd(env); + Label afterLoop(env); + Label targetIsHole(env); + Label targetNotHole(env); + Branch(Int32UnsignedLessThan(*i, *res), &loopHead, &afterLoop); + LoopBegin(&loopHead); + { + GateRef value = GetValueFromTaggedArray(argv, *i); + Branch(TaggedIsHole(value), &targetIsHole, &targetNotHole); + Bind(&targetIsHole); + { + SetValueToTaggedArray(VariableType::JS_ANY(), glue, argv, *i, Undefined()); + Jump(&targetNotHole); + } + Bind(&targetNotHole); + i = Int32Add(*i, Int32(1)); + Branch(Int32UnsignedLessThan(*i, *res), &loopEnd, &afterLoop); + } + Bind(&loopEnd); + LoopEnd(&loopHead); + Bind(&afterLoop); + { + res = length; + Jump(&exit); + } + } + Bind(&exit); + auto ret = *res; + env->SubCfgExit(); + return ret; +} + GateRef StubBuilder::JSAPIContainerGet(GateRef glue, GateRef receiver, GateRef index) { auto env = GetEnvironment(); @@ -4670,6 +4816,7 @@ GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNu newTarget, thisValue, data[0], data[1], data[2] }); // 2: args2 break; case JSCallMode::CALL_THIS_WITH_ARGV: + case JSCallMode::CALL_THIS_ARGV_WITH_RETURN: case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV: { thisValue = data[2]; // 2: this input [[fallthrough]]; @@ -4774,6 +4921,7 @@ GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNu Jump(&exit); break; case JSCallMode::CALL_THIS_WITH_ARGV: + case JSCallMode::CALL_THIS_ARGV_WITH_RETURN: case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV: thisValue = data[2]; // 2: this input [[fallthrough]]; @@ -4893,6 +5041,11 @@ GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNu { glue, func, method, callField, data[1], data[2], data[3], data[0] }); Jump(&exit); break; + case JSCallMode::CALL_THIS_ARGV_WITH_RETURN: + result = CallNGCRuntime(glue, RTSTUB_ID(CallReturnWithArgv), + { glue, func, method, callField, data[0], data[1], data[2] }); + Jump(&exit); + break; default: LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); @@ -4909,27 +5062,27 @@ void StubBuilder::CallFastPath(GateRef glue, GateRef nativeCode, GateRef func, G std::initializer_list args, JSCallMode mode) { auto env = GetEnvironment(); - Label isFastBuiltins(env); auto data = std::begin(args); + Label isFastBuiltins(env); GateRef numArgs = ZExtInt32ToPtr(actualNumArgs); GateRef isFastBuiltinsMask = Int64(static_cast(1) << MethodLiteral::IsFastBuiltinBit::START_BIT); - Branch(Int64NotEqual(Int64And(callField, isFastBuiltinsMask), Int64(0)), - &isFastBuiltins, notFastBuiltins); + Branch(Int64NotEqual(Int64And(callField, isFastBuiltinsMask), Int64(0)), &isFastBuiltins, notFastBuiltins); Bind(&isFastBuiltins); { GateRef builtinId = GetBuiltinId(method); GateRef ret; switch (mode) { case JSCallMode::CALL_THIS_ARG0: - ret = DispatchBuiltins(glue, builtinId, { glue, nativeCode, func, Undefined(), thisValue, numArgs }); + ret = DispatchBuiltins(glue, builtinId, { glue, nativeCode, func, Undefined(), thisValue, numArgs, + Undefined(), Undefined(), Undefined()}); break; case JSCallMode::CALL_THIS_ARG1: ret = DispatchBuiltins(glue, builtinId, { glue, nativeCode, func, Undefined(), - thisValue, numArgs, data[0] }); + thisValue, numArgs, data[0], Undefined(), Undefined() }); break; case JSCallMode::CALL_THIS_ARG2: ret = DispatchBuiltins(glue, builtinId, { glue, nativeCode, func, Undefined(), thisValue, - numArgs, data[0], data[1] }); + numArgs, data[0], data[1], Undefined() }); break; case JSCallMode::CALL_THIS_ARG3: ret = DispatchBuiltins(glue, builtinId, { glue, nativeCode, func, Undefined(), thisValue, @@ -5284,4 +5437,358 @@ GateRef StubBuilder::ToNumber(GateRef glue, GateRef tagged) env->SubCfgExit(); return ret; } + +GateRef StubBuilder::GetLengthOfJsArray(GateRef glue, GateRef array) +{ + auto env = GetEnvironment(); + Label entry(env); + env->SubCfgEntry(&entry); + Label exit(env); + Label isInt(env); + Label notInt(env); + Label notDouble(env); + Label isDouble(env); + DEFVARIABLE(result, VariableType::INT32(), Int32(0)); + GateRef len = Load(VariableType::JS_ANY(), array, IntPtr(JSArray::LENGTH_OFFSET)); + Branch(TaggedIsInt(len), &isInt, ¬Int); + Bind(&isInt); + { + result = TaggedGetInt(len); + Jump(&exit); + } + Bind(¬Int); + { + Branch(TaggedIsDouble(len), &isDouble, ¬Double); + Bind(&isDouble); + { + result = DoubleToInt(glue, GetDoubleOfTDouble(len)); + Jump(&exit); + } + Bind(¬Double); + { + FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) }); + Jump(&exit); + } + } + Bind(&exit); + auto ret = *result; + env->SubCfgExit(); + return ret; +} + +GateRef StubBuilder::CreateListFromArrayLike(GateRef glue, GateRef arrayObj) +{ + auto env = GetEnvironment(); + Label entry(env); + env->SubCfgEntry(&entry); + DEFVARIABLE(res, VariableType::JS_ANY(), Hole()); + DEFVARIABLE(index, VariableType::INT32(), Int32(0)); + Label exit(env); + + // 3. If Type(obj) is Object, throw a TypeError exception. + Label targetIsHeapObject(env); + Label targetIsEcmaObject(env); + Label targetNotEcmaObject(env); + Branch(TaggedIsHeapObject(arrayObj), &targetIsHeapObject, &targetNotEcmaObject); + Bind(&targetIsHeapObject); + Branch(TaggedObjectIsEcmaObject(arrayObj), &targetIsEcmaObject, &targetNotEcmaObject); + Bind(&targetNotEcmaObject); + { + GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(TargetTypeNotObject)); + CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) }); + Jump(&exit); + } + Bind(&targetIsEcmaObject); + { + // 4. Let len be ToLength(Get(obj, "length")). + GateRef lengthString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, + ConstantIndex::LENGTH_STRING_INDEX); + GateRef value = FastGetPropertyByName(glue, arrayObj, lengthString); + GateRef number = ToLength(glue, value); + // 5. ReturnIfAbrupt(len). + Label isPendingException1(env); + Label noPendingException1(env); + Branch(HasPendingException(glue), &isPendingException1, &noPendingException1); + Bind(&isPendingException1); + { + Jump(&exit); + } + Bind(&noPendingException1); + { + Label indexInRange(env); + Label indexOutRange(env); + GateRef doubleLen = GetDoubleOfTNumber(number); + Branch(DoubleGreaterThan(doubleLen, Double(JSObject::MAX_ELEMENT_INDEX)), &indexOutRange, &indexInRange); + Bind(&indexOutRange); + { + GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(LenGreaterThanMax)); + CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) }); + Jump(&exit); + } + Bind(&indexInRange); + { + GateRef int32Len = DoubleToInt(glue, doubleLen); + // 6. Let list be an empty List. + NewObjectStubBuilder newBuilder(this); + GateRef array = newBuilder.NewTaggedArray(glue, int32Len); + Label targetIsTypeArray(env); + Label targetNotTypeArray(env); + Branch(IsTypedArray(arrayObj), &targetIsTypeArray, &targetNotTypeArray); + Bind(&targetIsTypeArray); + { + TypedArrayStubBuilder arrayStubBuilder(this); + arrayStubBuilder.FastCopyElementToArray(glue, arrayObj, array); + // c. ReturnIfAbrupt(next). + Label isPendingException2(env); + Label noPendingException2(env); + Branch(HasPendingException(glue), &isPendingException2, &noPendingException2); + Bind(&isPendingException2); + { + Jump(&exit); + } + Bind(&noPendingException2); + { + res = array; + Jump(&exit); + } + } + Bind(&targetNotTypeArray); + // 8. Repeat while index < len + Label loopHead(env); + Label loopEnd(env); + Label afterLoop(env); + Label isPendingException3(env); + Label noPendingException3(env); + Label storeValue(env); + Jump(&loopHead); + LoopBegin(&loopHead); + { + Branch(Int32UnsignedLessThan(*index, int32Len), &storeValue, &afterLoop); + Bind(&storeValue); + { + GateRef next = FastGetPropertyByIndex(glue, arrayObj, *index); + // c. ReturnIfAbrupt(next). + Branch(HasPendingException(glue), &isPendingException3, &noPendingException3); + Bind(&isPendingException3); + { + Jump(&exit); + } + Bind(&noPendingException3); + SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *index, next); + index = Int32Add(*index, Int32(1)); + Jump(&loopEnd); + } + } + Bind(&loopEnd); + LoopEnd(&loopHead); + Bind(&afterLoop); + { + res = array; + Jump(&exit); + } + } + } + } + Bind(&exit); + GateRef ret = *res; + env->SubCfgExit(); + return ret; +} + +GateRef StubBuilder::ToLength(GateRef glue, GateRef target) +{ + auto env = GetEnvironment(); + Label subentry(env); + env->SubCfgEntry(&subentry); + DEFVARIABLE(res, VariableType::JS_ANY(), Hole()); + Label exit(env); + + GateRef number = ToNumber(glue, target); + Label isPendingException(env); + Label noPendingException(env); + Branch(HasPendingException(glue), &isPendingException, &noPendingException); + Bind(&isPendingException); + { + Jump(&exit); + } + Bind(&noPendingException); + { + GateRef num = GetDoubleOfTNumber(number); + Label targetLessThanZero(env); + Label targetGreaterThanZero(env); + Label targetLessThanSafeNumber(env); + Label targetGreaterThanSafeNumber(env); + Branch(DoubleLessThan(num, Double(0.0)), &targetLessThanZero, &targetGreaterThanZero); + Bind(&targetLessThanZero); + { + res = DoubleToTaggedDoublePtr(Double(0.0)); + Jump(&exit); + } + Bind(&targetGreaterThanZero); + Branch(DoubleGreaterThan(num, Double(SAFE_NUMBER)), &targetGreaterThanSafeNumber, &targetLessThanSafeNumber); + Bind(&targetGreaterThanSafeNumber); + { + res = DoubleToTaggedDoublePtr(Double(SAFE_NUMBER)); + Jump(&exit); + } + Bind(&targetLessThanSafeNumber); + { + res = number; + Jump(&exit); + } + } + Bind(&exit); + auto ret = *res; + env->SubCfgExit(); + return ret; +} + +GateRef StubBuilder::TaggedGetNumber(GateRef x) +{ + auto env = GetEnvironment(); + Label subentry(env); + Label exit(env); + env->SubCfgEntry(&subentry); + + Label targetIsInt(env); + Label targetIsDouble(env); + DEFVAlUE(number, env_, VariableType::FLOAT64(), Double(0)); + Branch(TaggedIsInt(x), &targetIsInt, &targetIsDouble); + Bind(&targetIsInt); + { + number = ChangeInt32ToFloat64(TaggedGetInt(x)); + Jump(&exit); + } + Bind(&targetIsDouble); + { + number = GetDoubleOfTDouble(x); + Jump(&exit); + } + Bind(&exit); + GateRef ret = *number; + env->SubCfgExit(); + return ret; +} + +GateRef StubBuilder::HasStableElements(GateRef glue, GateRef obj) +{ + auto env = GetEnvironment(); + Label subentry(env); + env->SubCfgEntry(&subentry); + DEFVARIABLE(result, VariableType::BOOL(), False()); + Label exit(env); + Label targetIsHeapObject(env); + Label targetIsStableElements(env); + + Branch(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit); + Bind(&targetIsHeapObject); + { + GateRef jsHclass = LoadHClass(obj); + Branch(IsStableElements(jsHclass), &targetIsStableElements, &exit); + Bind(&targetIsStableElements); + { + GateRef guardiansOffset = IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(env->Is32Bit())); + GateRef guardians = Load(VariableType::JS_ANY(), glue, guardiansOffset); + Label targetIsTaggedTrue(env); + Label targetIsTaggedFalse(env); + Branch(TaggedIsTrue(guardians), &targetIsTaggedTrue, &targetIsTaggedFalse); + Bind(&targetIsTaggedTrue); + { + result = True(); + Jump(&exit); + } + Bind(&targetIsTaggedFalse); + { + result = False(); + Jump(&exit); + } + } + } + Bind(&exit); + auto res = *result; + env->SubCfgExit(); + return res; +} + +GateRef StubBuilder::IsStableJSArguments(GateRef glue, GateRef obj) +{ + auto env = GetEnvironment(); + Label subentry(env); + env->SubCfgEntry(&subentry); + DEFVARIABLE(result, VariableType::BOOL(), False()); + Label exit(env); + Label targetIsHeapObject(env); + Label targetIsStableArguments(env); + + Branch(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit); + Bind(&targetIsHeapObject); + { + GateRef jsHclass = LoadHClass(obj); + Branch(IsStableArguments(jsHclass), &targetIsStableArguments, &exit); + Bind(&targetIsStableArguments); + { + GateRef guardiansOffset = IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(env->Is32Bit())); + GateRef guardians = Load(VariableType::JS_ANY(), glue, guardiansOffset); + + Label targetIsTaggedTrue(env); + Label targetIsTaggedFalse(env); + Branch(TaggedIsTrue(guardians), &targetIsTaggedTrue, &targetIsTaggedFalse); + Bind(&targetIsTaggedTrue); + { + result = True(); + Jump(&exit); + } + Bind(&targetIsTaggedFalse); + { + result = False(); + Jump(&exit); + } + } + } + Bind(&exit); + auto res = *result; + env->SubCfgExit(); + return res; +} + +GateRef StubBuilder::IsStableJSArray(GateRef glue, GateRef obj) +{ + auto env = GetEnvironment(); + Label subentry(env); + env->SubCfgEntry(&subentry); + DEFVARIABLE(result, VariableType::BOOL(), False()); + Label exit(env); + Label targetIsHeapObject(env); + Label targetIsStableArray(env); + + Branch(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit); + Bind(&targetIsHeapObject); + { + GateRef jsHclass = LoadHClass(obj); + Branch(IsStableArray(jsHclass), &targetIsStableArray, &exit); + Bind(&targetIsStableArray); + { + GateRef guardiansOffset = IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(env->Is32Bit())); + GateRef guardians = Load(VariableType::JS_ANY(), glue, guardiansOffset); + + Label targetIsTaggedTrue(env); + Label targetIsTaggedFalse(env); + Branch(TaggedIsTrue(guardians), &targetIsTaggedTrue, &targetIsTaggedFalse); + Bind(&targetIsTaggedTrue); + { + result = True(); + Jump(&exit); + } + Bind(&targetIsTaggedFalse); + { + result = False(); + Jump(&exit); + } + } + } + Bind(&exit); + auto res = *result; + env->SubCfgExit(); + return res; +} } // namespace panda::ecmascript::kungfu diff --git a/ecmascript/compiler/stub_builder.h b/ecmascript/compiler/stub_builder.h index fa9d172b89..dd609064b1 100644 --- a/ecmascript/compiler/stub_builder.h +++ b/ecmascript/compiler/stub_builder.h @@ -226,6 +226,7 @@ public: GateRef InYoungGeneration(GateRef region); GateRef TaggedIsGeneratorObject(GateRef x); GateRef TaggedIsAsyncGeneratorObject(GateRef x); + GateRef TaggedIsJSGlobalObject(GateRef x); GateRef TaggedIsWeak(GateRef x); GateRef TaggedIsPrototypeHandler(GateRef x); GateRef TaggedIsStoreTSHandler(GateRef x); @@ -243,6 +244,7 @@ public: GateRef TaggedIsFalse(GateRef x); GateRef TaggedIsBoolean(GateRef x); GateRef TaggedGetInt(GateRef x); + GateRef TaggedGetNumber(GateRef x); GateRef Int8ToTaggedInt(GateRef x); GateRef Int16ToTaggedInt(GateRef x); GateRef IntToTaggedPtr(GateRef x); @@ -282,6 +284,8 @@ public: GateRef ChangeInt64ToIntPtr(GateRef val); GateRef ZExtInt32ToPtr(GateRef val); GateRef ChangeIntPtrToInt32(GateRef val); + GateRef ToLength(GateRef glue, GateRef target); + // math operation GateRef Sqrt(GateRef x); GateRef GetSetterFromAccessor(GateRef accessor); @@ -292,6 +296,7 @@ public: void SetPropertiesArray(VariableType type, GateRef glue, GateRef object, GateRef propsArray); void SetHash(GateRef glue, GateRef object, GateRef hash); GateRef GetLengthOfTaggedArray(GateRef array); + GateRef GetLengthOfJsArray(GateRef glue, GateRef array); // object operation GateRef IsJSHClass(GateRef obj); GateRef LoadHClass(GateRef object); @@ -301,6 +306,7 @@ public: GateRef IsDictionaryMode(GateRef object); GateRef IsDictionaryModeByHClass(GateRef hClass); GateRef IsDictionaryElement(GateRef hClass); + GateRef IsStableElements(GateRef hClass); GateRef IsClassConstructorFromBitField(GateRef bitfield); GateRef IsClassConstructor(GateRef object); GateRef IsClassPrototype(GateRef object); @@ -371,7 +377,12 @@ public: void TryFastHasInstance(GateRef glue, GateRef instof, GateRef target, GateRef object, Label *fastPath, Label *exit, Variable *result); GateRef SameValue(GateRef glue, GateRef left, GateRef right); - + GateRef HasStableElements(GateRef glue, GateRef obj); + GateRef IsStableJSArguments(GateRef glue, GateRef obj); + GateRef IsStableJSArray(GateRef glue, GateRef obj); + GateRef IsTypedArray(GateRef obj); + GateRef IsStableArguments(GateRef hClass); + GateRef IsStableArray(GateRef hClass); // SetDictionaryOrder func in property_attribute.h GateRef SetDictionaryOrderFieldInPropAttr(GateRef attr, GateRef value); GateRef GetPrototypeFromHClass(GateRef hClass); @@ -510,6 +521,7 @@ public: GateRef GetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index); GateRef GetPropertyByName(GateRef glue, GateRef receiver, GateRef key); GateRef FastGetPropertyByName(GateRef glue, GateRef obj, GateRef key); + GateRef FastGetPropertyByIndex(GateRef glue, GateRef obj, GateRef index); GateRef GetPropertyByValue(GateRef glue, GateRef receiver, GateRef keyValue); GateRef SetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value, bool useOwn); GateRef SetPropertyByName(GateRef glue, GateRef receiver, GateRef key, @@ -538,6 +550,9 @@ public: GateRef GetMethodFromConstPool(GateRef glue, GateRef constpool, GateRef index); GateRef GetArrayLiteralFromConstPool(GateRef glue, GateRef constpool, GateRef index, GateRef module); GateRef GetObjectLiteralFromConstPool(GateRef glue, GateRef constpool, GateRef index, GateRef module); + GateRef CreateListFromArrayLike(GateRef glue, GateRef arrayObj); + GateRef BuildArgumentsListFastElements(GateRef glue, GateRef arrayObj); + GateRef MakeArgListWithHole(GateRef glue, GateRef argv, GateRef length); void SetExtensibleToBitfield(GateRef glue, GateRef obj, bool isExtensible); // fast path diff --git a/ecmascript/compiler/trampoline/aarch64/asm_interpreter_call.cpp b/ecmascript/compiler/trampoline/aarch64/asm_interpreter_call.cpp index e9aec95cfc..02e24872f8 100644 --- a/ecmascript/compiler/trampoline/aarch64/asm_interpreter_call.cpp +++ b/ecmascript/compiler/trampoline/aarch64/asm_interpreter_call.cpp @@ -326,6 +326,7 @@ Register AsmInterpreterCall::GetThisRegsiter(ExtendedAssembler *assembler, JSCal case JSCallMode::CALL_THIS_ARG2: case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV: case JSCallMode::CALL_THIS_WITH_ARGV: + case JSCallMode::CALL_THIS_ARGV_WITH_RETURN: return __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG2); case JSCallMode::CALL_THIS_ARG3: case JSCallMode::CALL_THIS_ARG3_WITH_RETURN: @@ -521,7 +522,7 @@ void AsmInterpreterCall::CallNativeWithArgv(ExtendedAssembler *assembler, bool c Register frameType(X11); __ Ldr(temp, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); __ Mov(spRegister, temp); - __ Mov(frameType, Immediate(static_cast(FrameType::BUILTIN_FRAME_WITH_ARGV))); + __ Mov(frameType, Immediate(static_cast(FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME))); // 2: frame type and argc __ Stp(Register(Zero), frameType, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); __ Mov(temp, Immediate(JSTaggedValue::VALUE_UNDEFINED)); @@ -529,8 +530,6 @@ void AsmInterpreterCall::CallNativeWithArgv(ExtendedAssembler *assembler, bool c __ Stp(temp, temp, MemoryOperand(spRegister, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); // 2: fill func&align slots __ Stp(Register(Zero), temp, MemoryOperand(spRegister, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); - __ Mov(temp, spRegister); - __ Add(Register(FP), temp, Immediate(48)); // 48: skip frame type, numArgs, func, newTarget, this and align Register runtimeId(X11); Register trampoline(X12); @@ -614,14 +613,10 @@ void AsmInterpreterCall::PushBuiltinFrame(ExtendedAssembler *assembler, Register // 16: type & next __ Stp(next, op, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); __ Add(Register(FP), sp, Immediate(2 * FRAME_SLOT_SIZE)); // 16: skip next and frame type - } else if (type == FrameType::BUILTIN_ENTRY_FRAME) { + } else { // 16: type & next __ Stp(next, op, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); __ Add(Register(FP), sp, Immediate(2 * FRAME_SLOT_SIZE)); // 16: skip next and frame type - } else { - ASSERT(type == FrameType::BUILTIN_FRAME_WITH_ARGV); - // 16: type & next - __ Stp(next, op, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); } } @@ -882,6 +877,28 @@ void AsmInterpreterCall::CallContainersArgs3(ExtendedAssembler *assembler) } } +// c++ calling convention +// X0 - glue +// X1 - callTarget +// X2 - method +// X3 - callField +// X4 - arg0(argc) +// X5 - arg1(arglist) +// X6 - arg3(argthis) +void AsmInterpreterCall::CallReturnWithArgv(ExtendedAssembler *assembler) +{ + __ BindAssemblerStub(RTSTUB_ID(CallReturnWithArgv)); + Label target; + PushAsmInterpBridgeFrame(assembler); + __ Bl(&target); + PopAsmInterpBridgeFrame(assembler); + __ Ret(); + __ Bind(&target); + { + JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARGV_WITH_RETURN); + } +} + // Generate code for generator re-entering asm interpreter // c++ calling convention // Input: %X0 - glue diff --git a/ecmascript/compiler/trampoline/aarch64/common_call.h b/ecmascript/compiler/trampoline/aarch64/common_call.h index d20da3c0c8..3b695acad9 100644 --- a/ecmascript/compiler/trampoline/aarch64/common_call.h +++ b/ecmascript/compiler/trampoline/aarch64/common_call.h @@ -171,6 +171,8 @@ public: static void CallContainersArgs3(ExtendedAssembler *assembler); + static void CallReturnWithArgv([[maybe_unused]]ExtendedAssembler *assembler); + private: static void PushCallThis(ExtendedAssembler *assembler, JSCallMode mode, Label *stackOverflow); diff --git a/ecmascript/compiler/trampoline/x64/asm_interpreter_call.cpp b/ecmascript/compiler/trampoline/x64/asm_interpreter_call.cpp index 631da6367d..f8853e7300 100644 --- a/ecmascript/compiler/trampoline/x64/asm_interpreter_call.cpp +++ b/ecmascript/compiler/trampoline/x64/asm_interpreter_call.cpp @@ -568,6 +568,9 @@ Register AsmInterpreterCall::GetThisRegsiter(ExtendedAssembler *assembler, JSCal } case JSCallMode::CALL_THIS_ARG3_WITH_RETURN: return __ CppJSCallAvailableRegister2(); + case JSCallMode::CALL_THIS_ARGV_WITH_RETURN: { + return __ CppJSCallAvailableRegister1(); + } default: LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); @@ -816,13 +819,12 @@ void AsmInterpreterCall::CallNativeWithArgv(ExtendedAssembler *assembler, bool c __ Bind(&stackOverflow); { Label aligneThrow; - __ Movq(rsp, Operand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); - __ Pushq(static_cast(FrameType::BUILTIN_FRAME_WITH_ARGV)); // frame type + __ Movq(static_cast(FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME), + Operand(rsp, FRAME_SLOT_SIZE)); __ Pushq(0); // argc __ Pushq(JSTaggedValue::VALUE_UNDEFINED); // this __ Pushq(JSTaggedValue::VALUE_UNDEFINED); // newTarget __ Pushq(JSTaggedValue::VALUE_UNDEFINED); // callTarget - __ Leaq(Operand(rsp, 5 * FRAME_SLOT_SIZE), rbp); // 40: skip frame type, numArgs, func, newTarget and this __ Testq(0xf, rsp); // 0xf: 0x1111 __ Jz(&aligneThrow, Distance::Near); @@ -922,9 +924,7 @@ void AsmInterpreterCall::PushBuiltinFrame(ExtendedAssembler *assembler, __ Pushq(rbp); __ Movq(rsp, Operand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); __ Pushq(static_cast(type)); - if (type != FrameType::BUILTIN_FRAME_WITH_ARGV) { - __ Leaq(Operand(rsp, FRAME_SLOT_SIZE), rbp); // 8: skip frame type - } + __ Leaq(Operand(rsp, FRAME_SLOT_SIZE), rbp); // 8: skip frame type } void AsmInterpreterCall::CallNativeInternal(ExtendedAssembler *assembler, Register nativeCode) @@ -1071,6 +1071,29 @@ void AsmInterpreterCall::CallSetter(ExtendedAssembler *assembler) JSCallCommonEntry(assembler, JSCallMode::CALL_SETTER); } +// Input: glue - %rdi +// callTarget - %rsi +// method - %rdx +// callField - %rcx +// arg0(argc) - %r8 +// arg1(arglist) - %r9 +// argthis - stack +void AsmInterpreterCall::CallReturnWithArgv(ExtendedAssembler *assembler) +{ + __ BindAssemblerStub(RTSTUB_ID(CallReturnWithArgv)); + Label target; + PushAsmInterpBridgeFrame(assembler); + Register r13 = __ CppJSCallAvailableRegister1(); + __ Movq(Operand(rbp, FRAME_SLOT_SIZE), r13); + __ Callq(&target); + PopAsmInterpBridgeFrame(assembler); + __ Ret(); + __ Bind(&target); + { + JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARGV_WITH_RETURN); + } +} + void AsmInterpreterCall::CallContainersArgs3(ExtendedAssembler *assembler) { __ BindAssemblerStub(RTSTUB_ID(CallContainersArgs3)); diff --git a/ecmascript/compiler/trampoline/x64/common_call.h b/ecmascript/compiler/trampoline/x64/common_call.h index af96d95050..8bbdd1e7ac 100644 --- a/ecmascript/compiler/trampoline/x64/common_call.h +++ b/ecmascript/compiler/trampoline/x64/common_call.h @@ -137,6 +137,8 @@ public: static void CallContainersArgs3(ExtendedAssembler *assembler); + static void CallReturnWithArgv(ExtendedAssembler *assembler); + static void ResumeCaughtFrameAndDispatch(ExtendedAssembler *assembler); static void ResumeUncaughtFrameAndReturn(ExtendedAssembler *assembler); diff --git a/ecmascript/frames.cpp b/ecmascript/frames.cpp index b22d142dc7..60cc23183f 100644 --- a/ecmascript/frames.cpp +++ b/ecmascript/frames.cpp @@ -89,6 +89,7 @@ JSTaggedValue FrameIterator::GetFunction() const auto *frame = OptimizedBuiltinLeaveFrame::GetFrameFromSp(GetSp()); return JSTaggedValue(*(frame->GetArgv())); } + case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME : case FrameType::OPTIMIZED_FRAME: case FrameType::OPTIMIZED_ENTRY_FRAME: case FrameType::ASM_BRIDGE_FRAME: @@ -260,6 +261,16 @@ void FrameIterator::Advance() current_ = frame->GetPrevFrameFp(); break; } + case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME : { + auto frame = GetFrame(); + if constexpr (GCVisit == GCVisitedFlag::VISITED) { + optimizedReturnAddr_ = frame->GetReturnAddr(); + optimizedCallSiteSp_ = GetPrevFrameCallSiteSp(); + needCalCallSiteInfo = true; + } + current_ = frame->GetPrevFrameFp(); + break; + } case FrameType::INTERPRETER_ENTRY_FRAME : { auto frame = GetFrame(); if constexpr (GCVisit == GCVisitedFlag::VISITED) { @@ -329,6 +340,10 @@ uintptr_t FrameIterator::GetPrevFrameCallSiteSp() const auto frame = GetFrame(); return frame->GetCallSiteSp(); } + case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME: { + auto frame = GetFrame(); + return frame->GetCallSiteSp(); + } case FrameType::BUILTIN_FRAME: { auto frame = GetFrame(); return frame->GetCallSiteSp(); @@ -777,6 +792,10 @@ bool GetTypeOffsetAndPrevOffsetFromFrameType(uintptr_t frameType, uintptr_t &typ typeOffset = MEMBER_OFFSET(BuiltinWithArgvFrame, type); prevOffset = MEMBER_OFFSET(BuiltinWithArgvFrame, prevFp); break; + case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME: + typeOffset = MEMBER_OFFSET(BuiltinWithArgvFrame, type); + prevOffset = MEMBER_OFFSET(BuiltinWithArgvFrame, prevFp); + break; case FrameType::INTERPRETER_ENTRY_FRAME: typeOffset = MEMBER_OFFSET(InterpretedEntryFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, type); diff --git a/ecmascript/frames.h b/ecmascript/frames.h index fa3e1dacef..69d0228592 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -131,6 +131,7 @@ enum class FrameType: uintptr_t { ASM_INTERPRETER_BRIDGE_FRAME, OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME, OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME, + BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME, FRAME_TYPE_FIRST = OPTIMIZED_FRAME, FRAME_TYPE_LAST = OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME, @@ -162,6 +163,7 @@ enum class JSCallMode : uintptr_t { CALL_GETTER, CALL_SETTER, CALL_THIS_ARG3_WITH_RETURN, + CALL_THIS_ARGV_WITH_RETURN, CALL_ENTRY, CALL_GENERATOR, CALL_FROM_AOT, diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index 9f95a61245..f0395c2a0b 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -187,6 +187,7 @@ JSTaggedValue FrameHandler::GetFunction() const auto *frame = OptimizedJSFunctionFrame::GetFrameFromSp(sp_); return frame->GetFunction(); } + case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME : case FrameType::INTERPRETER_FRAME: case FrameType::INTERPRETER_FAST_NEW_FRAME: case FrameType::INTERPRETER_ENTRY_FRAME: @@ -298,6 +299,7 @@ ARK_INLINE uintptr_t FrameHandler::GetInterpretedFrameEnd(JSTaggedType *prevSp) end = ToUintPtr(frame); break; } + case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME : case FrameType::BUILTIN_FRAME_WITH_ARGV: case FrameType::BUILTIN_ENTRY_FRAME: case FrameType::BUILTIN_FRAME: @@ -426,6 +428,7 @@ void FrameHandler::IterateFrameChain(JSTaggedType *start, const RootVisitor &vis frame->GCIterate(it, visitor, rangeVisitor); break; } + case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME: case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME: case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME: case FrameType::OPTIMIZED_ENTRY_FRAME: diff --git a/ecmascript/js_tagged_value-inl.h b/ecmascript/js_tagged_value-inl.h index a3bdbe4d51..a46e26b73a 100644 --- a/ecmascript/js_tagged_value-inl.h +++ b/ecmascript/js_tagged_value-inl.h @@ -39,7 +39,6 @@ namespace panda::ecmascript { // ecma6 7.1 Type Conversion -static constexpr double SAFE_NUMBER = 9007199254740991LL; static constexpr uint32_t MAX_ELEMENT_INDEX_LEN = 10; inline bool JSTaggedValue::ToBoolean() const diff --git a/ecmascript/js_tagged_value.h b/ecmascript/js_tagged_value.h index 4a1351eda7..db6f6523c1 100644 --- a/ecmascript/js_tagged_value.h +++ b/ecmascript/js_tagged_value.h @@ -35,6 +35,8 @@ class OperationResult; class EcmaString; class JSThread; +static constexpr double SAFE_NUMBER = 9007199254740991LL; + // Don't switch the order! enum PreferredPrimitiveType : uint8_t { PREFER_NUMBER = 0, PREFER_STRING, NO_PREFERENCE }; diff --git a/ecmascript/message_string.h b/ecmascript/message_string.h index ef2f1cc126..b569369e9d 100644 --- a/ecmascript/message_string.h +++ b/ecmascript/message_string.h @@ -36,7 +36,13 @@ namespace panda::ecmascript { V(INT32_VALUE, "value: %ld") \ V(TargetTypeNotObject, "Type of target is not Object") \ V(CanNotGetNotEcmaObject, "Can not get Prototype on non ECMA Object") \ - V(InstanceOfErrorTargetNotCallable, "InstanceOf error when target is not Callable") + V(InstanceOfErrorTargetNotCallable, "InstanceOf error when target is not Callable") \ + V(ApplyTargetNotCallable, "apply target is not callable") \ + V(TargetNotStableJSArray, "target not stable JSArray") \ + V(LenGreaterThanMax, "len is bigger than 2^32 - 1") \ + V(ElementTypeNoElementTypes, "CreateListFromArrayLike: not an element of elementTypes") \ + V(TargetIsDetachedBuffer, "Is Detached Buffer") \ + V(ThisBranchIsUnreachable, "this branch is unreachable") #define DEBUG_CHECK_MESSAGE_STRING_LIST(V) \ V(IsCallable) \ diff --git a/ecmascript/stubs/runtime_stubs.h b/ecmascript/stubs/runtime_stubs.h index 32f8c90d08..0d0f3fb9e1 100644 --- a/ecmascript/stubs/runtime_stubs.h +++ b/ecmascript/stubs/runtime_stubs.h @@ -67,7 +67,8 @@ using JSFunctionEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, con V(ResumeUncaughtFrameAndReturn) \ V(CallSetter) \ V(CallGetter) \ - V(CallContainersArgs3) + V(CallContainersArgs3) \ + V(CallReturnWithArgv) #define JS_CALL_TRAMPOLINE_LIST(V) \ V(CallRuntime) \ diff --git a/test/moduletest/builtins/builtinsir.js b/test/moduletest/builtins/builtinsir.js index f3aa9ef971..1a5437df67 100644 --- a/test/moduletest/builtins/builtinsir.js +++ b/test/moduletest/builtins/builtinsir.js @@ -34,4 +34,15 @@ print(str1.indexOf("hjs", 19)); print(str1.indexOf("jk", 3)); print(str1.indexOf(undefined)); print(str1.indexOf(null)); +var person = { +fullName: function(city, country) { + return this.firstName + " " + this.lastName + "," + city + "," + country; +} +} +var person1 = { +firstName:"Bill", +lastName: "Gates" +} +var a = new Uint32Array([1,2]); +print(person.fullName.apply(person1, a)); print("builtins ir end"); diff --git a/test/moduletest/builtins/expect_output.txt b/test/moduletest/builtins/expect_output.txt index bae3614d44..e947436280 100644 --- a/test/moduletest/builtins/expect_output.txt +++ b/test/moduletest/builtins/expect_output.txt @@ -30,6 +30,7 @@ NaN 5 -1 -1 +Bill Gates,1,2 builtins ir end builtins number start parseInt result = 16947500000