diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index 2dee2e84739d599561e30925fd51a18ad21ade6f..0b9bf373f8056005280f03920bd574c8770554af 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -1160,4 +1160,29 @@ void FastModStub::GenerateCircuit() } } } + +void FunctionCallInternalStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + AddrShift thread = PtrArgument(0); + AddrShift func = PtrArgument(1); + AddrShift thisArg = Int64Argument(2); /* 2 : 3rd parameter is value */ + AddrShift argc = Int32Argument(3); /* 3 : 4th parameter is value */ + AddrShift argv = PtrArgument(4); /* 4 : 5th parameter is ptr */ + Label funcNotBuiltinsConstructor(env); + Label funcIsBuiltinsConstructorOrFuncNotClassConstructor(env); + Label funcIsClassConstructor(env); + Branch(NotBuiltinsConstructor(func), &funcNotBuiltinsConstructor, + &funcIsBuiltinsConstructorOrFuncNotClassConstructor); + Bind(&funcNotBuiltinsConstructor); + { + Branch(IsClassConstructor(func), &funcIsClassConstructor, &funcIsBuiltinsConstructorOrFuncNotClassConstructor); + Bind(&funcIsClassConstructor); + ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(FunctionCallNotConstructor), FalseConstant()); + } + Bind(&funcIsBuiltinsConstructorOrFuncNotClassConstructor); + StubDescriptor *execute = GET_STUBDESCRIPTOR(Execute); + Return(CallRuntime(execute, thread, GetWord64Constant(FAST_STUB_ID(Execute)), + {thread, func, thisArg, argc, argv})); +} } // namespace kungfu \ No newline at end of file diff --git a/ecmascript/compiler/fast_stub.h b/ecmascript/compiler/fast_stub.h index 109b7be5d62f9595c2e778ac4b298c0e1b3c3650..642d5c2063a73298db2b162fb528516819291346 100644 --- a/ecmascript/compiler/fast_stub.h +++ b/ecmascript/compiler/fast_stub.h @@ -149,5 +149,15 @@ public: NO_COPY_SEMANTIC(FastModStub); void GenerateCircuit() override; }; + +class FunctionCallInternalStub : public Stub { +public: + // 5 : 5 means argument counts + explicit FunctionCallInternalStub(Circuit *circuit) : Stub("FunctionCallInternal", 5, circuit) {} + ~FunctionCallInternalStub() = default; + NO_MOVE_SEMANTIC(FunctionCallInternalStub); + NO_COPY_SEMANTIC(FunctionCallInternalStub); + void GenerateCircuit() override; +}; } // namespace kungfu #endif // ECMASCRIPT_COMPILER_FASTPATH_STUB_H \ No newline at end of file diff --git a/ecmascript/compiler/fast_stub_define.h b/ecmascript/compiler/fast_stub_define.h index 036fc11f4e623b528380258f536bbbef89a6188d..9147c850092f7a4a964b34c9c37a2af638cf742d 100644 --- a/ecmascript/compiler/fast_stub_define.h +++ b/ecmascript/compiler/fast_stub_define.h @@ -27,6 +27,7 @@ namespace kungfu { V(JSProxySetProperty, 6) \ V(GetHash32, 2) \ V(FindElementWithCache, 4) \ + V(Execute, 5) \ V(StringGetHashCode, 1) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) @@ -57,6 +58,7 @@ namespace kungfu { V(FindOwnProperty2, 6) \ V(FindOwnElement2, 6) \ V(GetPropertyByIndex, 3) \ + V(FunctionCallInternal, 5) \ V(SetPropertyByIndex, 4) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index d5e801fa9e7669ca32c928588dcb450b99234f57..4550be2bf28cd8a4bd51080911b3c9c7fb353b1c 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -646,9 +646,10 @@ AddrShift Stub::JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift a void Stub::ThrowTypeAndReturn(AddrShift thread, int messageId, AddrShift val) { + AddrShift taggedId = GetInteger32Constant(messageId); StubDescriptor *throwTypeError = GET_STUBDESCRIPTOR(ThrowTypeError); - AddrShift taggedId = IntBuildTagged(GetInteger32Constant(messageId)); - CallStub(throwTypeError, GetWord64Constant(FAST_STUB_ID(ThrowTypeError)), {thread, taggedId}); + CallRuntime(throwTypeError, thread, GetWord64Constant(FAST_STUB_ID(ThrowTypeError)), + {thread, taggedId}); Return(val); } diff --git a/ecmascript/compiler/stub.h b/ecmascript/compiler/stub.h index 1ae07f2419c8db6a031efc1a796cb6191f486031..c6042d41e56f8e08cbe3e7c7a130c2bf61937b10 100644 --- a/ecmascript/compiler/stub.h +++ b/ecmascript/compiler/stub.h @@ -22,6 +22,7 @@ #include "ecmascript/compiler/circuit_builder.h" #include "ecmascript/compiler/gate.h" #include "ecmascript/compiler/stub_descriptor.h" +#include "ecmascript/js_function.h" #include "ecmascript/js_object.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/layout_info.h" @@ -1065,6 +1066,35 @@ public: GetWord64Constant(0)); } + AddrShift NotBuiltinsConstructor(AddrShift object) + { + AddrShift hclass = LoadHClass(object); + AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); + + AddrShift bitfield = Load(INT64_TYPE, hclass, bitfieldOffset); + // decode + return Word64Equal( + Word64And( + Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::BuiltinsCtorBit::START_BIT)), + GetWord64Constant((1LLU << panda::ecmascript::JSHClass::BuiltinsCtorBit::SIZE) - 1)), + GetWord64Constant(0)); + } + + AddrShift IsClassConstructor(AddrShift object) + { + AddrShift functionInfoFlagOffset = GetPtrConstant(panda::ecmascript::JSFunction::FUNCTION_INFO_FLAG_OFFSET); + AddrShift functionInfoTaggedValue = Load(MachineType::UINT64_TYPE, object, functionInfoFlagOffset); + AddrShift functionInfoInt32 = TaggedCastToInt32(functionInfoTaggedValue); + AddrShift functionInfoFlag = ZExtInt32ToInt64(functionInfoInt32); + // decode + return Word64NotEqual( + Word64And( + Word64LSR(functionInfoFlag, + GetWord64Constant(panda::ecmascript::JSFunction::ClassConstructorBit::START_BIT)), + GetWord64Constant((1LLU << panda::ecmascript::JSFunction::ClassConstructorBit::SIZE) - 1)), + GetWord64Constant(0)); + } + AddrShift IsExtensible(AddrShift object) { AddrShift hclass = LoadHClass(object); diff --git a/ecmascript/compiler/stub_aot_compiler.cpp b/ecmascript/compiler/stub_aot_compiler.cpp index 79d0ab6d8ccdeb12748f120a47735646ee1070b3..6bfb263536384738db92f61d2bb2c2e5a17ec8c4 100644 --- a/ecmascript/compiler/stub_aot_compiler.cpp +++ b/ecmascript/compiler/stub_aot_compiler.cpp @@ -159,6 +159,7 @@ void StubAotCompiler::BuildStubModuleAndSave(const char *triple, panda::ecmascri SET_STUB_TO_MODULE(module, SetElement) \ SET_STUB_TO_MODULE(module, GetPropertyByIndex) \ SET_STUB_TO_MODULE(module, SetPropertyByIndex) \ + SET_STUB_TO_MODULE(module, FunctionCallInternal) \ SET_STUB_TO_MODULE(module, GetPropertyByName) int main(const int argc, const char **argv) diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index 135f379f5f2299be55d3ade4440bdfe0505bea63..ea20f07e1061593959442c2ac154b8f1c9dc7acd 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -334,6 +334,39 @@ CALL_STUB_INIT_DESCRIPTOR(FindElementWithCache) descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); } +CALL_STUB_INIT_DESCRIPTOR(Execute) +{ + // 5 : 5 input parameters + static StubDescriptor execute("Execute", 0, 5, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + *descriptor = execute; + std::array params = { // 5 : 5 input parameters + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + MachineType::UINT32_TYPE, + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); +} + +CALL_STUB_INIT_DESCRIPTOR(FunctionCallInternal) +{ + // 5 : 5 input parameters + static StubDescriptor functionCallInternal("FunctionCallInternal", 0, 5, + ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE); + *descriptor = functionCallInternal; + std::array params = { // 5 : 5 input parameters + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + MachineType::UINT32_TYPE, + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); +} + CALL_STUB_INIT_DESCRIPTOR(StringGetHashCode) { static StubDescriptor stringGetHashCode("StringGetHashCode", 0, 1, ArgumentsOrder::DEFAULT_ORDER, UINT32_TYPE); diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index 173fda779df148018bb61e926358d300cdc16e04..8bd6d0b5b65f217c257b2b39d78d898b53c5e144 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -502,6 +502,22 @@ HWTEST_F_L0(StubTest, FastFindOwnElementStub) assembler.Run(); } +HWTEST_F_L0(StubTest, FunctionCallInternal) +{ + auto module = stubModule.GetModule(); + auto findFunction = stubModule.GetStubFunction(FAST_STUB_ID(FunctionCallInternal)); + Circuit netOfGates; + FunctionCallInternalStub optimizer(&netOfGates); + optimizer.GenerateCircuit(); + netOfGates.PrintAllGates(); + auto cfg = Scheduler::Run(&netOfGates); + PrintCircuitByBasicBlock(cfg, netOfGates); + LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, findFunction); + llvmBuilder.Build(); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); + assembler.Run(); +} + HWTEST_F_L0(StubTest, GetElementStub) { auto module = stubModule.GetModule(); diff --git a/ecmascript/message_string.h b/ecmascript/message_string.h index 61a6ba1bfcd501a3dffb9f1db0205012f0bfde38..144f8bdb21edb9a9abfbf5f6dd2eee4bfc747acd 100644 --- a/ecmascript/message_string.h +++ b/ecmascript/message_string.h @@ -20,8 +20,9 @@ namespace panda::ecmascript { // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define MESSAGE_STRING_LIST(V) \ - V(SetReadOnlyProperty, "Cannot set readonly property") \ +#define MESSAGE_STRING_LIST(V) \ + V(SetReadOnlyProperty, "Cannot set readonly property") \ + V(FunctionCallNotConstructor, "class constructor cannot call") \ V(SetPropertyWhenNotExtensible, "Cannot add property in prevent extensions ") class MessageString { diff --git a/ecmascript/runtime_trampolines.cpp b/ecmascript/runtime_trampolines.cpp index e9592ee8ac357d6779c10fd736c7ee520e7a6158..36457e055a7c592dce59f1d48f100a23ea4fd7dd 100644 --- a/ecmascript/runtime_trampolines.cpp +++ b/ecmascript/runtime_trampolines.cpp @@ -22,6 +22,7 @@ #include "ecmascript/layout_info.h" #include "ecmascript/message_string.h" #include "ecmascript/object_factory.h" +#include "ecmascript/interpreter/interpreter-inl.h" namespace panda::ecmascript { bool RuntimeTrampolines::AddElementInternal(uint64_t argThread, uint64_t argReceiver, uint32_t argIndex, @@ -122,4 +123,20 @@ uint32_t RuntimeTrampolines::StringGetHashCode(uint64_t ecmaString) auto string = reinterpret_cast(ecmaString); return string->GetHashcode(); } + +uint64_t RuntimeTrampolines::Execute(uint64_t argThread, uint64_t argFunc, + uint64_t thisArg, uint32_t argc, uint64_t argArgv) +{ + auto thread = reinterpret_cast(argThread); + auto func = reinterpret_cast(argFunc); + auto argv = reinterpret_cast(argArgv); + CallParams params; + params.callTarget = func; + params.newTarget = JSTaggedValue::VALUE_UNDEFINED; + params.thisArg = thisArg; + params.argc = argc; + params.argv = argv; + + return EcmaInterpreter::Execute(thread, params).GetRawData(); +} } // namespace panda::ecmascript diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index 7d7c286760eeafbfabb423cbda233808e9e399d1..62a20bb957b515734722ba57bc9bddab6ff38a6c 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -48,6 +48,7 @@ public: static uint32_t GetHash32(uint64_t key, uint64_t len); static int32_t FindElementWithCache(uint64_t argThread, uint64_t hClass, uint64_t key, int32_t num); static uint32_t StringGetHashCode(uint64_t ecmaString); + static uint64_t Execute(uint64_t argThread, uint64_t argFunc, uint64_t thisArg, uint32_t argc, uint64_t argArgv); }; class CallRuntimeTrampolinesScope {