• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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/jspandafile/method_literal.h"
17 
18 #include "ecmascript/interpreter/interpreter-inl.h"
19 #include "ecmascript/jspandafile/js_pandafile.h"
20 
21 #include "libpandafile/class_data_accessor.h"
22 #include "libpandafile/code_data_accessor-inl.h"
23 #include "libpandafile/method_data_accessor-inl.h"
24 
25 namespace panda::ecmascript {
MethodLiteral(EntityId methodId)26 MethodLiteral::MethodLiteral(EntityId methodId)
27 {
28     ASSERT(methodId.IsValid());
29     SetMethodId(methodId);
30 }
31 
Initialize(const JSPandaFile * jsPandaFile)32 void MethodLiteral::Initialize(const JSPandaFile *jsPandaFile)
33 {
34     const panda_file::File *pf = jsPandaFile->GetPandaFile();
35     EntityId methodId = GetMethodId();
36     panda_file::MethodDataAccessor mda(*pf, methodId);
37     auto codeId = mda.GetCodeId().value();
38     ASSERT(codeId.IsValid());
39 
40     panda_file::CodeDataAccessor cda(*pf, codeId);
41     nativePointerOrBytecodeArray_ = cda.GetInstructions();
42     uint32_t codeSize = cda.GetCodeSize();
43     SetHotnessCounter(EcmaInterpreter::GetHotnessCounter(codeSize));
44 
45     uint32_t callType = UINT32_MAX;  // UINT32_MAX means not found
46     uint32_t slotSize = 0;
47     mda.EnumerateAnnotations([&](EntityId annotationId) {
48         panda_file::AnnotationDataAccessor ada(*pf, annotationId);
49         auto *annotationName = reinterpret_cast<const char *>(pf->GetStringData(ada.GetClassId()).data);
50         if (::strcmp("L_ESCallTypeAnnotation;", annotationName) == 0) {
51             uint32_t elemCount = ada.GetCount();
52             for (uint32_t i = 0; i < elemCount; i++) {
53                 panda_file::AnnotationDataAccessor::Elem adae = ada.GetElement(i);
54                 auto *elemName = reinterpret_cast<const char *>(pf->GetStringData(adae.GetNameId()).data);
55                 if (::strcmp("callType", elemName) == 0) {
56                     callType = adae.GetScalarValue().GetValue();
57                 }
58             }
59         } else if (::strcmp("L_ESSlotNumberAnnotation;", annotationName) == 0) {
60             uint32_t elemCount = ada.GetCount();
61             for (uint32_t i = 0; i < elemCount; i++) {
62                 panda_file::AnnotationDataAccessor::Elem adae = ada.GetElement(i);
63                 auto *elemName = reinterpret_cast<const char *>(pf->GetStringData(adae.GetNameId()).data);
64                 if (::strcmp("SlotNumber", elemName) == 0) {
65                     slotSize = adae.GetScalarValue().GetValue();
66                 }
67             }
68         }
69     });
70 
71     uint32_t numVregs = cda.GetNumVregs();
72     uint32_t numArgs = cda.GetNumArgs();
73     // Needed info for call can be got by loading callField only once.
74     // Native bit will be set in NewMethodForNativeFunction();
75     callField_ = (callType & CALL_TYPE_MASK) |
76                  NumVregsBits::Encode(numVregs) |
77                  NumArgsBits::Encode(numArgs - HaveFuncBit::Decode(callType)  // exclude func
78                                              - HaveNewTargetBit::Decode(callType)  // exclude new target
79                                              - HaveThisBit::Decode(callType));  // exclude this
80     SetSlotSize(slotSize);
81 }
82 
83 // It's not allowed '#' token appear in ECMA function(method) name, which discriminates same names in panda methods.
ParseFunctionName(const JSPandaFile * jsPandaFile,EntityId methodId)84 std::string MethodLiteral::ParseFunctionName(const JSPandaFile *jsPandaFile, EntityId methodId)
85 {
86     if (jsPandaFile == nullptr) {
87         return std::string();
88     }
89 
90     std::string methodName(GetMethodName(jsPandaFile, methodId));
91     if (LIKELY(methodName[0] != '#')) {
92         return methodName;
93     }
94 
95     size_t index = methodName.find_last_of('#');
96     return methodName.substr(index + 1);
97 }
98 
GetMethodName(const JSPandaFile * jsPandaFile,EntityId methodId)99 const char *MethodLiteral::GetMethodName(const JSPandaFile *jsPandaFile, EntityId methodId)
100 {
101     if (jsPandaFile == nullptr) {
102         return "";
103     }
104 
105     const panda_file::File *pf = jsPandaFile->GetPandaFile();
106     panda_file::MethodDataAccessor mda(*pf, methodId);
107     auto sd = jsPandaFile->GetStringData(mda.GetNameId());
108     return utf::Mutf8AsCString(sd.data);
109 }
110 
GetRecordName(const JSPandaFile * jsPandaFile,EntityId methodId)111 CString MethodLiteral::GetRecordName(const JSPandaFile *jsPandaFile, EntityId methodId)
112 {
113     if (jsPandaFile == nullptr) {
114         return "";
115     }
116 
117     const panda_file::File *pf = jsPandaFile->GetPandaFile();
118     panda_file::MethodDataAccessor mda(*pf, methodId);
119     panda_file::ClassDataAccessor cda(*pf, mda.GetClassId());
120     CString desc = utf::Mutf8AsCString(cda.GetDescriptor());
121     return JSPandaFile::ParseEntryPoint(desc);
122 }
123 
GetRecordNameWithSymbol(const JSPandaFile * jsPandaFile,EntityId methodId)124 const char *MethodLiteral::GetRecordNameWithSymbol(const JSPandaFile *jsPandaFile, EntityId methodId)
125 {
126     if (jsPandaFile == nullptr) {
127         return "";
128     }
129 
130     const panda_file::File *pf = jsPandaFile->GetPandaFile();
131     panda_file::MethodDataAccessor mda(*pf, methodId);
132     panda_file::ClassDataAccessor cda(*pf, mda.GetClassId());
133     return utf::Mutf8AsCString(cda.GetDescriptor());
134 }
135 
GetCodeSize(const JSPandaFile * jsPandaFile,EntityId methodId)136 uint32_t MethodLiteral::GetCodeSize(const JSPandaFile *jsPandaFile, EntityId methodId)
137 {
138     if (jsPandaFile == nullptr) {
139         return 0;
140     }
141 
142     const panda_file::File *pandaFile = jsPandaFile->GetPandaFile();
143     panda_file::MethodDataAccessor mda(*pandaFile, methodId);
144     auto codeId = mda.GetCodeId().value();
145     if (!codeId.IsValid()) {
146         return 0;
147     }
148 
149     panda_file::CodeDataAccessor cda(*pandaFile, codeId);
150     return cda.GetCodeSize();
151 }
152 } // namespace panda::ecmascript
153