xref: /aosp_15_r20/art/libdexfile/dex/compact_dex_file.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_LIBDEXFILE_DEX_COMPACT_DEX_FILE_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_LIBDEXFILE_DEX_COMPACT_DEX_FILE_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <memory>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include "base/casts.h"
23*795d594fSAndroid Build Coastguard Worker #include "dex/compact_offset_table.h"
24*795d594fSAndroid Build Coastguard Worker #include "dex_file.h"
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker namespace art {
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker // CompactDex is a currently ART internal dex file format that aims to reduce storage/RAM usage.
29*795d594fSAndroid Build Coastguard Worker class CompactDexFile : public DexFile {
30*795d594fSAndroid Build Coastguard Worker  public:
31*795d594fSAndroid Build Coastguard Worker   static constexpr uint8_t kDexMagic[kDexMagicSize] = { 'c', 'd', 'e', 'x' };
32*795d594fSAndroid Build Coastguard Worker   // Last change: remove code item deduping.
33*795d594fSAndroid Build Coastguard Worker   static constexpr uint8_t kDexMagicVersion[] = {'0', '0', '1', '\0'};
34*795d594fSAndroid Build Coastguard Worker 
35*795d594fSAndroid Build Coastguard Worker   enum class FeatureFlags : uint32_t {
36*795d594fSAndroid Build Coastguard Worker     kDefaultMethods = 0x1,
37*795d594fSAndroid Build Coastguard Worker   };
38*795d594fSAndroid Build Coastguard Worker 
39*795d594fSAndroid Build Coastguard Worker   class Header : public DexFile::Header {
40*795d594fSAndroid Build Coastguard Worker    public:
At(const void * at)41*795d594fSAndroid Build Coastguard Worker     static const Header* At(const void* at) {
42*795d594fSAndroid Build Coastguard Worker       return reinterpret_cast<const Header*>(at);
43*795d594fSAndroid Build Coastguard Worker     }
44*795d594fSAndroid Build Coastguard Worker 
GetFeatureFlags()45*795d594fSAndroid Build Coastguard Worker     uint32_t GetFeatureFlags() const {
46*795d594fSAndroid Build Coastguard Worker       return feature_flags_;
47*795d594fSAndroid Build Coastguard Worker     }
48*795d594fSAndroid Build Coastguard Worker 
GetDataOffset()49*795d594fSAndroid Build Coastguard Worker     uint32_t GetDataOffset() const {
50*795d594fSAndroid Build Coastguard Worker       return data_off_;
51*795d594fSAndroid Build Coastguard Worker     }
52*795d594fSAndroid Build Coastguard Worker 
GetDataSize()53*795d594fSAndroid Build Coastguard Worker     uint32_t GetDataSize() const {
54*795d594fSAndroid Build Coastguard Worker       return data_size_;
55*795d594fSAndroid Build Coastguard Worker     }
56*795d594fSAndroid Build Coastguard Worker 
57*795d594fSAndroid Build Coastguard Worker     // Range of the shared data section owned by the dex file. Owned in this context refers to data
58*795d594fSAndroid Build Coastguard Worker     // for this DEX that was not deduplicated to another DEX.
OwnedDataBegin()59*795d594fSAndroid Build Coastguard Worker     uint32_t OwnedDataBegin() const {
60*795d594fSAndroid Build Coastguard Worker       return owned_data_begin_;
61*795d594fSAndroid Build Coastguard Worker     }
62*795d594fSAndroid Build Coastguard Worker 
OwnedDataEnd()63*795d594fSAndroid Build Coastguard Worker     uint32_t OwnedDataEnd() const {
64*795d594fSAndroid Build Coastguard Worker       return owned_data_end_;
65*795d594fSAndroid Build Coastguard Worker     }
66*795d594fSAndroid Build Coastguard Worker 
67*795d594fSAndroid Build Coastguard Worker    private:
68*795d594fSAndroid Build Coastguard Worker     uint32_t feature_flags_ = 0u;
69*795d594fSAndroid Build Coastguard Worker 
70*795d594fSAndroid Build Coastguard Worker     // Position in the compact dex file for the debug info table data starts.
71*795d594fSAndroid Build Coastguard Worker     uint32_t debug_info_offsets_pos_ = 0u;
72*795d594fSAndroid Build Coastguard Worker 
73*795d594fSAndroid Build Coastguard Worker     // Offset into the debug info table data where the lookup table is.
74*795d594fSAndroid Build Coastguard Worker     uint32_t debug_info_offsets_table_offset_ = 0u;
75*795d594fSAndroid Build Coastguard Worker 
76*795d594fSAndroid Build Coastguard Worker     // Base offset of where debug info starts in the dex file.
77*795d594fSAndroid Build Coastguard Worker     uint32_t debug_info_base_ = 0u;
78*795d594fSAndroid Build Coastguard Worker 
79*795d594fSAndroid Build Coastguard Worker     // Range of the shared data section owned by the dex file.
80*795d594fSAndroid Build Coastguard Worker     uint32_t owned_data_begin_ = 0u;
81*795d594fSAndroid Build Coastguard Worker     uint32_t owned_data_end_ = 0u;
82*795d594fSAndroid Build Coastguard Worker 
83*795d594fSAndroid Build Coastguard Worker     friend class CompactDexFile;
84*795d594fSAndroid Build Coastguard Worker     friend class CompactDexWriter;
85*795d594fSAndroid Build Coastguard Worker   };
86*795d594fSAndroid Build Coastguard Worker 
87*795d594fSAndroid Build Coastguard Worker   // Like the standard code item except without a debug info offset. Each code item may have a
88*795d594fSAndroid Build Coastguard Worker   // preheader to encode large methods. In 99% of cases, the preheader is not used. This enables
89*795d594fSAndroid Build Coastguard Worker   // smaller size with a good fast path case in the accessors.
90*795d594fSAndroid Build Coastguard Worker   struct CodeItem : public dex::CodeItem {
91*795d594fSAndroid Build Coastguard Worker     static constexpr size_t kAlignment = sizeof(uint16_t);
92*795d594fSAndroid Build Coastguard Worker     // Max preheader size in uint16_ts.
93*795d594fSAndroid Build Coastguard Worker     static constexpr size_t kMaxPreHeaderSize = 6;
94*795d594fSAndroid Build Coastguard Worker 
FieldsOffsetCodeItem95*795d594fSAndroid Build Coastguard Worker     static constexpr size_t FieldsOffset() {
96*795d594fSAndroid Build Coastguard Worker       return OFFSETOF_MEMBER(CodeItem, fields_);
97*795d594fSAndroid Build Coastguard Worker     }
98*795d594fSAndroid Build Coastguard Worker 
InsnsCountAndFlagsOffsetCodeItem99*795d594fSAndroid Build Coastguard Worker     static constexpr size_t InsnsCountAndFlagsOffset() {
100*795d594fSAndroid Build Coastguard Worker       return OFFSETOF_MEMBER(CodeItem, insns_count_and_flags_);
101*795d594fSAndroid Build Coastguard Worker     }
102*795d594fSAndroid Build Coastguard Worker 
InsnsOffsetCodeItem103*795d594fSAndroid Build Coastguard Worker     static constexpr size_t InsnsOffset() {
104*795d594fSAndroid Build Coastguard Worker       return OFFSETOF_MEMBER(CodeItem, insns_);
105*795d594fSAndroid Build Coastguard Worker     }
106*795d594fSAndroid Build Coastguard Worker 
107*795d594fSAndroid Build Coastguard Worker     static constexpr size_t kRegistersSizeShift = 12;
108*795d594fSAndroid Build Coastguard Worker     static constexpr size_t kInsSizeShift = 8;
109*795d594fSAndroid Build Coastguard Worker     static constexpr size_t kOutsSizeShift = 4;
110*795d594fSAndroid Build Coastguard Worker     static constexpr size_t kTriesSizeSizeShift = 0;
111*795d594fSAndroid Build Coastguard Worker     static constexpr uint16_t kBitPreHeaderRegistersSize = 0;
112*795d594fSAndroid Build Coastguard Worker     static constexpr uint16_t kBitPreHeaderInsSize = 1;
113*795d594fSAndroid Build Coastguard Worker     static constexpr uint16_t kBitPreHeaderOutsSize = 2;
114*795d594fSAndroid Build Coastguard Worker     static constexpr uint16_t kBitPreHeaderTriesSize = 3;
115*795d594fSAndroid Build Coastguard Worker     static constexpr uint16_t kBitPreHeaderInsnsSize = 4;
116*795d594fSAndroid Build Coastguard Worker     static constexpr uint16_t kFlagPreHeaderRegistersSize = 0x1 << kBitPreHeaderRegistersSize;
117*795d594fSAndroid Build Coastguard Worker     static constexpr uint16_t kFlagPreHeaderInsSize = 0x1 << kBitPreHeaderInsSize;
118*795d594fSAndroid Build Coastguard Worker     static constexpr uint16_t kFlagPreHeaderOutsSize = 0x1 << kBitPreHeaderOutsSize;
119*795d594fSAndroid Build Coastguard Worker     static constexpr uint16_t kFlagPreHeaderTriesSize = 0x1 << kBitPreHeaderTriesSize;
120*795d594fSAndroid Build Coastguard Worker     static constexpr uint16_t kFlagPreHeaderInsnsSize = 0x1 << kBitPreHeaderInsnsSize;
121*795d594fSAndroid Build Coastguard Worker     static constexpr size_t kInsnsSizeShift = 5;
122*795d594fSAndroid Build Coastguard Worker     static constexpr size_t kInsnsSizeBits = sizeof(uint16_t) * kBitsPerByte -  kInsnsSizeShift;
123*795d594fSAndroid Build Coastguard Worker 
124*795d594fSAndroid Build Coastguard Worker    private:
125*795d594fSAndroid Build Coastguard Worker     CodeItem() = default;
126*795d594fSAndroid Build Coastguard Worker 
127*795d594fSAndroid Build Coastguard Worker     // Combined preheader flags for fast testing if we need to go slow path.
128*795d594fSAndroid Build Coastguard Worker     static constexpr uint16_t kFlagPreHeaderCombined =
129*795d594fSAndroid Build Coastguard Worker         kFlagPreHeaderRegistersSize |
130*795d594fSAndroid Build Coastguard Worker         kFlagPreHeaderInsSize |
131*795d594fSAndroid Build Coastguard Worker         kFlagPreHeaderOutsSize |
132*795d594fSAndroid Build Coastguard Worker         kFlagPreHeaderTriesSize |
133*795d594fSAndroid Build Coastguard Worker         kFlagPreHeaderInsnsSize;
134*795d594fSAndroid Build Coastguard Worker 
135*795d594fSAndroid Build Coastguard Worker     // Create a code item and associated preheader if required based on field values.
136*795d594fSAndroid Build Coastguard Worker     // Returns the start of the preheader. The preheader buffer must be at least as large as
137*795d594fSAndroid Build Coastguard Worker     // kMaxPreHeaderSize;
CreateCodeItem138*795d594fSAndroid Build Coastguard Worker     uint16_t* Create(uint16_t registers_size,
139*795d594fSAndroid Build Coastguard Worker                      uint16_t ins_size,
140*795d594fSAndroid Build Coastguard Worker                      uint16_t outs_size,
141*795d594fSAndroid Build Coastguard Worker                      uint16_t tries_size,
142*795d594fSAndroid Build Coastguard Worker                      uint32_t insns_size_in_code_units,
143*795d594fSAndroid Build Coastguard Worker                      uint16_t* out_preheader) {
144*795d594fSAndroid Build Coastguard Worker       // Dex verification ensures that registers size > ins_size, so we can subtract the registers
145*795d594fSAndroid Build Coastguard Worker       // size accordingly to reduce how often we need to use the preheader.
146*795d594fSAndroid Build Coastguard Worker       DCHECK_GE(registers_size, ins_size);
147*795d594fSAndroid Build Coastguard Worker       registers_size -= ins_size;
148*795d594fSAndroid Build Coastguard Worker       fields_ = (registers_size & 0xF) << kRegistersSizeShift;
149*795d594fSAndroid Build Coastguard Worker       fields_ |= (ins_size & 0xF) << kInsSizeShift;
150*795d594fSAndroid Build Coastguard Worker       fields_ |= (outs_size & 0xF) << kOutsSizeShift;
151*795d594fSAndroid Build Coastguard Worker       fields_ |= (tries_size & 0xF) << kTriesSizeSizeShift;
152*795d594fSAndroid Build Coastguard Worker       registers_size &= ~0xF;
153*795d594fSAndroid Build Coastguard Worker       ins_size &= ~0xF;
154*795d594fSAndroid Build Coastguard Worker       outs_size &= ~0xF;
155*795d594fSAndroid Build Coastguard Worker       tries_size &= ~0xF;
156*795d594fSAndroid Build Coastguard Worker       insns_count_and_flags_ = 0;
157*795d594fSAndroid Build Coastguard Worker       const size_t masked_count = insns_size_in_code_units & ((1 << kInsnsSizeBits) - 1);
158*795d594fSAndroid Build Coastguard Worker       insns_count_and_flags_ |= masked_count << kInsnsSizeShift;
159*795d594fSAndroid Build Coastguard Worker       insns_size_in_code_units -= masked_count;
160*795d594fSAndroid Build Coastguard Worker 
161*795d594fSAndroid Build Coastguard Worker       // Since the preheader case is rare (1% of code items), use a suboptimally large but fast
162*795d594fSAndroid Build Coastguard Worker       // decoding format.
163*795d594fSAndroid Build Coastguard Worker       if (insns_size_in_code_units != 0) {
164*795d594fSAndroid Build Coastguard Worker         insns_count_and_flags_ |= kFlagPreHeaderInsnsSize;
165*795d594fSAndroid Build Coastguard Worker         --out_preheader;
166*795d594fSAndroid Build Coastguard Worker         *out_preheader = static_cast<uint16_t>(insns_size_in_code_units);
167*795d594fSAndroid Build Coastguard Worker         --out_preheader;
168*795d594fSAndroid Build Coastguard Worker         *out_preheader = static_cast<uint16_t>(insns_size_in_code_units >> 16);
169*795d594fSAndroid Build Coastguard Worker       }
170*795d594fSAndroid Build Coastguard Worker       auto preheader_encode = [&](uint16_t size, uint16_t flag) {
171*795d594fSAndroid Build Coastguard Worker         if (size != 0) {
172*795d594fSAndroid Build Coastguard Worker           insns_count_and_flags_ |= flag;
173*795d594fSAndroid Build Coastguard Worker           --out_preheader;
174*795d594fSAndroid Build Coastguard Worker           *out_preheader = size;
175*795d594fSAndroid Build Coastguard Worker         }
176*795d594fSAndroid Build Coastguard Worker       };
177*795d594fSAndroid Build Coastguard Worker       preheader_encode(registers_size, kFlagPreHeaderRegistersSize);
178*795d594fSAndroid Build Coastguard Worker       preheader_encode(ins_size, kFlagPreHeaderInsSize);
179*795d594fSAndroid Build Coastguard Worker       preheader_encode(outs_size, kFlagPreHeaderOutsSize);
180*795d594fSAndroid Build Coastguard Worker       preheader_encode(tries_size, kFlagPreHeaderTriesSize);
181*795d594fSAndroid Build Coastguard Worker       return out_preheader;
182*795d594fSAndroid Build Coastguard Worker     }
183*795d594fSAndroid Build Coastguard Worker 
HasPreHeaderCodeItem184*795d594fSAndroid Build Coastguard Worker     ALWAYS_INLINE bool HasPreHeader(uint16_t flag) const {
185*795d594fSAndroid Build Coastguard Worker       return (insns_count_and_flags_ & flag) != 0;
186*795d594fSAndroid Build Coastguard Worker     }
187*795d594fSAndroid Build Coastguard Worker 
188*795d594fSAndroid Build Coastguard Worker     // Return true if the code item has any preheaders.
HasAnyPreHeaderCodeItem189*795d594fSAndroid Build Coastguard Worker     ALWAYS_INLINE static bool HasAnyPreHeader(uint16_t insns_count_and_flags) {
190*795d594fSAndroid Build Coastguard Worker       return (insns_count_and_flags & kFlagPreHeaderCombined) != 0;
191*795d594fSAndroid Build Coastguard Worker     }
192*795d594fSAndroid Build Coastguard Worker 
GetPreHeaderCodeItem193*795d594fSAndroid Build Coastguard Worker     ALWAYS_INLINE uint16_t* GetPreHeader() {
194*795d594fSAndroid Build Coastguard Worker       return reinterpret_cast<uint16_t*>(this);
195*795d594fSAndroid Build Coastguard Worker     }
196*795d594fSAndroid Build Coastguard Worker 
GetPreHeaderCodeItem197*795d594fSAndroid Build Coastguard Worker     ALWAYS_INLINE const uint16_t* GetPreHeader() const {
198*795d594fSAndroid Build Coastguard Worker       return reinterpret_cast<const uint16_t*>(this);
199*795d594fSAndroid Build Coastguard Worker     }
200*795d594fSAndroid Build Coastguard Worker 
201*795d594fSAndroid Build Coastguard Worker     // Decode fields and read the preheader if necessary. If kDecodeOnlyInstructionCount is
202*795d594fSAndroid Build Coastguard Worker     // specified then only the instruction count is decoded.
203*795d594fSAndroid Build Coastguard Worker     template <bool kDecodeOnlyInstructionCount>
DecodeFieldsCodeItem204*795d594fSAndroid Build Coastguard Worker     ALWAYS_INLINE void DecodeFields(uint32_t* insns_count,
205*795d594fSAndroid Build Coastguard Worker                                     uint16_t* registers_size,
206*795d594fSAndroid Build Coastguard Worker                                     uint16_t* ins_size,
207*795d594fSAndroid Build Coastguard Worker                                     uint16_t* outs_size,
208*795d594fSAndroid Build Coastguard Worker                                     uint16_t* tries_size) const {
209*795d594fSAndroid Build Coastguard Worker       *insns_count = insns_count_and_flags_ >> kInsnsSizeShift;
210*795d594fSAndroid Build Coastguard Worker       if (!kDecodeOnlyInstructionCount) {
211*795d594fSAndroid Build Coastguard Worker         const uint16_t fields = fields_;
212*795d594fSAndroid Build Coastguard Worker         *registers_size = (fields >> kRegistersSizeShift) & 0xF;
213*795d594fSAndroid Build Coastguard Worker         *ins_size = (fields >> kInsSizeShift) & 0xF;
214*795d594fSAndroid Build Coastguard Worker         *outs_size = (fields >> kOutsSizeShift) & 0xF;
215*795d594fSAndroid Build Coastguard Worker         *tries_size = (fields >> kTriesSizeSizeShift) & 0xF;
216*795d594fSAndroid Build Coastguard Worker       }
217*795d594fSAndroid Build Coastguard Worker       if (UNLIKELY(HasAnyPreHeader(insns_count_and_flags_))) {
218*795d594fSAndroid Build Coastguard Worker         const uint16_t* preheader = GetPreHeader();
219*795d594fSAndroid Build Coastguard Worker         if (HasPreHeader(kFlagPreHeaderInsnsSize)) {
220*795d594fSAndroid Build Coastguard Worker           --preheader;
221*795d594fSAndroid Build Coastguard Worker           *insns_count += static_cast<uint32_t>(*preheader);
222*795d594fSAndroid Build Coastguard Worker           --preheader;
223*795d594fSAndroid Build Coastguard Worker           *insns_count += static_cast<uint32_t>(*preheader) << 16;
224*795d594fSAndroid Build Coastguard Worker         }
225*795d594fSAndroid Build Coastguard Worker         if (!kDecodeOnlyInstructionCount) {
226*795d594fSAndroid Build Coastguard Worker           if (HasPreHeader(kFlagPreHeaderRegistersSize)) {
227*795d594fSAndroid Build Coastguard Worker             --preheader;
228*795d594fSAndroid Build Coastguard Worker             *registers_size += preheader[0];
229*795d594fSAndroid Build Coastguard Worker           }
230*795d594fSAndroid Build Coastguard Worker           if (HasPreHeader(kFlagPreHeaderInsSize)) {
231*795d594fSAndroid Build Coastguard Worker             --preheader;
232*795d594fSAndroid Build Coastguard Worker             *ins_size += preheader[0];
233*795d594fSAndroid Build Coastguard Worker           }
234*795d594fSAndroid Build Coastguard Worker           if (HasPreHeader(kFlagPreHeaderOutsSize)) {
235*795d594fSAndroid Build Coastguard Worker             --preheader;
236*795d594fSAndroid Build Coastguard Worker             *outs_size += preheader[0];
237*795d594fSAndroid Build Coastguard Worker           }
238*795d594fSAndroid Build Coastguard Worker           if (HasPreHeader(kFlagPreHeaderTriesSize)) {
239*795d594fSAndroid Build Coastguard Worker             --preheader;
240*795d594fSAndroid Build Coastguard Worker             *tries_size += preheader[0];
241*795d594fSAndroid Build Coastguard Worker           }
242*795d594fSAndroid Build Coastguard Worker         }
243*795d594fSAndroid Build Coastguard Worker       }
244*795d594fSAndroid Build Coastguard Worker       if (!kDecodeOnlyInstructionCount) {
245*795d594fSAndroid Build Coastguard Worker         *registers_size += *ins_size;
246*795d594fSAndroid Build Coastguard Worker       }
247*795d594fSAndroid Build Coastguard Worker     }
248*795d594fSAndroid Build Coastguard Worker 
249*795d594fSAndroid Build Coastguard Worker     // Packed code item data, 4 bits each: [registers_size, ins_size, outs_size, tries_size]
250*795d594fSAndroid Build Coastguard Worker     uint16_t fields_;
251*795d594fSAndroid Build Coastguard Worker 
252*795d594fSAndroid Build Coastguard Worker     // 5 bits for if either of the fields required preheader extension, 11 bits for the number of
253*795d594fSAndroid Build Coastguard Worker     // instruction code units.
254*795d594fSAndroid Build Coastguard Worker     uint16_t insns_count_and_flags_;
255*795d594fSAndroid Build Coastguard Worker 
256*795d594fSAndroid Build Coastguard Worker     uint16_t insns_[1];                  // actual array of bytecode.
257*795d594fSAndroid Build Coastguard Worker 
258*795d594fSAndroid Build Coastguard Worker     ART_FRIEND_TEST(CodeItemAccessorsTest, TestDexInstructionsAccessor);
259*795d594fSAndroid Build Coastguard Worker     ART_FRIEND_TEST(CompactDexFileTest, CodeItemFields);
260*795d594fSAndroid Build Coastguard Worker     friend class CodeItemDataAccessor;
261*795d594fSAndroid Build Coastguard Worker     friend class CodeItemDebugInfoAccessor;
262*795d594fSAndroid Build Coastguard Worker     friend class CodeItemInstructionAccessor;
263*795d594fSAndroid Build Coastguard Worker     friend class CompactDexFile;
264*795d594fSAndroid Build Coastguard Worker     friend class CompactDexWriter;
265*795d594fSAndroid Build Coastguard Worker     DISALLOW_COPY_AND_ASSIGN(CodeItem);
266*795d594fSAndroid Build Coastguard Worker   };
267*795d594fSAndroid Build Coastguard Worker 
268*795d594fSAndroid Build Coastguard Worker   // Write the compact dex specific magic.
269*795d594fSAndroid Build Coastguard Worker   static void WriteMagic(uint8_t* magic);
270*795d594fSAndroid Build Coastguard Worker 
271*795d594fSAndroid Build Coastguard Worker   // Write the current version, note that the input is the address of the magic.
272*795d594fSAndroid Build Coastguard Worker   static void WriteCurrentVersion(uint8_t* magic);
273*795d594fSAndroid Build Coastguard Worker 
274*795d594fSAndroid Build Coastguard Worker   // Returns true if the byte string points to the magic value.
275*795d594fSAndroid Build Coastguard Worker   static bool IsMagicValid(const uint8_t* magic);
IsMagicValid(DexFile::Magic magic)276*795d594fSAndroid Build Coastguard Worker   static bool IsMagicValid(DexFile::Magic magic) { return IsMagicValid(magic.data()); }
277*795d594fSAndroid Build Coastguard Worker   bool IsMagicValid() const override;
278*795d594fSAndroid Build Coastguard Worker 
279*795d594fSAndroid Build Coastguard Worker   // Returns true if the byte string after the magic is the correct value.
280*795d594fSAndroid Build Coastguard Worker   static bool IsVersionValid(const uint8_t* magic);
281*795d594fSAndroid Build Coastguard Worker   bool IsVersionValid() const override;
282*795d594fSAndroid Build Coastguard Worker 
283*795d594fSAndroid Build Coastguard Worker   // TODO This is completely a guess. We really need to do better. b/72402467
284*795d594fSAndroid Build Coastguard Worker   // We ask for 64 megabytes which should be big enough for any realistic dex file.
GetDequickenedSize()285*795d594fSAndroid Build Coastguard Worker   size_t GetDequickenedSize() const override {
286*795d594fSAndroid Build Coastguard Worker     return 64 * MB;
287*795d594fSAndroid Build Coastguard Worker   }
288*795d594fSAndroid Build Coastguard Worker 
GetHeader()289*795d594fSAndroid Build Coastguard Worker   const Header& GetHeader() const {
290*795d594fSAndroid Build Coastguard Worker     return down_cast<const Header&>(DexFile::GetHeader());
291*795d594fSAndroid Build Coastguard Worker   }
292*795d594fSAndroid Build Coastguard Worker 
293*795d594fSAndroid Build Coastguard Worker   bool SupportsDefaultMethods() const override;
294*795d594fSAndroid Build Coastguard Worker 
295*795d594fSAndroid Build Coastguard Worker   uint32_t GetCodeItemSize(const dex::CodeItem& item) const override;
296*795d594fSAndroid Build Coastguard Worker 
GetDebugInfoOffset(uint32_t dex_method_index)297*795d594fSAndroid Build Coastguard Worker   uint32_t GetDebugInfoOffset(uint32_t dex_method_index) const {
298*795d594fSAndroid Build Coastguard Worker     return debug_info_offsets_.GetOffset(dex_method_index);
299*795d594fSAndroid Build Coastguard Worker   }
300*795d594fSAndroid Build Coastguard Worker 
301*795d594fSAndroid Build Coastguard Worker   static uint32_t CalculateChecksum(const uint8_t* base_begin,
302*795d594fSAndroid Build Coastguard Worker                                     size_t base_size,
303*795d594fSAndroid Build Coastguard Worker                                     const uint8_t* data_begin,
304*795d594fSAndroid Build Coastguard Worker                                     size_t data_size);
305*795d594fSAndroid Build Coastguard Worker   uint32_t CalculateChecksum() const override;
306*795d594fSAndroid Build Coastguard Worker 
307*795d594fSAndroid Build Coastguard Worker  private:
308*795d594fSAndroid Build Coastguard Worker   CompactDexFile(const uint8_t* base,
309*795d594fSAndroid Build Coastguard Worker                  const std::string& location,
310*795d594fSAndroid Build Coastguard Worker                  uint32_t location_checksum,
311*795d594fSAndroid Build Coastguard Worker                  const OatDexFile* oat_dex_file,
312*795d594fSAndroid Build Coastguard Worker                  // Shared since several dex files may be stored in the same logical container.
313*795d594fSAndroid Build Coastguard Worker                  std::shared_ptr<DexFileContainer> container);
314*795d594fSAndroid Build Coastguard Worker 
315*795d594fSAndroid Build Coastguard Worker   CompactOffsetTable::Accessor debug_info_offsets_;
316*795d594fSAndroid Build Coastguard Worker 
317*795d594fSAndroid Build Coastguard Worker   friend class DexFile;
318*795d594fSAndroid Build Coastguard Worker   friend class DexFileLoader;
319*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(CompactDexFile);
320*795d594fSAndroid Build Coastguard Worker };
321*795d594fSAndroid Build Coastguard Worker 
322*795d594fSAndroid Build Coastguard Worker }  // namespace art
323*795d594fSAndroid Build Coastguard Worker 
324*795d594fSAndroid Build Coastguard Worker #endif  // ART_LIBDEXFILE_DEX_COMPACT_DEX_FILE_H_
325