1/* 2 * Copyright (c) 2022-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "ecmascript/method.h" 17 18#include "ecmascript/jspandafile/program_object.h" 19 20namespace panda::ecmascript { 21std::string Method::ParseFunctionName() const 22{ 23 const JSPandaFile *jsPandaFile = GetJSPandaFile(); 24 return MethodLiteral::ParseFunctionName(jsPandaFile, GetMethodId()); 25} 26 27std::pair<std::string_view, bool> Method::ParseFunctionNameView() const 28{ 29 const JSPandaFile *jsPandaFile = GetJSPandaFile(); 30 return MethodLiteral::ParseFunctionNameView(jsPandaFile, GetMethodId()); 31} 32 33const char *Method::GetMethodName() const 34{ 35 const JSPandaFile *jsPandaFile = GetJSPandaFile(); 36 return MethodLiteral::GetMethodName(jsPandaFile, GetMethodId()); 37} 38 39const char *Method::GetMethodName(const JSPandaFile *file) const 40{ 41 return MethodLiteral::GetMethodName(file, GetMethodId()); 42} 43 44const CString Method::GetRecordNameStr() const 45{ 46 const JSPandaFile *jsPandaFile = GetJSPandaFile(); 47 return MethodLiteral::GetRecordName(jsPandaFile, GetMethodId()); 48} 49 50uint32_t Method::GetCodeSize() const 51{ 52 const JSPandaFile *jsPandaFile = GetJSPandaFile(); 53 return MethodLiteral::GetCodeSize(jsPandaFile, GetMethodId()); 54} 55 56const JSPandaFile *Method::GetJSPandaFile() const 57{ 58 JSTaggedValue constpool = GetConstantPool(); 59 if (constpool.IsUndefined()) { 60 return nullptr; 61 } 62 63 const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); 64 return taggedPool->GetJSPandaFile(); 65} 66 67MethodLiteral *Method::GetMethodLiteral() const 68{ 69 if (IsAotWithCallField() || IsDeoptimized()) { 70 ASSERT(!IsNativeWithCallField()); 71 const JSPandaFile *jsPandaFile = GetJSPandaFile(); 72 ASSERT(jsPandaFile != nullptr); 73 return jsPandaFile->FindMethodLiteral(GetMethodId().GetOffset()); 74 } 75 return reinterpret_cast<MethodLiteral *>(GetCodeEntryOrLiteral()); 76} 77 78bool Method::IsDeoptimized() const 79{ 80 return GetDeoptType() != kungfu::DeoptType::NONE; 81} 82 83uint32_t Method::FindCatchBlock(uint32_t pc) const 84{ 85 ASSERT(!IsNativeWithCallField()); 86 ASSERT(GetJSPandaFile() != nullptr); 87 auto *pandaFile = GetJSPandaFile()->GetPandaFile(); 88 ASSERT(pandaFile != nullptr); 89 panda_file::MethodDataAccessor mda(*pandaFile, GetMethodId()); 90 panda_file::CodeDataAccessor cda(*pandaFile, mda.GetCodeId().value()); 91 92 uint32_t pcOffset = INVALID_INDEX; 93 cda.EnumerateTryBlocks([&pcOffset, pc](panda_file::CodeDataAccessor::TryBlock &tryBlock) { 94 if ((tryBlock.GetStartPc() <= pc) && ((tryBlock.GetStartPc() + tryBlock.GetLength()) > pc)) { 95 tryBlock.EnumerateCatchBlocks([&](panda_file::CodeDataAccessor::CatchBlock &catchBlock) { 96 pcOffset = catchBlock.GetHandlerPc(); 97 return false; 98 }); 99 } 100 return pcOffset == INVALID_INDEX; 101 }); 102 return pcOffset; 103} 104 105bool Method::HasCatchBlock() const 106{ 107 ASSERT(GetJSPandaFile() != nullptr); 108 auto *pandaFile = GetJSPandaFile()->GetPandaFile(); 109 ASSERT(pandaFile != nullptr); 110 panda_file::MethodDataAccessor mda(*pandaFile, GetMethodId()); 111 panda_file::CodeDataAccessor cda(*pandaFile, mda.GetCodeId().value()); 112 return cda.GetTriesSize() != 0; 113} 114 115JSHandle<Method> Method::Create(JSThread *thread, const JSPandaFile *jsPandaFile, MethodLiteral *methodLiteral) 116{ 117 EcmaVM *vm = thread->GetEcmaVM(); 118 EntityId methodId = methodLiteral->GetMethodId(); 119 JSTaggedValue patchVal = vm->GetQuickFixManager()->CheckAndGetPatch(thread, jsPandaFile, methodId); 120 if (!patchVal.IsHole()) { 121 return JSHandle<Method>(thread, patchVal); 122 } 123 124 JSHandle<Method> method; 125 method = vm->GetFactory()->NewSMethod(methodLiteral); 126 JSHandle<ConstantPool> newConstpool = thread->GetCurrentEcmaContext()->FindOrCreateConstPool(jsPandaFile, methodId); 127 method->SetConstantPool(thread, newConstpool); 128 return method; 129} 130 131void Method::SetCodeEntryAndMarkAOTWhenBinding(uintptr_t codeEntry) 132{ 133 SetAotCodeBit(true); 134 SetNativeBit(false); 135 SetCodeEntryOrLiteral(codeEntry); 136} 137 138void Method::ClearAOTStatusWhenDeopt(uintptr_t entry) 139{ 140 ClearAOTFlagsWhenInit(); 141 // Do not clear deopt type, which records a method has deoptimized before 142 SetCodeEntryOrLiteral(entry); 143} 144 145void Method::ClearAOTFlagsWhenInit() 146{ 147 SetAotCodeBit(false); 148 SetIsFastCall(false); 149} 150 151void Method::InitInterpreterStatusForCompiledMethod(const JSThread *thread) 152{ 153 if (!IsAotWithCallField()) { 154 return; 155 } 156 bool isFastCall = IsFastCall(); 157 uintptr_t entry = 158 isFastCall ? thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_FastCallToAsmInterBridge) 159 : thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_AOTCallToAsmInterBridge); 160 SetCodeEntryOrLiteral(entry); 161 ClearAOTFlagsWhenInit(); 162 SetDeoptType(kungfu::DeoptType::INIT_AOT_FAILED); 163} 164} // namespace panda::ecmascript 165