blob: ce153682db80d95f9834fdb3ad4dbde4d66148d3 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Brian Carlstrome24fa612011-09-29 00:53:55 -070016
17#include "oat_writer.h"
18
Elliott Hughesa0e18062012-04-13 15:59:59 -070019#include <zlib.h>
20
Brian Carlstrome24fa612011-09-29 00:53:55 -070021#include "class_linker.h"
22#include "class_loader.h"
23#include "file.h"
24#include "os.h"
Elliott Hughesa0e18062012-04-13 15:59:59 -070025#include "safe_map.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070026#include "scoped_thread_state_change.h"
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070027#include "space.h"
Brian Carlstrome24fa612011-09-29 00:53:55 -070028#include "stl_util.h"
29
30namespace art {
31
Elliott Hughes234da572011-11-03 22:13:06 -070032bool OatWriter::Create(File* file,
Ian Rogers00f7d0e2012-07-19 15:28:27 -070033 jobject class_loader,
jeffhao10037c82012-01-23 15:06:23 -080034 const std::vector<const DexFile*>& dex_files,
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070035 uint32_t image_file_location_checksum,
36 const std::string& image_file_location,
Brian Carlstrom3320cf42011-10-04 14:58:28 -070037 const Compiler& compiler) {
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070038 OatWriter oat_writer(dex_files,
39 image_file_location_checksum,
40 image_file_location,
41 class_loader,
42 compiler);
Elliott Hughes234da572011-11-03 22:13:06 -070043 return oat_writer.Write(file);
Brian Carlstrome24fa612011-09-29 00:53:55 -070044}
45
Brian Carlstrom3320cf42011-10-04 14:58:28 -070046OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files,
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070047 uint32_t image_file_location_checksum,
48 const std::string& image_file_location,
Ian Rogers00f7d0e2012-07-19 15:28:27 -070049 jobject class_loader,
Brian Carlstrom3320cf42011-10-04 14:58:28 -070050 const Compiler& compiler) {
51 compiler_ = &compiler;
Brian Carlstrome24fa612011-09-29 00:53:55 -070052 class_loader_ = class_loader;
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070053 image_file_location_checksum_ = image_file_location_checksum;
54 image_file_location_ = image_file_location;
Brian Carlstrome24fa612011-09-29 00:53:55 -070055 dex_files_ = &dex_files;
Ian Rogers0571d352011-11-03 19:51:38 -070056 oat_header_ = NULL;
57 executable_offset_padding_length_ = 0;
Brian Carlstrome24fa612011-09-29 00:53:55 -070058
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070059 size_t offset = InitOatHeader();
Brian Carlstrome24fa612011-09-29 00:53:55 -070060 offset = InitOatDexFiles(offset);
Brian Carlstrom89521892011-12-07 22:05:07 -080061 offset = InitDexFiles(offset);
Brian Carlstrom389efb02012-01-11 12:06:26 -080062 offset = InitOatClasses(offset);
Brian Carlstrome24fa612011-09-29 00:53:55 -070063 offset = InitOatCode(offset);
64 offset = InitOatCodeDexFiles(offset);
65
66 CHECK_EQ(dex_files_->size(), oat_dex_files_.size());
Brian Carlstrome24fa612011-09-29 00:53:55 -070067}
68
Ian Rogers0571d352011-11-03 19:51:38 -070069OatWriter::~OatWriter() {
70 delete oat_header_;
71 STLDeleteElements(&oat_dex_files_);
Brian Carlstrom389efb02012-01-11 12:06:26 -080072 STLDeleteElements(&oat_classes_);
Ian Rogers0571d352011-11-03 19:51:38 -070073}
74
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070075size_t OatWriter::InitOatHeader() {
Brian Carlstrome24fa612011-09-29 00:53:55 -070076 // create the OatHeader
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070077 oat_header_ = new OatHeader(compiler_->GetInstructionSet(),
78 dex_files_,
79 image_file_location_checksum_,
80 image_file_location_);
Brian Carlstrome24fa612011-09-29 00:53:55 -070081 size_t offset = sizeof(*oat_header_);
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070082 offset += image_file_location_.size();
Brian Carlstrome24fa612011-09-29 00:53:55 -070083 return offset;
84}
85
86size_t OatWriter::InitOatDexFiles(size_t offset) {
87 // create the OatDexFiles
88 for (size_t i = 0; i != dex_files_->size(); ++i) {
89 const DexFile* dex_file = (*dex_files_)[i];
90 CHECK(dex_file != NULL);
91 OatDexFile* oat_dex_file = new OatDexFile(*dex_file);
92 oat_dex_files_.push_back(oat_dex_file);
93 offset += oat_dex_file->SizeOf();
94 }
95 return offset;
96}
97
Brian Carlstrom89521892011-12-07 22:05:07 -080098size_t OatWriter::InitDexFiles(size_t offset) {
99 // calculate the offsets within OatDexFiles to the DexFiles
100 for (size_t i = 0; i != dex_files_->size(); ++i) {
101 // dex files are required to be 4 byte aligned
102 offset = RoundUp(offset, 4);
103
104 // set offset in OatDexFile to DexFile
105 oat_dex_files_[i]->dex_file_offset_ = offset;
106
107 const DexFile* dex_file = (*dex_files_)[i];
108 offset += dex_file->GetHeader().file_size_;
109 }
110 return offset;
111}
112
Brian Carlstrom389efb02012-01-11 12:06:26 -0800113size_t OatWriter::InitOatClasses(size_t offset) {
114 // create the OatClasses
115 // calculate the offsets within OatDexFiles to OatClasses
Brian Carlstrome24fa612011-09-29 00:53:55 -0700116 for (size_t i = 0; i != dex_files_->size(); ++i) {
117 const DexFile* dex_file = (*dex_files_)[i];
118 for (size_t class_def_index = 0;
119 class_def_index < dex_file->NumClassDefs();
Ian Rogersc20a83e2012-01-18 18:15:32 -0800120 class_def_index++) {
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800121 oat_dex_files_[i]->methods_offsets_[class_def_index] = offset;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700122 const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
123 const byte* class_data = dex_file->GetClassData(class_def);
Ian Rogers0571d352011-11-03 19:51:38 -0700124 uint32_t num_methods = 0;
125 if (class_data != NULL) { // ie not an empty class, such as a marker interface
126 ClassDataItemIterator it(*dex_file, class_data);
127 size_t num_direct_methods = it.NumDirectMethods();
128 size_t num_virtual_methods = it.NumVirtualMethods();
129 num_methods = num_direct_methods + num_virtual_methods;
130 }
Brian Carlstrom0755ec52012-01-11 15:19:46 -0800131
132 CompiledClass* compiled_class =
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800133 compiler_->GetCompiledClass(Compiler::MethodReference(dex_file, class_def_index));
Brian Carlstrom0755ec52012-01-11 15:19:46 -0800134 Class::Status status =
135 (compiled_class != NULL) ? compiled_class->GetStatus() : Class::kStatusNotReady;
136
137 OatClass* oat_class = new OatClass(status, num_methods);
Brian Carlstrom389efb02012-01-11 12:06:26 -0800138 oat_classes_.push_back(oat_class);
139 offset += oat_class->SizeOf();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700140 }
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800141 oat_dex_files_[i]->UpdateChecksum(*oat_header_);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700142 }
143 return offset;
144}
145
146size_t OatWriter::InitOatCode(size_t offset) {
147 // calculate the offsets within OatHeader to executable code
148 size_t old_offset = offset;
149 // required to be on a new page boundary
150 offset = RoundUp(offset, kPageSize);
151 oat_header_->SetExecutableOffset(offset);
152 executable_offset_padding_length_ = offset - old_offset;
153 return offset;
154}
155
156size_t OatWriter::InitOatCodeDexFiles(size_t offset) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700157 size_t oat_class_index = 0;
158 for (size_t i = 0; i != dex_files_->size(); ++i) {
159 const DexFile* dex_file = (*dex_files_)[i];
160 CHECK(dex_file != NULL);
161 offset = InitOatCodeDexFile(offset, oat_class_index, *dex_file);
162 }
163 return offset;
164}
165
166size_t OatWriter::InitOatCodeDexFile(size_t offset,
167 size_t& oat_class_index,
168 const DexFile& dex_file) {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800169 for (size_t class_def_index = 0;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700170 class_def_index < dex_file.NumClassDefs();
171 class_def_index++, oat_class_index++) {
172 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
Ian Rogersc20a83e2012-01-18 18:15:32 -0800173 offset = InitOatCodeClassDef(offset, oat_class_index, class_def_index, dex_file, class_def);
Brian Carlstrom389efb02012-01-11 12:06:26 -0800174 oat_classes_[oat_class_index]->UpdateChecksum(*oat_header_);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700175 }
176 return offset;
177}
178
179size_t OatWriter::InitOatCodeClassDef(size_t offset,
Ian Rogersc20a83e2012-01-18 18:15:32 -0800180 size_t oat_class_index, size_t class_def_index,
Brian Carlstrome24fa612011-09-29 00:53:55 -0700181 const DexFile& dex_file,
182 const DexFile::ClassDef& class_def) {
183 const byte* class_data = dex_file.GetClassData(class_def);
Ian Rogers0571d352011-11-03 19:51:38 -0700184 if (class_data == NULL) {
185 // empty class, such as a marker interface
Ian Rogers387b6992011-10-31 17:52:37 -0700186 return offset;
187 }
Ian Rogers0571d352011-11-03 19:51:38 -0700188 ClassDataItemIterator it(dex_file, class_data);
Brian Carlstrom389efb02012-01-11 12:06:26 -0800189 CHECK_EQ(oat_classes_[oat_class_index]->method_offsets_.size(),
Ian Rogers0571d352011-11-03 19:51:38 -0700190 it.NumDirectMethods() + it.NumVirtualMethods());
191 // Skip fields
192 while (it.HasNextStaticField()) {
193 it.Next();
194 }
195 while (it.HasNextInstanceField()) {
196 it.Next();
197 }
198 // Process methods
Brian Carlstrome24fa612011-09-29 00:53:55 -0700199 size_t class_def_method_index = 0;
Ian Rogers0571d352011-11-03 19:51:38 -0700200 while (it.HasNextDirectMethod()) {
Ian Rogersc20a83e2012-01-18 18:15:32 -0800201 bool is_native = (it.GetMemberAccessFlags() & kAccNative) != 0;
Ian Rogers08f753d2012-08-24 14:35:25 -0700202 offset = InitOatCodeMethod(offset, oat_class_index, class_def_index, class_def_method_index,
203 is_native, it.GetMethodInvokeType(class_def), it.GetMemberIndex(),
204 &dex_file);
Ian Rogers0571d352011-11-03 19:51:38 -0700205 class_def_method_index++;
206 it.Next();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700207 }
Ian Rogers0571d352011-11-03 19:51:38 -0700208 while (it.HasNextVirtualMethod()) {
Ian Rogersc20a83e2012-01-18 18:15:32 -0800209 bool is_native = (it.GetMemberAccessFlags() & kAccNative) != 0;
Ian Rogers08f753d2012-08-24 14:35:25 -0700210 offset = InitOatCodeMethod(offset, oat_class_index, class_def_index, class_def_method_index,
211 is_native, it.GetMethodInvokeType(class_def), it.GetMemberIndex(),
212 &dex_file);
Ian Rogers0571d352011-11-03 19:51:38 -0700213 class_def_method_index++;
214 it.Next();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700215 }
Ian Rogers0571d352011-11-03 19:51:38 -0700216 DCHECK(!it.HasNext());
Brian Carlstrome24fa612011-09-29 00:53:55 -0700217 return offset;
218}
219
Elliott Hughes1bac54f2012-03-16 12:48:31 -0700220size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index,
221 size_t __attribute__((unused)) class_def_index,
222 size_t class_def_method_index,
223 bool __attribute__((unused)) is_native,
Ian Rogers08f753d2012-08-24 14:35:25 -0700224 InvokeType type,
Elliott Hughes1bac54f2012-03-16 12:48:31 -0700225 uint32_t method_idx, const DexFile* dex_file) {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700226 // derived from CompiledMethod if available
227 uint32_t code_offset = 0;
228 uint32_t frame_size_in_bytes = kStackAlignment;
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700229 uint32_t core_spill_mask = 0;
230 uint32_t fp_spill_mask = 0;
231 uint32_t mapping_table_offset = 0;
232 uint32_t vmap_table_offset = 0;
Brian Carlstrome7d856b2012-01-11 18:10:55 -0800233 uint32_t gc_map_offset = 0;
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700234 // derived from CompiledInvokeStub if available
235 uint32_t invoke_stub_offset = 0;
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700236#if defined(ART_USE_LLVM_COMPILER)
Logan Chien971bf3f2012-05-01 15:47:55 +0800237 uint32_t proxy_stub_offset = 0;
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700238#endif
Brian Carlstrome24fa612011-09-29 00:53:55 -0700239
Ian Rogers0571d352011-11-03 19:51:38 -0700240 CompiledMethod* compiled_method =
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800241 compiler_->GetCompiledMethod(Compiler::MethodReference(dex_file, method_idx));
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700242 if (compiled_method != NULL) {
Logan Chien971bf3f2012-05-01 15:47:55 +0800243 offset = compiled_method->AlignCode(offset);
244 DCHECK_ALIGNED(offset, kArmAlignment);
245 const std::vector<uint8_t>& code = compiled_method->GetCode();
246 uint32_t code_size = code.size() * sizeof(code[0]);
247 CHECK_NE(code_size, 0U);
248 uint32_t thumb_offset = compiled_method->CodeDelta();
249 code_offset = offset + sizeof(code_size) + thumb_offset;
250
251 // Deduplicate code arrays
252 SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
253 if (code_iter != code_offsets_.end()) {
254 code_offset = code_iter->second;
jeffhao55d78212011-11-02 11:41:50 -0700255 } else {
Logan Chien971bf3f2012-05-01 15:47:55 +0800256 code_offsets_.Put(&code, code_offset);
257 offset += sizeof(code_size); // code size is prepended before code
258 offset += code_size;
259 oat_header_->UpdateChecksum(&code[0], code_size);
260 }
261 frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
262 core_spill_mask = compiled_method->GetCoreSpillMask();
263 fp_spill_mask = compiled_method->GetFpSpillMask();
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700264
Logan Chien971bf3f2012-05-01 15:47:55 +0800265 const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable();
266 size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
267 mapping_table_offset = (mapping_table_size == 0) ? 0 : offset;
jeffhao55d78212011-11-02 11:41:50 -0700268
Logan Chien971bf3f2012-05-01 15:47:55 +0800269 // Deduplicate mapping tables
270 SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = mapping_table_offsets_.find(&mapping_table);
271 if (mapping_iter != mapping_table_offsets_.end()) {
272 mapping_table_offset = mapping_iter->second;
273 } else {
274 mapping_table_offsets_.Put(&mapping_table, mapping_table_offset);
275 offset += mapping_table_size;
276 oat_header_->UpdateChecksum(&mapping_table[0], mapping_table_size);
277 }
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700278
Logan Chien971bf3f2012-05-01 15:47:55 +0800279 const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable();
280 size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
281 vmap_table_offset = (vmap_table_size == 0) ? 0 : offset;
jeffhao55d78212011-11-02 11:41:50 -0700282
Logan Chien971bf3f2012-05-01 15:47:55 +0800283 // Deduplicate vmap tables
284 SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = vmap_table_offsets_.find(&vmap_table);
285 if (vmap_iter != vmap_table_offsets_.end()) {
286 vmap_table_offset = vmap_iter->second;
287 } else {
288 vmap_table_offsets_.Put(&vmap_table, vmap_table_offset);
289 offset += vmap_table_size;
290 oat_header_->UpdateChecksum(&vmap_table[0], vmap_table_size);
291 }
Brian Carlstrome7d856b2012-01-11 18:10:55 -0800292
Logan Chien971bf3f2012-05-01 15:47:55 +0800293 const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap();
294 size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]);
295 gc_map_offset = (gc_map_size == 0) ? 0 : offset;
Logan Chienccb7bf12012-03-28 12:52:32 +0800296
Logan Chien971bf3f2012-05-01 15:47:55 +0800297#if !defined(NDEBUG) && !defined(ART_USE_LLVM_COMPILER)
298 // We expect GC maps except when the class hasn't been verified or the method is native
299 CompiledClass* compiled_class =
300 compiler_->GetCompiledClass(Compiler::MethodReference(dex_file, class_def_index));
301 Class::Status status =
302 (compiled_class != NULL) ? compiled_class->GetStatus() : Class::kStatusNotReady;
303 CHECK(gc_map_size != 0 || is_native || status < Class::kStatusVerified)
304 << &gc_map << " " << gc_map_size << " " << (is_native ? "true" : "false") << " " << (status < Class::kStatusVerified) << " " << status << " " << PrettyMethod(method_idx, *dex_file);
Ian Rogersc20a83e2012-01-18 18:15:32 -0800305#endif
306
Logan Chien971bf3f2012-05-01 15:47:55 +0800307 // Deduplicate GC maps
308 SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = gc_map_offsets_.find(&gc_map);
309 if (gc_map_iter != gc_map_offsets_.end()) {
310 gc_map_offset = gc_map_iter->second;
311 } else {
312 gc_map_offsets_.Put(&gc_map, gc_map_offset);
313 offset += gc_map_size;
314 oat_header_->UpdateChecksum(&gc_map[0], gc_map_size);
Brian Carlstrome7d856b2012-01-11 18:10:55 -0800315 }
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700316 }
317
Ian Rogers0571d352011-11-03 19:51:38 -0700318 const char* shorty = dex_file->GetMethodShorty(dex_file->GetMethodId(method_idx));
Ian Rogers08f753d2012-08-24 14:35:25 -0700319 const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(type == kStatic,
320 shorty);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700321 if (compiled_invoke_stub != NULL) {
Logan Chien971bf3f2012-05-01 15:47:55 +0800322 offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet());
323 DCHECK_ALIGNED(offset, kArmAlignment);
324 const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
325 uint32_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
326 CHECK_NE(invoke_stub_size, 0U);
327 uint32_t thumb_offset = compiled_invoke_stub->CodeDelta();
328 invoke_stub_offset = offset + sizeof(invoke_stub_size) + thumb_offset;
Logan Chienccb7bf12012-03-28 12:52:32 +0800329
Logan Chien971bf3f2012-05-01 15:47:55 +0800330 // Deduplicate invoke stubs
331 SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&invoke_stub);
332 if (stub_iter != code_offsets_.end()) {
333 invoke_stub_offset = stub_iter->second;
334 } else {
335 code_offsets_.Put(&invoke_stub, invoke_stub_offset);
336 offset += sizeof(invoke_stub_size); // invoke stub size is prepended before code
337 offset += invoke_stub_size;
338 oat_header_->UpdateChecksum(&invoke_stub[0], invoke_stub_size);
jeffhao55d78212011-11-02 11:41:50 -0700339 }
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700340 }
341
Logan Chien7a2a23a2012-06-06 11:01:00 +0800342#if defined(ART_USE_LLVM_COMPILER)
Ian Rogers08f753d2012-08-24 14:35:25 -0700343 if (type == kStatic) {
Logan Chien7a2a23a2012-06-06 11:01:00 +0800344 const CompiledInvokeStub* compiled_proxy_stub = compiler_->FindProxyStub(shorty);
345 if (compiled_proxy_stub != NULL) {
Logan Chien971bf3f2012-05-01 15:47:55 +0800346 offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet());
347 DCHECK_ALIGNED(offset, kArmAlignment);
348 const std::vector<uint8_t>& proxy_stub = compiled_proxy_stub->GetCode();
349 uint32_t proxy_stub_size = proxy_stub.size() * sizeof(proxy_stub[0]);
350 CHECK_NE(proxy_stub_size, 0U);
351 uint32_t thumb_offset = compiled_proxy_stub->CodeDelta();
352 proxy_stub_offset = offset + sizeof(proxy_stub_size) + thumb_offset;
353
354 // Deduplicate proxy stubs
355 SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&proxy_stub);
356 if (stub_iter != code_offsets_.end()) {
357 proxy_stub_offset = stub_iter->second;
358 } else {
359 code_offsets_.Put(&proxy_stub, proxy_stub_offset);
360 offset += sizeof(proxy_stub_size); // proxy stub size is prepended before code
361 offset += proxy_stub_size;
362 oat_header_->UpdateChecksum(&proxy_stub[0], proxy_stub_size);
363 }
Logan Chien7a2a23a2012-06-06 11:01:00 +0800364 }
365 }
366#endif
367
Brian Carlstrom389efb02012-01-11 12:06:26 -0800368 oat_classes_[oat_class_index]->method_offsets_[class_def_method_index]
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700369 = OatMethodOffsets(code_offset,
370 frame_size_in_bytes,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700371 core_spill_mask,
372 fp_spill_mask,
373 mapping_table_offset,
374 vmap_table_offset,
Brian Carlstrome7d856b2012-01-11 18:10:55 -0800375 gc_map_offset,
Logan Chienccb7bf12012-03-28 12:52:32 +0800376 invoke_stub_offset
377#if defined(ART_USE_LLVM_COMPILER)
Logan Chien971bf3f2012-05-01 15:47:55 +0800378 , proxy_stub_offset
Logan Chienccb7bf12012-03-28 12:52:32 +0800379#endif
380 );
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700381
Ian Rogers0571d352011-11-03 19:51:38 -0700382 if (compiler_->IsImage()) {
383 ClassLinker* linker = Runtime::Current()->GetClassLinker();
384 DexCache* dex_cache = linker->FindDexCache(*dex_file);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700385 // Unchecked as we hold mutator_lock_ on entry.
386 ScopedObjectAccessUnchecked soa(Thread::Current());
387 Method* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache,
jeffhaoc0228b82012-08-29 18:15:05 -0700388 soa.Decode<ClassLoader*>(class_loader_), NULL, type);
Ian Rogers0571d352011-11-03 19:51:38 -0700389 CHECK(method != NULL);
390 method->SetFrameSizeInBytes(frame_size_in_bytes);
391 method->SetCoreSpillMask(core_spill_mask);
392 method->SetFpSpillMask(fp_spill_mask);
393 method->SetOatMappingTableOffset(mapping_table_offset);
Ian Rogers19846512012-02-24 11:42:47 -0800394 // Don't overwrite static method trampoline
395 if (!method->IsStatic() || method->IsConstructor() ||
396 method->GetDeclaringClass()->IsInitialized()) {
397 method->SetOatCodeOffset(code_offset);
398 } else {
399 method->SetCode(Runtime::Current()->GetResolutionStubArray(Runtime::kStaticMethod)->GetData());
400 }
Ian Rogers0571d352011-11-03 19:51:38 -0700401 method->SetOatVmapTableOffset(vmap_table_offset);
Brian Carlstrome7d856b2012-01-11 18:10:55 -0800402 method->SetOatGcMapOffset(gc_map_offset);
Ian Rogers0571d352011-11-03 19:51:38 -0700403 method->SetOatInvokeStubOffset(invoke_stub_offset);
404 }
Logan Chien8b977d32012-02-21 19:14:55 +0800405
Brian Carlstrome24fa612011-09-29 00:53:55 -0700406 return offset;
407}
408
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700409#define DCHECK_CODE_OFFSET() \
Elliott Hughes2a2ff562012-01-06 18:07:59 -0800410 DCHECK_EQ(static_cast<off_t>(code_offset), lseek(file->Fd(), 0, SEEK_CUR))
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700411
Elliott Hughes234da572011-11-03 22:13:06 -0700412bool OatWriter::Write(File* file) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700413 if (!file->WriteFully(oat_header_, sizeof(*oat_header_))) {
Elliott Hughes234da572011-11-03 22:13:06 -0700414 PLOG(ERROR) << "Failed to write oat header to " << file->name();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700415 return false;
416 }
417
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700418 if (!file->WriteFully(image_file_location_.data(),
419 image_file_location_.size())) {
420 PLOG(ERROR) << "Failed to write oat header image file location to " << file->name();
421 return false;
422 }
423
Elliott Hughes234da572011-11-03 22:13:06 -0700424 if (!WriteTables(file)) {
425 LOG(ERROR) << "Failed to write oat tables to " << file->name();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700426 return false;
427 }
428
Elliott Hughes234da572011-11-03 22:13:06 -0700429 size_t code_offset = WriteCode(file);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700430 if (code_offset == 0) {
Elliott Hughes234da572011-11-03 22:13:06 -0700431 LOG(ERROR) << "Failed to write oat code to " << file->name();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700432 return false;
433 }
434
Elliott Hughes234da572011-11-03 22:13:06 -0700435 code_offset = WriteCodeDexFiles(file, code_offset);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700436 if (code_offset == 0) {
Elliott Hughes234da572011-11-03 22:13:06 -0700437 LOG(ERROR) << "Failed to write oat code for dex files to " << file->name();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700438 return false;
439 }
440
441 return true;
442}
443
444bool OatWriter::WriteTables(File* file) {
445 for (size_t i = 0; i != oat_dex_files_.size(); ++i) {
446 if (!oat_dex_files_[i]->Write(file)) {
Elliott Hughes234da572011-11-03 22:13:06 -0700447 PLOG(ERROR) << "Failed to write oat dex information to " << file->name();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700448 return false;
449 }
450 }
Brian Carlstrom89521892011-12-07 22:05:07 -0800451 for (size_t i = 0; i != oat_dex_files_.size(); ++i) {
452 uint32_t expected_offset = oat_dex_files_[i]->dex_file_offset_;
Elliott Hughes2a2ff562012-01-06 18:07:59 -0800453 off_t actual_offset = lseek(file->Fd(), expected_offset, SEEK_SET);
Brian Carlstrom89521892011-12-07 22:05:07 -0800454 if (static_cast<uint32_t>(actual_offset) != expected_offset) {
455 const DexFile* dex_file = (*dex_files_)[i];
456 PLOG(ERROR) << "Failed to seek to dex file section. Actual: " << actual_offset
457 << " Expected: " << expected_offset << " File: " << dex_file->GetLocation();
458 return false;
459 }
460 const DexFile* dex_file = (*dex_files_)[i];
461 if (!file->WriteFully(&dex_file->GetHeader(), dex_file->GetHeader().file_size_)) {
462 PLOG(ERROR) << "Failed to write dex file " << dex_file->GetLocation() << " to " << file->name();
463 return false;
464 }
465 }
Brian Carlstrom389efb02012-01-11 12:06:26 -0800466 for (size_t i = 0; i != oat_classes_.size(); ++i) {
467 if (!oat_classes_[i]->Write(file)) {
Elliott Hughes234da572011-11-03 22:13:06 -0700468 PLOG(ERROR) << "Failed to write oat methods information to " << file->name();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700469 return false;
470 }
471 }
472 return true;
473}
474
475size_t OatWriter::WriteCode(File* file) {
476 uint32_t code_offset = oat_header_->GetExecutableOffset();
Elliott Hughes2a2ff562012-01-06 18:07:59 -0800477 off_t new_offset = lseek(file->Fd(), executable_offset_padding_length_, SEEK_CUR);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700478 if (static_cast<uint32_t>(new_offset) != code_offset) {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700479 PLOG(ERROR) << "Failed to seek to oat code section. Actual: " << new_offset
Elliott Hughes234da572011-11-03 22:13:06 -0700480 << " Expected: " << code_offset << " File: " << file->name();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700481 return 0;
482 }
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700483 DCHECK_CODE_OFFSET();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700484 return code_offset;
485}
486
487size_t OatWriter::WriteCodeDexFiles(File* file, size_t code_offset) {
Ian Rogers0571d352011-11-03 19:51:38 -0700488 size_t oat_class_index = 0;
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800489 for (size_t i = 0; i != oat_dex_files_.size(); ++i) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700490 const DexFile* dex_file = (*dex_files_)[i];
491 CHECK(dex_file != NULL);
Ian Rogers0571d352011-11-03 19:51:38 -0700492 code_offset = WriteCodeDexFile(file, code_offset, oat_class_index, *dex_file);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700493 if (code_offset == 0) {
494 return 0;
495 }
496 }
497 return code_offset;
498}
499
Ian Rogers0571d352011-11-03 19:51:38 -0700500size_t OatWriter::WriteCodeDexFile(File* file, size_t code_offset, size_t& oat_class_index,
501 const DexFile& dex_file) {
502 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs();
503 class_def_index++, oat_class_index++) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700504 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
Ian Rogers0571d352011-11-03 19:51:38 -0700505 code_offset = WriteCodeClassDef(file, code_offset, oat_class_index, dex_file, class_def);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700506 if (code_offset == 0) {
507 return 0;
508 }
509 }
510 return code_offset;
511}
512
Ian Rogers0571d352011-11-03 19:51:38 -0700513void OatWriter::ReportWriteFailure(const char* what, uint32_t method_idx,
514 const DexFile& dex_file, File* f) const {
515 PLOG(ERROR) << "Failed to write " << what << " for " << PrettyMethod(method_idx, dex_file)
516 << " to " << f->name();
Elliott Hughes234da572011-11-03 22:13:06 -0700517}
518
Brian Carlstrome24fa612011-09-29 00:53:55 -0700519size_t OatWriter::WriteCodeClassDef(File* file,
Ian Rogers0571d352011-11-03 19:51:38 -0700520 size_t code_offset, size_t oat_class_index,
Brian Carlstrome24fa612011-09-29 00:53:55 -0700521 const DexFile& dex_file,
522 const DexFile::ClassDef& class_def) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700523 const byte* class_data = dex_file.GetClassData(class_def);
Ian Rogers0571d352011-11-03 19:51:38 -0700524 if (class_data == NULL) {
525 // ie. an empty class such as a marker interface
Ian Rogers387b6992011-10-31 17:52:37 -0700526 return code_offset;
527 }
Ian Rogers0571d352011-11-03 19:51:38 -0700528 ClassDataItemIterator it(dex_file, class_data);
529 // Skip fields
530 while (it.HasNextStaticField()) {
531 it.Next();
532 }
533 while (it.HasNextInstanceField()) {
534 it.Next();
535 }
536 // Process methods
537 size_t class_def_method_index = 0;
538 while (it.HasNextDirectMethod()) {
539 bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0;
540 code_offset = WriteCodeMethod(file, code_offset, oat_class_index, class_def_method_index,
541 is_static, it.GetMemberIndex(), dex_file);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700542 if (code_offset == 0) {
543 return 0;
544 }
Ian Rogers0571d352011-11-03 19:51:38 -0700545 class_def_method_index++;
546 it.Next();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700547 }
Ian Rogers0571d352011-11-03 19:51:38 -0700548 while (it.HasNextVirtualMethod()) {
549 code_offset = WriteCodeMethod(file, code_offset, oat_class_index, class_def_method_index,
550 false, it.GetMemberIndex(), dex_file);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700551 if (code_offset == 0) {
552 return 0;
553 }
Ian Rogers0571d352011-11-03 19:51:38 -0700554 class_def_method_index++;
555 it.Next();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700556 }
557 return code_offset;
558}
559
Ian Rogers0571d352011-11-03 19:51:38 -0700560size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, size_t oat_class_index,
561 size_t class_def_method_index, bool is_static,
562 uint32_t method_idx, const DexFile& dex_file) {
563 const CompiledMethod* compiled_method =
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800564 compiler_->GetCompiledMethod(Compiler::MethodReference(&dex_file, method_idx));
Ian Rogers0571d352011-11-03 19:51:38 -0700565
Ian Rogers0571d352011-11-03 19:51:38 -0700566 OatMethodOffsets method_offsets =
Brian Carlstrom389efb02012-01-11 12:06:26 -0800567 oat_classes_[oat_class_index]->method_offsets_[class_def_method_index];
Ian Rogers0571d352011-11-03 19:51:38 -0700568
569
570 if (compiled_method != NULL) { // ie. not an abstract method
Logan Chien971bf3f2012-05-01 15:47:55 +0800571 uint32_t aligned_code_offset = compiled_method->AlignCode(code_offset);
572 uint32_t aligned_code_delta = aligned_code_offset - code_offset;
573 if (aligned_code_delta != 0) {
574 off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR);
575 if (static_cast<uint32_t>(new_offset) != aligned_code_offset) {
576 PLOG(ERROR) << "Failed to seek to align oat code. Actual: " << new_offset
577 << " Expected: " << aligned_code_offset << " File: " << file->name();
578 return 0;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700579 }
Logan Chien971bf3f2012-05-01 15:47:55 +0800580 code_offset += aligned_code_delta;
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700581 DCHECK_CODE_OFFSET();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700582 }
Logan Chien971bf3f2012-05-01 15:47:55 +0800583 DCHECK_ALIGNED(code_offset, kArmAlignment);
584 const std::vector<uint8_t>& code = compiled_method->GetCode();
585 uint32_t code_size = code.size() * sizeof(code[0]);
586 CHECK_NE(code_size, 0U);
587
588 // Deduplicate code arrays
589 size_t offset = code_offset + sizeof(code_size) + compiled_method->CodeDelta();
590 SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
591 if (code_iter != code_offsets_.end() && offset != method_offsets.code_offset_) {
592 DCHECK(code_iter->second == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file);
593 } else {
594 DCHECK(offset == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file);
595 if (!file->WriteFully(&code_size, sizeof(code_size))) {
596 ReportWriteFailure("method code size", method_idx, dex_file, file);
597 return 0;
598 }
599 code_offset += sizeof(code_size);
600 DCHECK_CODE_OFFSET();
601 if (!file->WriteFully(&code[0], code_size)) {
602 ReportWriteFailure("method code", method_idx, dex_file, file);
603 return 0;
604 }
605 code_offset += code_size;
606 }
607 DCHECK_CODE_OFFSET();
608
609 const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable();
610 size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
611
612 // Deduplicate mapping tables
613 SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter =
614 mapping_table_offsets_.find(&mapping_table);
615 if (mapping_iter != mapping_table_offsets_.end() &&
616 code_offset != method_offsets.mapping_table_offset_) {
617 DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0)
618 || mapping_iter->second == method_offsets.mapping_table_offset_)
619 << PrettyMethod(method_idx, dex_file);
620 } else {
621 DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0)
622 || code_offset == method_offsets.mapping_table_offset_)
623 << PrettyMethod(method_idx, dex_file);
624 if (!file->WriteFully(&mapping_table[0], mapping_table_size)) {
625 ReportWriteFailure("mapping table", method_idx, dex_file, file);
626 return 0;
627 }
628 code_offset += mapping_table_size;
629 }
630 DCHECK_CODE_OFFSET();
631
632 const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable();
633 size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
634
635 // Deduplicate vmap tables
636 SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter =
637 vmap_table_offsets_.find(&vmap_table);
638 if (vmap_iter != vmap_table_offsets_.end() &&
639 code_offset != method_offsets.vmap_table_offset_) {
640 DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0)
641 || vmap_iter->second == method_offsets.vmap_table_offset_)
642 << PrettyMethod(method_idx, dex_file);
643 } else {
644 DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0)
645 || code_offset == method_offsets.vmap_table_offset_)
646 << PrettyMethod(method_idx, dex_file);
647 if (!file->WriteFully(&vmap_table[0], vmap_table_size)) {
648 ReportWriteFailure("vmap table", method_idx, dex_file, file);
649 return 0;
650 }
651 code_offset += vmap_table_size;
652 }
653 DCHECK_CODE_OFFSET();
654
655 const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap();
656 size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]);
657
658 // Deduplicate GC maps
659 SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter =
660 gc_map_offsets_.find(&gc_map);
661 if (gc_map_iter != gc_map_offsets_.end() &&
662 code_offset != method_offsets.gc_map_offset_) {
663 DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0)
664 || gc_map_iter->second == method_offsets.gc_map_offset_)
665 << PrettyMethod(method_idx, dex_file);
666 } else {
667 DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0)
668 || code_offset == method_offsets.gc_map_offset_)
669 << PrettyMethod(method_idx, dex_file);
670 if (!file->WriteFully(&gc_map[0], gc_map_size)) {
671 ReportWriteFailure("GC map", method_idx, dex_file, file);
672 return 0;
673 }
674 code_offset += gc_map_size;
675 }
676 DCHECK_CODE_OFFSET();
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700677 }
Ian Rogers0571d352011-11-03 19:51:38 -0700678 const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
679 const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700680 if (compiled_invoke_stub != NULL) {
Logan Chien971bf3f2012-05-01 15:47:55 +0800681 uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset,
682 compiler_->GetInstructionSet());
683 uint32_t aligned_code_delta = aligned_code_offset - code_offset;
684 if (aligned_code_delta != 0) {
685 off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR);
686 if (static_cast<uint32_t>(new_offset) != aligned_code_offset) {
687 PLOG(ERROR) << "Failed to seek to align invoke stub code. Actual: " << new_offset
688 << " Expected: " << aligned_code_offset;
689 return 0;
690 }
691 code_offset += aligned_code_delta;
692 DCHECK_CODE_OFFSET();
693 }
694 DCHECK_ALIGNED(code_offset, kArmAlignment);
695 const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
696 uint32_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
697 CHECK_NE(invoke_stub_size, 0U);
698
699 // Deduplicate invoke stubs
700 size_t offset = code_offset + sizeof(invoke_stub_size) + compiled_invoke_stub->CodeDelta();
701 SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter =
702 code_offsets_.find(&invoke_stub);
703 if (stub_iter != code_offsets_.end() && offset != method_offsets.invoke_stub_offset_) {
704 DCHECK(stub_iter->second == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file);
705 } else {
706 DCHECK(offset == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file);
707 if (!file->WriteFully(&invoke_stub_size, sizeof(invoke_stub_size))) {
708 ReportWriteFailure("invoke stub code size", method_idx, dex_file, file);
709 return 0;
710 }
711 code_offset += sizeof(invoke_stub_size);
712 DCHECK_CODE_OFFSET();
713 if (!file->WriteFully(&invoke_stub[0], invoke_stub_size)) {
714 ReportWriteFailure("invoke stub code", method_idx, dex_file, file);
715 return 0;
716 }
717 code_offset += invoke_stub_size;
718 DCHECK_CODE_OFFSET();
719 }
720 }
721
722#if defined(ART_USE_LLVM_COMPILER)
Ian Rogers08f753d2012-08-24 14:35:25 -0700723 if (is_static) {
Logan Chien971bf3f2012-05-01 15:47:55 +0800724 const CompiledInvokeStub* compiled_proxy_stub = compiler_->FindProxyStub(shorty);
725 if (compiled_proxy_stub != NULL) {
Logan Chienccb7bf12012-03-28 12:52:32 +0800726 uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset,
727 compiler_->GetInstructionSet());
728 uint32_t aligned_code_delta = aligned_code_offset - code_offset;
Logan Chien971bf3f2012-05-01 15:47:55 +0800729 CHECK(aligned_code_delta < 48u);
Logan Chienccb7bf12012-03-28 12:52:32 +0800730 if (aligned_code_delta != 0) {
731 off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR);
732 if (static_cast<uint32_t>(new_offset) != aligned_code_offset) {
Logan Chien971bf3f2012-05-01 15:47:55 +0800733 PLOG(ERROR) << "Failed to seek to align proxy stub code. Actual: " << new_offset
Logan Chienccb7bf12012-03-28 12:52:32 +0800734 << " Expected: " << aligned_code_offset;
735 return 0;
736 }
737 code_offset += aligned_code_delta;
738 DCHECK_CODE_OFFSET();
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700739 }
Logan Chienccb7bf12012-03-28 12:52:32 +0800740 DCHECK_ALIGNED(code_offset, kArmAlignment);
Logan Chien971bf3f2012-05-01 15:47:55 +0800741 const std::vector<uint8_t>& proxy_stub = compiled_proxy_stub->GetCode();
742 uint32_t proxy_stub_size = proxy_stub.size() * sizeof(proxy_stub[0]);
743 CHECK_NE(proxy_stub_size, 0U);
jeffhao55d78212011-11-02 11:41:50 -0700744
Logan Chien971bf3f2012-05-01 15:47:55 +0800745 // Deduplicate proxy stubs
746 size_t offset = code_offset + sizeof(proxy_stub_size) + compiled_proxy_stub->CodeDelta();
Elliott Hughesa0e18062012-04-13 15:59:59 -0700747 SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter =
Logan Chien971bf3f2012-05-01 15:47:55 +0800748 code_offsets_.find(&proxy_stub);
749 if (stub_iter != code_offsets_.end() && offset != method_offsets.proxy_stub_offset_) {
750 DCHECK(stub_iter->second == method_offsets.proxy_stub_offset_) << PrettyMethod(method_idx, dex_file);
Logan Chienccb7bf12012-03-28 12:52:32 +0800751 } else {
Logan Chien971bf3f2012-05-01 15:47:55 +0800752 DCHECK(offset == method_offsets.proxy_stub_offset_) << PrettyMethod(method_idx, dex_file);
753 if (!file->WriteFully(&proxy_stub_size, sizeof(proxy_stub_size))) {
754 ReportWriteFailure("proxy stub code size", method_idx, dex_file, file);
Logan Chienccb7bf12012-03-28 12:52:32 +0800755 return 0;
756 }
Logan Chien971bf3f2012-05-01 15:47:55 +0800757 code_offset += sizeof(proxy_stub_size);
Logan Chienccb7bf12012-03-28 12:52:32 +0800758 DCHECK_CODE_OFFSET();
Logan Chien971bf3f2012-05-01 15:47:55 +0800759 if (!file->WriteFully(&proxy_stub[0], proxy_stub_size)) {
760 ReportWriteFailure("proxy stub code", method_idx, dex_file, file);
Logan Chienccb7bf12012-03-28 12:52:32 +0800761 return 0;
762 }
Logan Chien971bf3f2012-05-01 15:47:55 +0800763 code_offset += proxy_stub_size;
764 DCHECK_CODE_OFFSET();
Brian Carlstromf8bbb842012-03-14 03:01:42 -0700765 }
Brian Carlstromf8bbb842012-03-14 03:01:42 -0700766 DCHECK_CODE_OFFSET();
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700767 }
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700768 }
Logan Chien971bf3f2012-05-01 15:47:55 +0800769#endif
Logan Chien8b977d32012-02-21 19:14:55 +0800770
Brian Carlstrome24fa612011-09-29 00:53:55 -0700771 return code_offset;
772}
773
Brian Carlstrome24fa612011-09-29 00:53:55 -0700774OatWriter::OatDexFile::OatDexFile(const DexFile& dex_file) {
Elliott Hughes95572412011-12-13 18:14:20 -0800775 const std::string& location(dex_file.GetLocation());
Brian Carlstrome24fa612011-09-29 00:53:55 -0700776 dex_file_location_size_ = location.size();
777 dex_file_location_data_ = reinterpret_cast<const uint8_t*>(location.data());
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800778 dex_file_location_checksum_ = dex_file.GetLocationChecksum();
Brian Carlstrom89521892011-12-07 22:05:07 -0800779 dex_file_offset_ = 0;
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800780 methods_offsets_.resize(dex_file.NumClassDefs());
Brian Carlstrome24fa612011-09-29 00:53:55 -0700781}
782
783size_t OatWriter::OatDexFile::SizeOf() const {
784 return sizeof(dex_file_location_size_)
785 + dex_file_location_size_
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800786 + sizeof(dex_file_location_checksum_)
Brian Carlstrom89521892011-12-07 22:05:07 -0800787 + sizeof(dex_file_offset_)
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800788 + (sizeof(methods_offsets_[0]) * methods_offsets_.size());
Brian Carlstrome24fa612011-09-29 00:53:55 -0700789}
790
791void OatWriter::OatDexFile::UpdateChecksum(OatHeader& oat_header) const {
792 oat_header.UpdateChecksum(&dex_file_location_size_, sizeof(dex_file_location_size_));
793 oat_header.UpdateChecksum(dex_file_location_data_, dex_file_location_size_);
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800794 oat_header.UpdateChecksum(&dex_file_location_checksum_, sizeof(dex_file_location_checksum_));
Brian Carlstrom89521892011-12-07 22:05:07 -0800795 oat_header.UpdateChecksum(&dex_file_offset_, sizeof(dex_file_offset_));
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800796 oat_header.UpdateChecksum(&methods_offsets_[0],
797 sizeof(methods_offsets_[0]) * methods_offsets_.size());
Brian Carlstrome24fa612011-09-29 00:53:55 -0700798}
799
800bool OatWriter::OatDexFile::Write(File* file) const {
801 if (!file->WriteFully(&dex_file_location_size_, sizeof(dex_file_location_size_))) {
Elliott Hughes234da572011-11-03 22:13:06 -0700802 PLOG(ERROR) << "Failed to write dex file location length to " << file->name();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700803 return false;
804 }
805 if (!file->WriteFully(dex_file_location_data_, dex_file_location_size_)) {
Elliott Hughes234da572011-11-03 22:13:06 -0700806 PLOG(ERROR) << "Failed to write dex file location data to " << file->name();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700807 return false;
808 }
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800809 if (!file->WriteFully(&dex_file_location_checksum_, sizeof(dex_file_location_checksum_))) {
810 PLOG(ERROR) << "Failed to write dex file location checksum to " << file->name();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700811 return false;
812 }
Brian Carlstrom89521892011-12-07 22:05:07 -0800813 if (!file->WriteFully(&dex_file_offset_, sizeof(dex_file_offset_))) {
814 PLOG(ERROR) << "Failed to write dex file offset to " << file->name();
815 return false;
816 }
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800817 if (!file->WriteFully(&methods_offsets_[0],
818 sizeof(methods_offsets_[0]) * methods_offsets_.size())) {
Elliott Hughes234da572011-11-03 22:13:06 -0700819 PLOG(ERROR) << "Failed to write methods offsets to " << file->name();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700820 return false;
821 }
822 return true;
823}
824
Brian Carlstrom0755ec52012-01-11 15:19:46 -0800825OatWriter::OatClass::OatClass(Class::Status status, uint32_t methods_count) {
826 status_ = status;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700827 method_offsets_.resize(methods_count);
828}
829
Brian Carlstrom389efb02012-01-11 12:06:26 -0800830size_t OatWriter::OatClass::SizeOf() const {
Brian Carlstrom0755ec52012-01-11 15:19:46 -0800831 return sizeof(status_)
832 + (sizeof(method_offsets_[0]) * method_offsets_.size());
Brian Carlstrome24fa612011-09-29 00:53:55 -0700833}
834
Brian Carlstrom389efb02012-01-11 12:06:26 -0800835void OatWriter::OatClass::UpdateChecksum(OatHeader& oat_header) const {
Brian Carlstrom0755ec52012-01-11 15:19:46 -0800836 oat_header.UpdateChecksum(&status_, sizeof(status_));
837 oat_header.UpdateChecksum(&method_offsets_[0],
838 sizeof(method_offsets_[0]) * method_offsets_.size());
Brian Carlstrome24fa612011-09-29 00:53:55 -0700839}
840
Brian Carlstrom389efb02012-01-11 12:06:26 -0800841bool OatWriter::OatClass::Write(File* file) const {
Brian Carlstrom0755ec52012-01-11 15:19:46 -0800842 if (!file->WriteFully(&status_, sizeof(status_))) {
843 PLOG(ERROR) << "Failed to write class status to " << file->name();
844 return false;
845 }
846 if (!file->WriteFully(&method_offsets_[0],
847 sizeof(method_offsets_[0]) * method_offsets_.size())) {
Elliott Hughes234da572011-11-03 22:13:06 -0700848 PLOG(ERROR) << "Failed to write method offsets to " << file->name();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700849 return false;
850 }
851 return true;
852}
853
Brian Carlstrome24fa612011-09-29 00:53:55 -0700854} // namespace art