• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #ifndef ECMASCRIPT_JS_METHOD_H
17 #define ECMASCRIPT_JS_METHOD_H
18 
19 #include "ecmascript/mem/c_string.h"
20 #include "include/method.h"
21 #include "libpandafile/file.h"
22 
23 static constexpr uint32_t CALL_TYPE_MASK = 0xF;  // 0xF: the last 4 bits are used as callType
24 static constexpr size_t STORAGE_32_NUM = 4;
25 static constexpr size_t STORAGE_PTR_NUM = 3;
26 
27 #define JS_METHOD_OFFSET_LIST(V)                                                                    \
28     V(STORPTR, STOR32, STORAGE_32_NUM * sizeof(uint32_t), STORAGE_32_NUM * sizeof(uint32_t))        \
29     V(PANDAFILE, STORPTR, STORAGE_PTR_NUM * sizeof(uint32_t), STORAGE_PTR_NUM * sizeof(uint64_t))   \
30     V(FILEID, PANDAFILE, sizeof(uint32_t), sizeof(uint64_t))                                        \
31     V(CODEID, FILEID, sizeof(uint32_t), sizeof(uint32_t))                                           \
32     V(SHORTY, CODEID, sizeof(uint32_t), sizeof(uint32_t))                                           \
33     V(PROFILINGDATA, SHORTY, sizeof(uint32_t), sizeof(uint64_t))                                    \
34     V(BYTECODEARRAY, PROFILINGDATA, sizeof(uint32_t), sizeof(uint64_t))                             \
35     V(BYTECODEARRAYSIZE, BYTECODEARRAY, sizeof(uint32_t), sizeof(uint64_t))                         \
36     V(SLOTSIZE, BYTECODEARRAYSIZE, sizeof(uint32_t), sizeof(uint32_t))                              \
37     V(CALLFIELD, SLOTSIZE, sizeof(uint8_t), sizeof(uint8_t))                                        \
38 
39 static constexpr uint32_t JS_METHOD_STOR32_OFFSET_32 = 0U;
40 static constexpr uint32_t JS_METHOD_STOR32_OFFSET_64 = 0U;
41 #define JS_METHOD_OFFSET_MACRO(name, lastName, lastSize32, lastSize64)                                          \
42     static constexpr uint32_t JS_METHOD_##name##_OFFSET_32 = JS_METHOD_##lastName##_OFFSET_32 + (lastSize32);   \
43     static constexpr uint32_t JS_METHOD_##name##_OFFSET_64 = JS_METHOD_##lastName##_OFFSET_64 + (lastSize64);
JS_METHOD_OFFSET_LIST(JS_METHOD_OFFSET_MACRO)44 JS_METHOD_OFFSET_LIST(JS_METHOD_OFFSET_MACRO)
45 #undef JS_METHOD_OFFSET_MACRO
46 
47 namespace panda::ecmascript {
48 class JSPandaFile;
49 
50 class JSMethod : public Method {
51 public:
52     static constexpr uint8_t MAX_SLOT_SIZE = 0xFF;
53     static constexpr uint32_t HOTNESS_COUNTER_OFFSET = 3 * sizeof(uint32_t);  // 3: the 3th field of method
54 
55     static JSMethod *Cast(Method *method)
56     {
57         return static_cast<JSMethod *>(method);
58     }
59 
60     JSMethod(const JSPandaFile *jsPandaFile,  panda_file::File::EntityId fileId,
61              panda_file::File::EntityId codeId, uint32_t accessFlags, uint32_t numArgs, const uint16_t *shorty);
62     JSMethod() = delete;
63     ~JSMethod() = default;
64     JSMethod(const JSMethod &) = delete;
65     JSMethod(JSMethod &&) = delete;
66     JSMethod &operator=(const JSMethod &) = delete;
67     JSMethod &operator=(JSMethod &&) = delete;
68 
69     static constexpr uint32_t GetBytecodeArrayOffset()
70     {
71         return MEMBER_OFFSET(JSMethod, bytecodeArray_);
72     }
73 
74     static constexpr uint32_t GetBytecodeArrayOffset(bool isArm32)
75     {
76         if (isArm32) {
77             return JS_METHOD_BYTECODEARRAY_OFFSET_32;
78         }
79         return JS_METHOD_BYTECODEARRAY_OFFSET_64;
80     }
81 
82     const uint8_t *GetBytecodeArray() const
83     {
84         return bytecodeArray_;
85     }
86 
87     uint32_t GetBytecodeArraySize() const
88     {
89         return bytecodeArraySize_;
90     }
91 
92     void SetBytecodeArray(const uint8_t *bc)
93     {
94         bytecodeArray_ = bc;
95     }
96 
97     uint8_t GetSlotSize() const
98     {
99         return slotSize_;
100     }
101 
102     void UpdateSlotSize (uint8_t size)
103     {
104         uint16_t end = GetSlotSize() + size;
105         if (end >= MAX_SLOT_SIZE) {
106             slotSize_ = MAX_SLOT_SIZE;
107             return;
108         }
109         slotSize_ = static_cast<uint8_t>(end);
110     }
111 
112     static constexpr size_t VREGS_ARGS_NUM_BITS = 28; // 28: maximum 268,435,455
113     using HaveThisBit = BitField<bool, 0, 1>;  // offset 0
114     using HaveNewTargetBit = HaveThisBit::NextFlag;  // offset 1
115     using HaveExtraBit = HaveNewTargetBit::NextFlag;  // offset 2
116     using HaveFuncBit = HaveExtraBit::NextFlag;  // offset 3
117     using NumVregsBits = HaveFuncBit::NextField<uint32_t, VREGS_ARGS_NUM_BITS>;  // offset 4-31
118     using NumArgsBits = NumVregsBits::NextField<uint32_t, VREGS_ARGS_NUM_BITS>;  // offset 32-59
119     using IsNativeBit = NumArgsBits::NextFlag;  // offset 60
120 
121     uint64_t GetCallField() const
122     {
123         return callField_;
124     }
125 
126     void SetNativeBit(bool isNative)
127     {
128         callField_ = IsNativeBit::Update(callField_, isNative);
129     }
130 
131     std::string ParseFunctionName() const;
132     void InitializeCallField();
133 
134     bool HaveThisWithCallField() const
135     {
136         return HaveThisBit::Decode(callField_);
137     }
138 
139     bool HaveNewTargetWithCallField() const
140     {
141         return HaveNewTargetBit::Decode(callField_);
142     }
143 
144     bool HaveExtraWithCallField() const
145     {
146         return HaveExtraBit::Decode(callField_);
147     }
148 
149     bool HaveFuncWithCallField() const
150     {
151         return HaveFuncBit::Decode(callField_);
152     }
153 
154     bool IsNativeWithCallField() const
155     {
156         return IsNativeBit::Decode(callField_);
157     }
158 
159     bool OnlyHaveThisWithCallField() const
160     {
161         return (callField_ & CALL_TYPE_MASK) == 1;  // 1: the first bit of callFiled is HaveThisBit
162     }
163 
164     uint32_t GetNumVregsWithCallField() const
165     {
166         return NumVregsBits::Decode(callField_);
167     }
168 
169     uint32_t GetNumArgsWithCallField() const
170     {
171         return NumArgsBits::Decode(callField_);
172     }
173     panda_file::File::EntityId GetMethodId() const
174     {
175         return GetFileId();
176     }
177     const JSPandaFile *GetJSPandaFile() const
178     {
179         return jsPandaFile_;
180     }
181 
182 private:
183     const uint8_t *bytecodeArray_ {nullptr};
184     uint32_t bytecodeArraySize_ {0};
185     uint8_t slotSize_ {0};
186     uint64_t callField_ {0};
187     const JSPandaFile *jsPandaFile_ {nullptr};
188 };
189 }  // namespace panda::ecmascript
190 
191 #endif  // ECMASCRIPT_JS_METHOD_H
192