| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1 | /* | 
 | 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 |  */ | 
 | 16 |  | 
 | 17 | #include <stdio.h> | 
 | 18 | #include <stdlib.h> | 
 | 19 | #include <sys/stat.h> | 
| Ian Rogers | 2672a9f | 2013-09-05 17:24:22 -0700 | [diff] [blame] | 20 | #include <valgrind.h> | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 21 |  | 
 | 22 | #include <fstream> | 
 | 23 | #include <iostream> | 
 | 24 | #include <sstream> | 
 | 25 | #include <string> | 
 | 26 | #include <vector> | 
 | 27 |  | 
 | 28 | #include "base/stl_util.h" | 
 | 29 | #include "base/stringpiece.h" | 
 | 30 | #include "base/timing_logger.h" | 
 | 31 | #include "base/unix_file/fd_file.h" | 
 | 32 | #include "class_linker.h" | 
| Nicolas Geoffray | f5df897 | 2014-02-14 18:37:08 +0000 | [diff] [blame] | 33 | #include "compiler_backend.h" | 
| Vladimir Marko | 2b5eaa2 | 2013-12-13 13:59:30 +0000 | [diff] [blame] | 34 | #include "compiler_callbacks.h" | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 35 | #include "dex_file-inl.h" | 
| Vladimir Marko | c7f8320 | 2014-01-24 17:55:18 +0000 | [diff] [blame] | 36 | #include "dex/verification_results.h" | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 37 | #include "driver/compiler_callbacks_impl.h" | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 38 | #include "driver/compiler_driver.h" | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 39 | #include "driver/compiler_options.h" | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 40 | #include "elf_fixup.h" | 
 | 41 | #include "elf_stripper.h" | 
 | 42 | #include "gc/space/image_space.h" | 
 | 43 | #include "gc/space/space-inl.h" | 
 | 44 | #include "image_writer.h" | 
 | 45 | #include "leb128.h" | 
| Brian Carlstrom | ea46f95 | 2013-07-30 01:26:50 -0700 | [diff] [blame] | 46 | #include "mirror/art_method-inl.h" | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 47 | #include "mirror/class-inl.h" | 
 | 48 | #include "mirror/class_loader.h" | 
 | 49 | #include "mirror/object-inl.h" | 
 | 50 | #include "mirror/object_array-inl.h" | 
 | 51 | #include "oat_writer.h" | 
 | 52 | #include "object_utils.h" | 
 | 53 | #include "os.h" | 
 | 54 | #include "runtime.h" | 
 | 55 | #include "ScopedLocalRef.h" | 
 | 56 | #include "scoped_thread_state_change.h" | 
 | 57 | #include "sirt_ref.h" | 
 | 58 | #include "vector_output_stream.h" | 
 | 59 | #include "well_known_classes.h" | 
 | 60 | #include "zip_archive.h" | 
 | 61 |  | 
 | 62 | namespace art { | 
 | 63 |  | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 64 | static int original_argc; | 
 | 65 | static char** original_argv; | 
 | 66 |  | 
 | 67 | static std::string CommandLine() { | 
 | 68 |   std::vector<std::string> command; | 
 | 69 |   for (int i = 0; i < original_argc; ++i) { | 
 | 70 |     command.push_back(original_argv[i]); | 
 | 71 |   } | 
 | 72 |   return Join(command, ' '); | 
 | 73 | } | 
 | 74 |  | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 75 | static void UsageErrorV(const char* fmt, va_list ap) { | 
 | 76 |   std::string error; | 
 | 77 |   StringAppendV(&error, fmt, ap); | 
 | 78 |   LOG(ERROR) << error; | 
 | 79 | } | 
 | 80 |  | 
 | 81 | static void UsageError(const char* fmt, ...) { | 
 | 82 |   va_list ap; | 
 | 83 |   va_start(ap, fmt); | 
 | 84 |   UsageErrorV(fmt, ap); | 
 | 85 |   va_end(ap); | 
 | 86 | } | 
 | 87 |  | 
 | 88 | static void Usage(const char* fmt, ...) { | 
 | 89 |   va_list ap; | 
 | 90 |   va_start(ap, fmt); | 
 | 91 |   UsageErrorV(fmt, ap); | 
 | 92 |   va_end(ap); | 
 | 93 |  | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 94 |   UsageError("Command: %s", CommandLine().c_str()); | 
 | 95 |  | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 96 |   UsageError("Usage: dex2oat [options]..."); | 
 | 97 |   UsageError(""); | 
 | 98 |   UsageError("  --dex-file=<dex-file>: specifies a .dex file to compile."); | 
 | 99 |   UsageError("      Example: --dex-file=/system/framework/core.jar"); | 
 | 100 |   UsageError(""); | 
 | 101 |   UsageError("  --zip-fd=<file-descriptor>: specifies a file descriptor of a zip file"); | 
 | 102 |   UsageError("      containing a classes.dex file to compile."); | 
 | 103 |   UsageError("      Example: --zip-fd=5"); | 
 | 104 |   UsageError(""); | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 105 |   UsageError("  --zip-location=<zip-location>: specifies a symbolic name for the file"); | 
 | 106 |   UsageError("      corresponding to the file descriptor specified by --zip-fd."); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 107 |   UsageError("      Example: --zip-location=/system/app/Calculator.apk"); | 
 | 108 |   UsageError(""); | 
 | 109 |   UsageError("  --oat-file=<file.oat>: specifies the oat output destination via a filename."); | 
 | 110 |   UsageError("      Example: --oat-file=/system/framework/boot.oat"); | 
 | 111 |   UsageError(""); | 
 | 112 |   UsageError("  --oat-fd=<number>: specifies the oat output destination via a file descriptor."); | 
 | 113 |   UsageError("      Example: --oat-file=/system/framework/boot.oat"); | 
 | 114 |   UsageError(""); | 
 | 115 |   UsageError("  --oat-location=<oat-name>: specifies a symbolic name for the file corresponding"); | 
 | 116 |   UsageError("      to the file descriptor specified by --oat-fd."); | 
 | 117 |   UsageError("      Example: --oat-location=/data/dalvik-cache/system@app@Calculator.apk.oat"); | 
 | 118 |   UsageError(""); | 
 | 119 |   UsageError("  --oat-symbols=<file.oat>: specifies the oat output destination with full symbols."); | 
 | 120 |   UsageError("      Example: --oat-symbols=/symbols/system/framework/boot.oat"); | 
 | 121 |   UsageError(""); | 
 | 122 |   UsageError("  --bitcode=<file.bc>: specifies the optional bitcode filename."); | 
 | 123 |   UsageError("      Example: --bitcode=/system/framework/boot.bc"); | 
 | 124 |   UsageError(""); | 
 | 125 |   UsageError("  --image=<file.art>: specifies the output image filename."); | 
 | 126 |   UsageError("      Example: --image=/system/framework/boot.art"); | 
 | 127 |   UsageError(""); | 
 | 128 |   UsageError("  --image-classes=<classname-file>: specifies classes to include in an image."); | 
 | 129 |   UsageError("      Example: --image=frameworks/base/preloaded-classes"); | 
 | 130 |   UsageError(""); | 
 | 131 |   UsageError("  --base=<hex-address>: specifies the base address when creating a boot image."); | 
 | 132 |   UsageError("      Example: --base=0x50000000"); | 
 | 133 |   UsageError(""); | 
 | 134 |   UsageError("  --boot-image=<file.art>: provide the image file for the boot class path."); | 
 | 135 |   UsageError("      Example: --boot-image=/system/framework/boot.art"); | 
| Nicolas Geoffray | 9583fbc | 2014-02-28 15:21:07 +0000 | [diff] [blame] | 136 |   UsageError("      Default: $ANDROID_ROOT/system/framework/boot.art"); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 137 |   UsageError(""); | 
 | 138 |   UsageError("  --android-root=<path>: used to locate libraries for portable linking."); | 
 | 139 |   UsageError("      Example: --android-root=out/host/linux-x86"); | 
 | 140 |   UsageError("      Default: $ANDROID_ROOT"); | 
 | 141 |   UsageError(""); | 
| Ian Rogers | befbd57 | 2014-03-06 01:13:39 -0800 | [diff] [blame^] | 142 |   UsageError("  --instruction-set=(arm|mips|x86|x86_64): compile for a particular instruction"); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 143 |   UsageError("      set."); | 
 | 144 |   UsageError("      Example: --instruction-set=x86"); | 
 | 145 |   UsageError("      Default: arm"); | 
 | 146 |   UsageError(""); | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 147 |   UsageError("  --instruction-set-features=...,: Specify instruction set features"); | 
 | 148 |   UsageError("      Example: --instruction-set-features=div"); | 
 | 149 |   UsageError("      Default: default"); | 
 | 150 |   UsageError(""); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 151 |   UsageError("  --compiler-backend=(Quick|QuickGBC|Portable): select compiler backend"); | 
 | 152 |   UsageError("      set."); | 
| Brian Carlstrom | 635733d | 2013-10-30 23:19:31 -0700 | [diff] [blame] | 153 |   UsageError("      Example: --compiler-backend=Portable"); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 154 |   UsageError("      Default: Quick"); | 
 | 155 |   UsageError(""); | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 156 |   UsageError("  --compiler-filter=(interpret-only|space|balanced|speed|everything): select"); | 
 | 157 |   UsageError("      compiler filter."); | 
 | 158 |   UsageError("      Example: --compiler-filter=everything"); | 
 | 159 | #if ART_SMALL_MODE | 
 | 160 |   UsageError("      Default: interpret-only"); | 
 | 161 | #else | 
 | 162 |   UsageError("      Default: speed"); | 
 | 163 | #endif | 
 | 164 |   UsageError(""); | 
 | 165 |   UsageError("  --huge-method-max=<method-instruction-count>: the threshold size for a huge"); | 
 | 166 |   UsageError("      method for compiler filter tuning."); | 
 | 167 |   UsageError("      Example: --huge-method-max=%d", CompilerOptions::kDefaultHugeMethodThreshold); | 
 | 168 |   UsageError("      Default: %d", CompilerOptions::kDefaultHugeMethodThreshold); | 
 | 169 |   UsageError(""); | 
 | 170 |   UsageError("  --huge-method-max=<method-instruction-count>: threshold size for a huge"); | 
 | 171 |   UsageError("      method for compiler filter tuning."); | 
 | 172 |   UsageError("      Example: --huge-method-max=%d", CompilerOptions::kDefaultHugeMethodThreshold); | 
 | 173 |   UsageError("      Default: %d", CompilerOptions::kDefaultHugeMethodThreshold); | 
 | 174 |   UsageError(""); | 
 | 175 |   UsageError("  --large-method-max=<method-instruction-count>: threshold size for a large"); | 
 | 176 |   UsageError("      method for compiler filter tuning."); | 
 | 177 |   UsageError("      Example: --large-method-max=%d", CompilerOptions::kDefaultLargeMethodThreshold); | 
 | 178 |   UsageError("      Default: %d", CompilerOptions::kDefaultLargeMethodThreshold); | 
 | 179 |   UsageError(""); | 
 | 180 |   UsageError("  --small-method-max=<method-instruction-count>: threshold size for a small"); | 
 | 181 |   UsageError("      method for compiler filter tuning."); | 
 | 182 |   UsageError("      Example: --small-method-max=%d", CompilerOptions::kDefaultSmallMethodThreshold); | 
 | 183 |   UsageError("      Default: %d", CompilerOptions::kDefaultSmallMethodThreshold); | 
 | 184 |   UsageError(""); | 
 | 185 |   UsageError("  --tiny-method-max=<method-instruction-count>: threshold size for a tiny"); | 
 | 186 |   UsageError("      method for compiler filter tuning."); | 
 | 187 |   UsageError("      Example: --tiny-method-max=%d", CompilerOptions::kDefaultTinyMethodThreshold); | 
 | 188 |   UsageError("      Default: %d", CompilerOptions::kDefaultTinyMethodThreshold); | 
 | 189 |   UsageError(""); | 
 | 190 |   UsageError("  --num-dex-methods=<method-count>: threshold size for a small dex file for"); | 
 | 191 |   UsageError("      compiler filter tuning. If the input has fewer than this many methods"); | 
 | 192 |   UsageError("      and the filter is not interpret-only, overrides the filter to use speed"); | 
 | 193 |   UsageError("      Example: --num-dex-method=%d", CompilerOptions::kDefaultNumDexMethodsThreshold); | 
 | 194 |   UsageError("      Default: %d", CompilerOptions::kDefaultNumDexMethodsThreshold); | 
 | 195 |   UsageError(""); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 196 |   UsageError("  --host: used with Portable backend to link against host runtime libraries"); | 
 | 197 |   UsageError(""); | 
| Ian Rogers | 4639860 | 2013-08-20 07:50:36 -0700 | [diff] [blame] | 198 |   UsageError("  --dump-timing: display a breakdown of where time was spent"); | 
 | 199 |   UsageError(""); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 200 |   UsageError("  --runtime-arg <argument>: used to specify various arguments for the runtime,"); | 
 | 201 |   UsageError("      such as initial heap size, maximum heap size, and verbose output."); | 
 | 202 |   UsageError("      Use a separate --runtime-arg switch for each argument."); | 
 | 203 |   UsageError("      Example: --runtime-arg -Xms256m"); | 
 | 204 |   UsageError(""); | 
 | 205 |   std::cerr << "See log for usage error information\n"; | 
 | 206 |   exit(EXIT_FAILURE); | 
 | 207 | } | 
 | 208 |  | 
 | 209 | class Dex2Oat { | 
 | 210 |  public: | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 211 |   static bool Create(Dex2Oat** p_dex2oat, | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 212 |                      const Runtime::Options& runtime_options, | 
 | 213 |                      const CompilerOptions& compiler_options, | 
| Nicolas Geoffray | f5df897 | 2014-02-14 18:37:08 +0000 | [diff] [blame] | 214 |                      CompilerBackend::Kind compiler_backend, | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 215 |                      InstructionSet instruction_set, | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 216 |                      InstructionSetFeatures instruction_set_features, | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 217 |                      VerificationResults* verification_results, | 
 | 218 |                      DexFileToMethodInlinerMap* method_inliner_map, | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 219 |                      size_t thread_count) | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 220 |       SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_) { | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 221 |     CHECK(verification_results != nullptr); | 
 | 222 |     CHECK(method_inliner_map != nullptr); | 
 | 223 |     UniquePtr<Dex2Oat> dex2oat(new Dex2Oat(&compiler_options, | 
 | 224 |                                            compiler_backend, | 
 | 225 |                                            instruction_set, | 
 | 226 |                                            instruction_set_features, | 
 | 227 |                                            verification_results, | 
 | 228 |                                            method_inliner_map, | 
 | 229 |                                            thread_count)); | 
 | 230 |     if (!dex2oat->CreateRuntime(runtime_options, instruction_set)) { | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 231 |       *p_dex2oat = NULL; | 
 | 232 |       return false; | 
 | 233 |     } | 
| Vladimir Marko | 2b5eaa2 | 2013-12-13 13:59:30 +0000 | [diff] [blame] | 234 |     *p_dex2oat = dex2oat.release(); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 235 |     return true; | 
 | 236 |   } | 
 | 237 |  | 
 | 238 |   ~Dex2Oat() { | 
 | 239 |     delete runtime_; | 
| Brian Carlstrom | 65c23bb | 2014-02-01 22:12:39 -0800 | [diff] [blame] | 240 |     LogCompletionTime(); | 
 | 241 |   } | 
 | 242 |  | 
 | 243 |   void LogCompletionTime() { | 
 | 244 |     LOG(INFO) << "dex2oat took " << PrettyDuration(NanoTime() - start_ns_) | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 245 |               << " (threads: " << thread_count_ << ")"; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 246 |   } | 
 | 247 |  | 
 | 248 |  | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 249 |   // Reads the class names (java.lang.Object) and returns a set of descriptors (Ljava/lang/Object;) | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 250 |   CompilerDriver::DescriptorSet* ReadImageClassesFromFile(const char* image_classes_filename) { | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 251 |     UniquePtr<std::ifstream> image_classes_file(new std::ifstream(image_classes_filename, | 
 | 252 |                                                                   std::ifstream::in)); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 253 |     if (image_classes_file.get() == NULL) { | 
 | 254 |       LOG(ERROR) << "Failed to open image classes file " << image_classes_filename; | 
 | 255 |       return NULL; | 
 | 256 |     } | 
 | 257 |     UniquePtr<CompilerDriver::DescriptorSet> result(ReadImageClasses(*image_classes_file.get())); | 
 | 258 |     image_classes_file->close(); | 
 | 259 |     return result.release(); | 
 | 260 |   } | 
 | 261 |  | 
 | 262 |   CompilerDriver::DescriptorSet* ReadImageClasses(std::istream& image_classes_stream) { | 
 | 263 |     UniquePtr<CompilerDriver::DescriptorSet> image_classes(new CompilerDriver::DescriptorSet); | 
 | 264 |     while (image_classes_stream.good()) { | 
 | 265 |       std::string dot; | 
 | 266 |       std::getline(image_classes_stream, dot); | 
 | 267 |       if (StartsWith(dot, "#") || dot.empty()) { | 
 | 268 |         continue; | 
 | 269 |       } | 
 | 270 |       std::string descriptor(DotToDescriptor(dot.c_str())); | 
 | 271 |       image_classes->insert(descriptor); | 
 | 272 |     } | 
 | 273 |     return image_classes.release(); | 
 | 274 |   } | 
 | 275 |  | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 276 |   // Reads the class names (java.lang.Object) and returns a set of descriptors (Ljava/lang/Object;) | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 277 |   CompilerDriver::DescriptorSet* ReadImageClassesFromZip(const char* zip_filename, | 
 | 278 |                                                          const char* image_classes_filename, | 
 | 279 |                                                          std::string* error_msg) { | 
 | 280 |     UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(zip_filename, error_msg)); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 281 |     if (zip_archive.get() == NULL) { | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 282 |       return NULL; | 
 | 283 |     } | 
| Narayan Kamath | 92572be | 2013-11-28 14:06:24 +0000 | [diff] [blame] | 284 |     UniquePtr<ZipEntry> zip_entry(zip_archive->Find(image_classes_filename, error_msg)); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 285 |     if (zip_entry.get() == NULL) { | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 286 |       *error_msg = StringPrintf("Failed to find '%s' within '%s': %s", image_classes_filename, | 
 | 287 |                                 zip_filename, error_msg->c_str()); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 288 |       return NULL; | 
 | 289 |     } | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 290 |     UniquePtr<MemMap> image_classes_file(zip_entry->ExtractToMemMap(image_classes_filename, | 
 | 291 |                                                                     error_msg)); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 292 |     if (image_classes_file.get() == NULL) { | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 293 |       *error_msg = StringPrintf("Failed to extract '%s' from '%s': %s", image_classes_filename, | 
 | 294 |                                 zip_filename, error_msg->c_str()); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 295 |       return NULL; | 
 | 296 |     } | 
 | 297 |     const std::string image_classes_string(reinterpret_cast<char*>(image_classes_file->Begin()), | 
 | 298 |                                            image_classes_file->Size()); | 
 | 299 |     std::istringstream image_classes_stream(image_classes_string); | 
 | 300 |     return ReadImageClasses(image_classes_stream); | 
 | 301 |   } | 
 | 302 |  | 
 | 303 |   const CompilerDriver* CreateOatFile(const std::string& boot_image_option, | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 304 |                                       const std::string& android_root, | 
 | 305 |                                       bool is_host, | 
 | 306 |                                       const std::vector<const DexFile*>& dex_files, | 
 | 307 |                                       File* oat_file, | 
 | 308 |                                       const std::string& bitcode_filename, | 
 | 309 |                                       bool image, | 
 | 310 |                                       UniquePtr<CompilerDriver::DescriptorSet>& image_classes, | 
 | 311 |                                       bool dump_stats, | 
| Nicolas Geoffray | ea3fa0b | 2014-02-10 11:59:41 +0000 | [diff] [blame] | 312 |                                       bool dump_passes, | 
 | 313 |                                       TimingLogger& timings, | 
 | 314 |                                       CumulativeLogger& compiler_phases_timings) { | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 315 |     // SirtRef and ClassLoader creation needs to come after Runtime::Create | 
 | 316 |     jobject class_loader = NULL; | 
| Ian Rogers | 3f3d22c | 2013-08-27 18:11:09 -0700 | [diff] [blame] | 317 |     Thread* self = Thread::Current(); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 318 |     if (!boot_image_option.empty()) { | 
 | 319 |       ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); | 
 | 320 |       std::vector<const DexFile*> class_path_files(dex_files); | 
 | 321 |       OpenClassPathFiles(runtime_->GetClassPathString(), class_path_files); | 
| Ian Rogers | 3f3d22c | 2013-08-27 18:11:09 -0700 | [diff] [blame] | 322 |       ScopedObjectAccess soa(self); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 323 |       for (size_t i = 0; i < class_path_files.size(); i++) { | 
 | 324 |         class_linker->RegisterDexFile(*class_path_files[i]); | 
 | 325 |       } | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 326 |       soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader); | 
 | 327 |       ScopedLocalRef<jobject> class_loader_local(soa.Env(), | 
 | 328 |           soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader)); | 
 | 329 |       class_loader = soa.Env()->NewGlobalRef(class_loader_local.get()); | 
 | 330 |       Runtime::Current()->SetCompileTimeClassPath(class_loader, class_path_files); | 
 | 331 |     } | 
 | 332 |  | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 333 |     UniquePtr<CompilerDriver> driver(new CompilerDriver(compiler_options_, | 
 | 334 |                                                         verification_results_, | 
 | 335 |                                                         method_inliner_map_, | 
| Vladimir Marko | 2b5eaa2 | 2013-12-13 13:59:30 +0000 | [diff] [blame] | 336 |                                                         compiler_backend_, | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 337 |                                                         instruction_set_, | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 338 |                                                         instruction_set_features_, | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 339 |                                                         image, | 
 | 340 |                                                         image_classes.release(), | 
 | 341 |                                                         thread_count_, | 
| Nicolas Geoffray | ea3fa0b | 2014-02-10 11:59:41 +0000 | [diff] [blame] | 342 |                                                         dump_stats, | 
 | 343 |                                                         dump_passes, | 
 | 344 |                                                         &compiler_phases_timings)); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 345 |  | 
| Ian Rogers | 3d50407 | 2014-03-01 09:16:49 -0800 | [diff] [blame] | 346 |     driver->GetCompilerBackend()->SetBitcodeFileName(*driver.get(), bitcode_filename); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 347 |  | 
| Ian Rogers | 3d50407 | 2014-03-01 09:16:49 -0800 | [diff] [blame] | 348 |     driver->CompileAll(class_loader, dex_files, &timings); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 349 |  | 
| Anwar Ghuloum | 6f28d91 | 2013-07-24 15:02:53 -0700 | [diff] [blame] | 350 |     timings.NewSplit("dex2oat OatWriter"); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 351 |     std::string image_file_location; | 
 | 352 |     uint32_t image_file_location_oat_checksum = 0; | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 353 |     uintptr_t image_file_location_oat_data_begin = 0; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 354 |     if (!driver->IsImage()) { | 
| Ian Rogers | ca368cb | 2013-11-15 15:52:08 -0800 | [diff] [blame] | 355 |       TimingLogger::ScopedSplit split("Loading image checksum", &timings); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 356 |       gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetImageSpace(); | 
 | 357 |       image_file_location_oat_checksum = image_space->GetImageHeader().GetOatChecksum(); | 
 | 358 |       image_file_location_oat_data_begin = | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 359 |           reinterpret_cast<uintptr_t>(image_space->GetImageHeader().GetOatDataBegin()); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 360 |       image_file_location = image_space->GetImageFilename(); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 361 |     } | 
 | 362 |  | 
| Brian Carlstrom | c50d8e1 | 2013-07-23 22:35:16 -0700 | [diff] [blame] | 363 |     OatWriter oat_writer(dex_files, | 
 | 364 |                          image_file_location_oat_checksum, | 
 | 365 |                          image_file_location_oat_data_begin, | 
 | 366 |                          image_file_location, | 
| Ian Rogers | ca368cb | 2013-11-15 15:52:08 -0800 | [diff] [blame] | 367 |                          driver.get(), | 
 | 368 |                          &timings); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 369 |  | 
| Ian Rogers | ca368cb | 2013-11-15 15:52:08 -0800 | [diff] [blame] | 370 |     TimingLogger::ScopedSplit split("Writing ELF", &timings); | 
| Ian Rogers | 3d50407 | 2014-03-01 09:16:49 -0800 | [diff] [blame] | 371 |     if (!driver->WriteElf(android_root, is_host, dex_files, &oat_writer, oat_file)) { | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 372 |       LOG(ERROR) << "Failed to write ELF file " << oat_file->GetPath(); | 
 | 373 |       return NULL; | 
 | 374 |     } | 
 | 375 |  | 
 | 376 |     return driver.release(); | 
 | 377 |   } | 
 | 378 |  | 
 | 379 |   bool CreateImageFile(const std::string& image_filename, | 
 | 380 |                        uintptr_t image_base, | 
 | 381 |                        const std::string& oat_filename, | 
 | 382 |                        const std::string& oat_location, | 
 | 383 |                        const CompilerDriver& compiler) | 
 | 384 |       LOCKS_EXCLUDED(Locks::mutator_lock_) { | 
 | 385 |     uintptr_t oat_data_begin; | 
 | 386 |     { | 
 | 387 |       // ImageWriter is scoped so it can free memory before doing FixupElf | 
 | 388 |       ImageWriter image_writer(compiler); | 
 | 389 |       if (!image_writer.Write(image_filename, image_base, oat_filename, oat_location)) { | 
 | 390 |         LOG(ERROR) << "Failed to create image file " << image_filename; | 
 | 391 |         return false; | 
 | 392 |       } | 
 | 393 |       oat_data_begin = image_writer.GetOatDataBegin(); | 
 | 394 |     } | 
 | 395 |  | 
| Brian Carlstrom | 7571e8b | 2013-08-12 17:04:14 -0700 | [diff] [blame] | 396 |     UniquePtr<File> oat_file(OS::OpenFileReadWrite(oat_filename.c_str())); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 397 |     if (oat_file.get() == NULL) { | 
 | 398 |       PLOG(ERROR) << "Failed to open ELF file: " << oat_filename; | 
 | 399 |       return false; | 
 | 400 |     } | 
 | 401 |     if (!ElfFixup::Fixup(oat_file.get(), oat_data_begin)) { | 
 | 402 |       LOG(ERROR) << "Failed to fixup ELF file " << oat_file->GetPath(); | 
 | 403 |       return false; | 
 | 404 |     } | 
 | 405 |     return true; | 
 | 406 |   } | 
 | 407 |  | 
 | 408 |  private: | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 409 |   explicit Dex2Oat(const CompilerOptions* compiler_options, | 
 | 410 |                    CompilerBackend::Kind compiler_backend, | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 411 |                    InstructionSet instruction_set, | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 412 |                    InstructionSetFeatures instruction_set_features, | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 413 |                    VerificationResults* verification_results, | 
 | 414 |                    DexFileToMethodInlinerMap* method_inliner_map, | 
| Brian Carlstrom | 0177fe2 | 2013-07-21 12:21:36 -0700 | [diff] [blame] | 415 |                    size_t thread_count) | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 416 |       : compiler_options_(compiler_options), | 
 | 417 |         compiler_backend_(compiler_backend), | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 418 |         instruction_set_(instruction_set), | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 419 |         instruction_set_features_(instruction_set_features), | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 420 |         verification_results_(verification_results), | 
 | 421 |         method_inliner_map_(method_inliner_map), | 
| Vladimir Marko | 2b5eaa2 | 2013-12-13 13:59:30 +0000 | [diff] [blame] | 422 |         runtime_(nullptr), | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 423 |         thread_count_(thread_count), | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 424 |         start_ns_(NanoTime()) { | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 425 |     CHECK(compiler_options != nullptr); | 
 | 426 |     CHECK(verification_results != nullptr); | 
 | 427 |     CHECK(method_inliner_map != nullptr); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 428 |   } | 
 | 429 |  | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 430 |   bool CreateRuntime(const Runtime::Options& runtime_options, InstructionSet instruction_set) | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 431 |       SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_) { | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 432 |     if (!Runtime::Create(runtime_options, false)) { | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 433 |       LOG(ERROR) << "Failed to create runtime"; | 
 | 434 |       return false; | 
 | 435 |     } | 
 | 436 |     Runtime* runtime = Runtime::Current(); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 437 |     for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { | 
 | 438 |       Runtime::CalleeSaveType type = Runtime::CalleeSaveType(i); | 
 | 439 |       if (!runtime->HasCalleeSaveMethod(type)) { | 
 | 440 |         runtime->SetCalleeSaveMethod(runtime->CreateCalleeSaveMethod(instruction_set, type), type); | 
 | 441 |       } | 
 | 442 |     } | 
 | 443 |     runtime->GetClassLinker()->FixupDexCaches(runtime->GetResolutionMethod()); | 
| Vladimir Marko | 2b5eaa2 | 2013-12-13 13:59:30 +0000 | [diff] [blame] | 444 |     runtime_ = runtime; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 445 |     return true; | 
 | 446 |   } | 
 | 447 |  | 
 | 448 |   // Appends to dex_files any elements of class_path that it doesn't already | 
 | 449 |   // contain. This will open those dex files as necessary. | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 450 |   static void OpenClassPathFiles(const std::string& class_path, | 
 | 451 |                                  std::vector<const DexFile*>& dex_files) { | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 452 |     std::vector<std::string> parsed; | 
 | 453 |     Split(class_path, ':', parsed); | 
 | 454 |     // Take Locks::mutator_lock_ so that lock ordering on the ClassLinker::dex_lock_ is maintained. | 
 | 455 |     ScopedObjectAccess soa(Thread::Current()); | 
 | 456 |     for (size_t i = 0; i < parsed.size(); ++i) { | 
 | 457 |       if (DexFilesContains(dex_files, parsed[i])) { | 
 | 458 |         continue; | 
 | 459 |       } | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 460 |       std::string error_msg; | 
 | 461 |       const DexFile* dex_file = DexFile::Open(parsed[i].c_str(), parsed[i].c_str(), &error_msg); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 462 |       if (dex_file == NULL) { | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 463 |         LOG(WARNING) << "Failed to open dex file '" << parsed[i] << "': " << error_msg; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 464 |       } else { | 
 | 465 |         dex_files.push_back(dex_file); | 
 | 466 |       } | 
 | 467 |     } | 
 | 468 |   } | 
 | 469 |  | 
 | 470 |   // Returns true if dex_files has a dex with the named location. | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 471 |   static bool DexFilesContains(const std::vector<const DexFile*>& dex_files, | 
 | 472 |                                const std::string& location) { | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 473 |     for (size_t i = 0; i < dex_files.size(); ++i) { | 
 | 474 |       if (dex_files[i]->GetLocation() == location) { | 
 | 475 |         return true; | 
 | 476 |       } | 
 | 477 |     } | 
 | 478 |     return false; | 
 | 479 |   } | 
 | 480 |  | 
| Brian Carlstrom | ae7083d | 2014-02-24 21:56:02 -0800 | [diff] [blame] | 481 |   const CompilerOptions* const compiler_options_; | 
| Nicolas Geoffray | f5df897 | 2014-02-14 18:37:08 +0000 | [diff] [blame] | 482 |   const CompilerBackend::Kind compiler_backend_; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 483 |  | 
 | 484 |   const InstructionSet instruction_set_; | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 485 |   const InstructionSetFeatures instruction_set_features_; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 486 |  | 
| Brian Carlstrom | ae7083d | 2014-02-24 21:56:02 -0800 | [diff] [blame] | 487 |   VerificationResults* const verification_results_; | 
 | 488 |   DexFileToMethodInlinerMap* const method_inliner_map_; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 489 |   Runtime* runtime_; | 
 | 490 |   size_t thread_count_; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 491 |   uint64_t start_ns_; | 
 | 492 |  | 
 | 493 |   DISALLOW_IMPLICIT_CONSTRUCTORS(Dex2Oat); | 
 | 494 | }; | 
 | 495 |  | 
 | 496 | static bool ParseInt(const char* in, int* out) { | 
 | 497 |   char* end; | 
 | 498 |   int result = strtol(in, &end, 10); | 
 | 499 |   if (in == end || *end != '\0') { | 
 | 500 |     return false; | 
 | 501 |   } | 
 | 502 |   *out = result; | 
 | 503 |   return true; | 
 | 504 | } | 
 | 505 |  | 
| Brian Carlstrom | 3cf59d5 | 2013-11-10 21:04:10 -0800 | [diff] [blame] | 506 | static size_t OpenDexFiles(const std::vector<const char*>& dex_filenames, | 
 | 507 |                            const std::vector<const char*>& dex_locations, | 
 | 508 |                            std::vector<const DexFile*>& dex_files) { | 
 | 509 |   size_t failure_count = 0; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 510 |   for (size_t i = 0; i < dex_filenames.size(); i++) { | 
 | 511 |     const char* dex_filename = dex_filenames[i]; | 
 | 512 |     const char* dex_location = dex_locations[i]; | 
| Ian Rogers | 740a11d | 2014-01-14 10:11:25 -0800 | [diff] [blame] | 513 |     ATRACE_BEGIN(StringPrintf("Opening dex file '%s'", dex_filenames[i]).c_str()); | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 514 |     std::string error_msg; | 
| Brian Carlstrom | d5aba59 | 2013-11-12 01:52:44 -0800 | [diff] [blame] | 515 |     if (!OS::FileExists(dex_filename)) { | 
 | 516 |       LOG(WARNING) << "Skipping non-existent dex file '" << dex_filename << "'"; | 
 | 517 |       continue; | 
 | 518 |     } | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 519 |     const DexFile* dex_file = DexFile::Open(dex_filename, dex_location, &error_msg); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 520 |     if (dex_file == NULL) { | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 521 |       LOG(WARNING) << "Failed to open .dex from file '" << dex_filename << "': " << error_msg; | 
| Brian Carlstrom | 3cf59d5 | 2013-11-10 21:04:10 -0800 | [diff] [blame] | 522 |       ++failure_count; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 523 |     } else { | 
 | 524 |       dex_files.push_back(dex_file); | 
 | 525 |     } | 
| Ian Rogers | 740a11d | 2014-01-14 10:11:25 -0800 | [diff] [blame] | 526 |     ATRACE_END(); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 527 |   } | 
| Brian Carlstrom | 3cf59d5 | 2013-11-10 21:04:10 -0800 | [diff] [blame] | 528 |   return failure_count; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 529 | } | 
 | 530 |  | 
 | 531 | // The primary goal of the watchdog is to prevent stuck build servers | 
 | 532 | // during development when fatal aborts lead to a cascade of failures | 
 | 533 | // that result in a deadlock. | 
 | 534 | class WatchDog { | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 535 | // WatchDog defines its own CHECK_PTHREAD_CALL to avoid using Log which uses locks | 
 | 536 | #undef CHECK_PTHREAD_CALL | 
 | 537 | #define CHECK_WATCH_DOG_PTHREAD_CALL(call, args, what) \ | 
 | 538 |   do { \ | 
 | 539 |     int rc = call args; \ | 
 | 540 |     if (rc != 0) { \ | 
 | 541 |       errno = rc; \ | 
 | 542 |       std::string message(# call); \ | 
 | 543 |       message += " failed for "; \ | 
 | 544 |       message += reason; \ | 
 | 545 |       Fatal(message); \ | 
 | 546 |     } \ | 
 | 547 |   } while (false) | 
 | 548 |  | 
 | 549 |  public: | 
| Brian Carlstrom | 93ba893 | 2013-07-17 21:31:49 -0700 | [diff] [blame] | 550 |   explicit WatchDog(bool is_watch_dog_enabled) { | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 551 |     is_watch_dog_enabled_ = is_watch_dog_enabled; | 
 | 552 |     if (!is_watch_dog_enabled_) { | 
 | 553 |       return; | 
 | 554 |     } | 
 | 555 |     shutting_down_ = false; | 
 | 556 |     const char* reason = "dex2oat watch dog thread startup"; | 
 | 557 |     CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_init, (&mutex_, NULL), reason); | 
 | 558 |     CHECK_WATCH_DOG_PTHREAD_CALL(pthread_cond_init, (&cond_, NULL), reason); | 
 | 559 |     CHECK_WATCH_DOG_PTHREAD_CALL(pthread_attr_init, (&attr_), reason); | 
 | 560 |     CHECK_WATCH_DOG_PTHREAD_CALL(pthread_create, (&pthread_, &attr_, &CallBack, this), reason); | 
 | 561 |     CHECK_WATCH_DOG_PTHREAD_CALL(pthread_attr_destroy, (&attr_), reason); | 
 | 562 |   } | 
 | 563 |   ~WatchDog() { | 
 | 564 |     if (!is_watch_dog_enabled_) { | 
 | 565 |       return; | 
 | 566 |     } | 
 | 567 |     const char* reason = "dex2oat watch dog thread shutdown"; | 
 | 568 |     CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_lock, (&mutex_), reason); | 
 | 569 |     shutting_down_ = true; | 
 | 570 |     CHECK_WATCH_DOG_PTHREAD_CALL(pthread_cond_signal, (&cond_), reason); | 
 | 571 |     CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_unlock, (&mutex_), reason); | 
 | 572 |  | 
 | 573 |     CHECK_WATCH_DOG_PTHREAD_CALL(pthread_join, (pthread_, NULL), reason); | 
 | 574 |  | 
 | 575 |     CHECK_WATCH_DOG_PTHREAD_CALL(pthread_cond_destroy, (&cond_), reason); | 
 | 576 |     CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_destroy, (&mutex_), reason); | 
 | 577 |   } | 
 | 578 |  | 
 | 579 |  private: | 
 | 580 |   static void* CallBack(void* arg) { | 
 | 581 |     WatchDog* self = reinterpret_cast<WatchDog*>(arg); | 
 | 582 |     ::art::SetThreadName("dex2oat watch dog"); | 
 | 583 |     self->Wait(); | 
 | 584 |     return NULL; | 
 | 585 |   } | 
 | 586 |  | 
 | 587 |   static void Message(char severity, const std::string& message) { | 
 | 588 |     // TODO: Remove when we switch to LOG when we can guarantee it won't prevent shutdown in error | 
 | 589 |     //       cases. | 
 | 590 |     fprintf(stderr, "dex2oat%s %c %d %d %s\n", | 
 | 591 |             kIsDebugBuild ? "d" : "", | 
 | 592 |             severity, | 
 | 593 |             getpid(), | 
 | 594 |             GetTid(), | 
 | 595 |             message.c_str()); | 
 | 596 |   } | 
 | 597 |  | 
 | 598 |   static void Warn(const std::string& message) { | 
 | 599 |     Message('W', message); | 
 | 600 |   } | 
 | 601 |  | 
 | 602 |   static void Fatal(const std::string& message) { | 
 | 603 |     Message('F', message); | 
 | 604 |     exit(1); | 
 | 605 |   } | 
 | 606 |  | 
 | 607 |   void Wait() { | 
 | 608 |     bool warning = true; | 
 | 609 |     CHECK_GT(kWatchDogTimeoutSeconds, kWatchDogWarningSeconds); | 
 | 610 |     // TODO: tune the multiplier for GC verification, the following is just to make the timeout | 
 | 611 |     //       large. | 
| Mathieu Chartier | 4e30541 | 2014-02-19 10:54:44 -0800 | [diff] [blame] | 612 |     int64_t multiplier = kVerifyObjectSupport > kVerifyObjectModeFast ? 100 : 1; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 613 |     timespec warning_ts; | 
 | 614 |     InitTimeSpec(true, CLOCK_REALTIME, multiplier * kWatchDogWarningSeconds * 1000, 0, &warning_ts); | 
 | 615 |     timespec timeout_ts; | 
 | 616 |     InitTimeSpec(true, CLOCK_REALTIME, multiplier * kWatchDogTimeoutSeconds * 1000, 0, &timeout_ts); | 
 | 617 |     const char* reason = "dex2oat watch dog thread waiting"; | 
 | 618 |     CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_lock, (&mutex_), reason); | 
 | 619 |     while (!shutting_down_) { | 
 | 620 |       int rc = TEMP_FAILURE_RETRY(pthread_cond_timedwait(&cond_, &mutex_, | 
 | 621 |                                                          warning ? &warning_ts | 
 | 622 |                                                                  : &timeout_ts)); | 
 | 623 |       if (rc == ETIMEDOUT) { | 
 | 624 |         std::string message(StringPrintf("dex2oat did not finish after %d seconds", | 
 | 625 |                                          warning ? kWatchDogWarningSeconds | 
 | 626 |                                                  : kWatchDogTimeoutSeconds)); | 
 | 627 |         if (warning) { | 
 | 628 |           Warn(message.c_str()); | 
 | 629 |           warning = false; | 
 | 630 |         } else { | 
 | 631 |           Fatal(message.c_str()); | 
 | 632 |         } | 
 | 633 |       } else if (rc != 0) { | 
 | 634 |         std::string message(StringPrintf("pthread_cond_timedwait failed: %s", | 
 | 635 |                                          strerror(errno))); | 
 | 636 |         Fatal(message.c_str()); | 
 | 637 |       } | 
 | 638 |     } | 
 | 639 |     CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_unlock, (&mutex_), reason); | 
 | 640 |   } | 
 | 641 |  | 
 | 642 |   // When setting timeouts, keep in mind that the build server may not be as fast as your desktop. | 
 | 643 | #if ART_USE_PORTABLE_COMPILER | 
 | 644 |   static const unsigned int kWatchDogWarningSeconds =  2 * 60;  // 2 minutes. | 
 | 645 |   static const unsigned int kWatchDogTimeoutSeconds = 30 * 60;  // 25 minutes + buffer. | 
 | 646 | #else | 
 | 647 |   static const unsigned int kWatchDogWarningSeconds =  1 * 60;  // 1 minute. | 
 | 648 |   static const unsigned int kWatchDogTimeoutSeconds =  6 * 60;  // 5 minutes + buffer. | 
 | 649 | #endif | 
 | 650 |  | 
 | 651 |   bool is_watch_dog_enabled_; | 
 | 652 |   bool shutting_down_; | 
 | 653 |   // TODO: Switch to Mutex when we can guarantee it won't prevent shutdown in error cases. | 
 | 654 |   pthread_mutex_t mutex_; | 
 | 655 |   pthread_cond_t cond_; | 
 | 656 |   pthread_attr_t attr_; | 
 | 657 |   pthread_t pthread_; | 
 | 658 | }; | 
 | 659 | const unsigned int WatchDog::kWatchDogWarningSeconds; | 
 | 660 | const unsigned int WatchDog::kWatchDogTimeoutSeconds; | 
 | 661 |  | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 662 | // Given a set of instruction features from the build, parse it.  The | 
 | 663 | // input 'str' is a comma separated list of feature names.  Parse it and | 
 | 664 | // return the InstructionSetFeatures object. | 
 | 665 | static InstructionSetFeatures ParseFeatureList(std::string str) { | 
 | 666 |   InstructionSetFeatures result; | 
 | 667 |   typedef std::vector<std::string> FeatureList; | 
 | 668 |   FeatureList features; | 
 | 669 |   Split(str, ',', features); | 
 | 670 |   for (FeatureList::iterator i = features.begin(); i != features.end(); i++) { | 
 | 671 |     std::string feature = Trim(*i); | 
 | 672 |     if (feature == "default") { | 
 | 673 |       // Nothing to do. | 
 | 674 |     } else if (feature == "div") { | 
 | 675 |       // Supports divide instruction. | 
 | 676 |        result.SetHasDivideInstruction(true); | 
 | 677 |     } else if (feature == "nodiv") { | 
 | 678 |       // Turn off support for divide instruction. | 
 | 679 |       result.SetHasDivideInstruction(false); | 
 | 680 |     } else { | 
 | 681 |       Usage("Unknown instruction set feature: '%s'", feature.c_str()); | 
 | 682 |     } | 
 | 683 |   } | 
 | 684 |   // others... | 
 | 685 |   return result; | 
 | 686 | } | 
 | 687 |  | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 688 | static int dex2oat(int argc, char** argv) { | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 689 |   original_argc = argc; | 
 | 690 |   original_argv = argv; | 
 | 691 |  | 
| Ian Rogers | 5fe9af7 | 2013-11-14 00:17:20 -0800 | [diff] [blame] | 692 |   TimingLogger timings("compiler", false, false); | 
| Nicolas Geoffray | ea3fa0b | 2014-02-10 11:59:41 +0000 | [diff] [blame] | 693 |   CumulativeLogger compiler_phases_timings("compilation times"); | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 694 |  | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 695 |   InitLogging(argv); | 
 | 696 |  | 
 | 697 |   // Skip over argv[0]. | 
 | 698 |   argv++; | 
 | 699 |   argc--; | 
 | 700 |  | 
 | 701 |   if (argc == 0) { | 
| Brian Carlstrom | e0948e1 | 2013-08-29 09:36:15 -0700 | [diff] [blame] | 702 |     Usage("No arguments specified"); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 703 |   } | 
 | 704 |  | 
 | 705 |   std::vector<const char*> dex_filenames; | 
 | 706 |   std::vector<const char*> dex_locations; | 
 | 707 |   int zip_fd = -1; | 
 | 708 |   std::string zip_location; | 
 | 709 |   std::string oat_filename; | 
 | 710 |   std::string oat_symbols; | 
 | 711 |   std::string oat_location; | 
 | 712 |   int oat_fd = -1; | 
 | 713 |   std::string bitcode_filename; | 
 | 714 |   const char* image_classes_zip_filename = NULL; | 
 | 715 |   const char* image_classes_filename = NULL; | 
 | 716 |   std::string image_filename; | 
 | 717 |   std::string boot_image_filename; | 
 | 718 |   uintptr_t image_base = 0; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 719 |   std::string android_root; | 
 | 720 |   std::vector<const char*> runtime_args; | 
 | 721 |   int thread_count = sysconf(_SC_NPROCESSORS_CONF); | 
| Nicolas Geoffray | f5df897 | 2014-02-14 18:37:08 +0000 | [diff] [blame] | 722 |   CompilerBackend::Kind compiler_backend = kUsePortableCompiler | 
 | 723 |       ? CompilerBackend::kPortable | 
 | 724 |       : CompilerBackend::kQuick; | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 725 |   const char* compiler_filter_string = NULL; | 
 | 726 |   int huge_method_threshold = CompilerOptions::kDefaultHugeMethodThreshold; | 
 | 727 |   int large_method_threshold = CompilerOptions::kDefaultLargeMethodThreshold; | 
 | 728 |   int small_method_threshold = CompilerOptions::kDefaultSmallMethodThreshold; | 
 | 729 |   int tiny_method_threshold = CompilerOptions::kDefaultTinyMethodThreshold; | 
 | 730 |   int num_dex_methods_threshold = CompilerOptions::kDefaultNumDexMethodsThreshold; | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 731 |  | 
| Brian Carlstrom | 1bd2ceb | 2013-11-06 00:29:48 -0800 | [diff] [blame] | 732 |   // Take the default set of instruction features from the build. | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 733 |   InstructionSetFeatures instruction_set_features = | 
| Brian Carlstrom | 1bd2ceb | 2013-11-06 00:29:48 -0800 | [diff] [blame] | 734 |       ParseFeatureList(STRINGIFY(ART_DEFAULT_INSTRUCTION_SET_FEATURES)); | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 735 |  | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 736 | #if defined(__arm__) | 
 | 737 |   InstructionSet instruction_set = kThumb2; | 
 | 738 | #elif defined(__i386__) | 
 | 739 |   InstructionSet instruction_set = kX86; | 
 | 740 | #elif defined(__mips__) | 
 | 741 |   InstructionSet instruction_set = kMips; | 
 | 742 | #else | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 743 |   InstructionSet instruction_set = kNone; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 744 | #endif | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 745 |  | 
 | 746 |  | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 747 |   bool is_host = false; | 
| Ian Rogers | e732ef1 | 2013-10-09 15:22:24 -0700 | [diff] [blame] | 748 |   bool dump_stats = false; | 
| Ian Rogers | 4639860 | 2013-08-20 07:50:36 -0700 | [diff] [blame] | 749 |   bool dump_timing = false; | 
| Nicolas Geoffray | ea3fa0b | 2014-02-10 11:59:41 +0000 | [diff] [blame] | 750 |   bool dump_passes = false; | 
| Ian Rogers | 4639860 | 2013-08-20 07:50:36 -0700 | [diff] [blame] | 751 |   bool dump_slow_timing = kIsDebugBuild; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 752 |   bool watch_dog_enabled = !kIsTargetBuild; | 
| Mark Mendell | ae9fd93 | 2014-02-10 16:14:35 -0800 | [diff] [blame] | 753 |   bool generate_gdb_information = kIsDebugBuild; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 754 |  | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 755 |   for (int i = 0; i < argc; i++) { | 
 | 756 |     const StringPiece option(argv[i]); | 
 | 757 |     bool log_options = false; | 
 | 758 |     if (log_options) { | 
 | 759 |       LOG(INFO) << "dex2oat: option[" << i << "]=" << argv[i]; | 
 | 760 |     } | 
 | 761 |     if (option.starts_with("--dex-file=")) { | 
 | 762 |       dex_filenames.push_back(option.substr(strlen("--dex-file=")).data()); | 
 | 763 |     } else if (option.starts_with("--dex-location=")) { | 
 | 764 |       dex_locations.push_back(option.substr(strlen("--dex-location=")).data()); | 
 | 765 |     } else if (option.starts_with("--zip-fd=")) { | 
 | 766 |       const char* zip_fd_str = option.substr(strlen("--zip-fd=")).data(); | 
 | 767 |       if (!ParseInt(zip_fd_str, &zip_fd)) { | 
| Brian Carlstrom | e0948e1 | 2013-08-29 09:36:15 -0700 | [diff] [blame] | 768 |         Usage("Failed to parse --zip-fd argument '%s' as an integer", zip_fd_str); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 769 |       } | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 770 |       if (zip_fd < 0) { | 
 | 771 |         Usage("--zip-fd passed a negative value %d", zip_fd); | 
 | 772 |       } | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 773 |     } else if (option.starts_with("--zip-location=")) { | 
 | 774 |       zip_location = option.substr(strlen("--zip-location=")).data(); | 
 | 775 |     } else if (option.starts_with("--oat-file=")) { | 
 | 776 |       oat_filename = option.substr(strlen("--oat-file=")).data(); | 
 | 777 |     } else if (option.starts_with("--oat-symbols=")) { | 
 | 778 |       oat_symbols = option.substr(strlen("--oat-symbols=")).data(); | 
 | 779 |     } else if (option.starts_with("--oat-fd=")) { | 
 | 780 |       const char* oat_fd_str = option.substr(strlen("--oat-fd=")).data(); | 
 | 781 |       if (!ParseInt(oat_fd_str, &oat_fd)) { | 
| Brian Carlstrom | e0948e1 | 2013-08-29 09:36:15 -0700 | [diff] [blame] | 782 |         Usage("Failed to parse --oat-fd argument '%s' as an integer", oat_fd_str); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 783 |       } | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 784 |       if (oat_fd < 0) { | 
 | 785 |         Usage("--oat-fd passed a negative value %d", oat_fd); | 
 | 786 |       } | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 787 |     } else if (option == "--watch-dog") { | 
 | 788 |       watch_dog_enabled = true; | 
 | 789 |     } else if (option == "--no-watch-dog") { | 
 | 790 |       watch_dog_enabled = false; | 
| Mark Mendell | ae9fd93 | 2014-02-10 16:14:35 -0800 | [diff] [blame] | 791 |     } else if (option == "--gen-gdb-info") { | 
 | 792 |       generate_gdb_information = true; | 
 | 793 |     } else if (option == "--no-gen-gdb-info") { | 
 | 794 |       generate_gdb_information = false; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 795 |     } else if (option.starts_with("-j")) { | 
 | 796 |       const char* thread_count_str = option.substr(strlen("-j")).data(); | 
 | 797 |       if (!ParseInt(thread_count_str, &thread_count)) { | 
| Brian Carlstrom | e0948e1 | 2013-08-29 09:36:15 -0700 | [diff] [blame] | 798 |         Usage("Failed to parse -j argument '%s' as an integer", thread_count_str); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 799 |       } | 
 | 800 |     } else if (option.starts_with("--oat-location=")) { | 
 | 801 |       oat_location = option.substr(strlen("--oat-location=")).data(); | 
 | 802 |     } else if (option.starts_with("--bitcode=")) { | 
 | 803 |       bitcode_filename = option.substr(strlen("--bitcode=")).data(); | 
 | 804 |     } else if (option.starts_with("--image=")) { | 
 | 805 |       image_filename = option.substr(strlen("--image=")).data(); | 
 | 806 |     } else if (option.starts_with("--image-classes=")) { | 
 | 807 |       image_classes_filename = option.substr(strlen("--image-classes=")).data(); | 
 | 808 |     } else if (option.starts_with("--image-classes-zip=")) { | 
 | 809 |       image_classes_zip_filename = option.substr(strlen("--image-classes-zip=")).data(); | 
 | 810 |     } else if (option.starts_with("--base=")) { | 
 | 811 |       const char* image_base_str = option.substr(strlen("--base=")).data(); | 
 | 812 |       char* end; | 
 | 813 |       image_base = strtoul(image_base_str, &end, 16); | 
 | 814 |       if (end == image_base_str || *end != '\0') { | 
 | 815 |         Usage("Failed to parse hexadecimal value for option %s", option.data()); | 
 | 816 |       } | 
 | 817 |     } else if (option.starts_with("--boot-image=")) { | 
 | 818 |       boot_image_filename = option.substr(strlen("--boot-image=")).data(); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 819 |     } else if (option.starts_with("--android-root=")) { | 
 | 820 |       android_root = option.substr(strlen("--android-root=")).data(); | 
 | 821 |     } else if (option.starts_with("--instruction-set=")) { | 
 | 822 |       StringPiece instruction_set_str = option.substr(strlen("--instruction-set=")).data(); | 
 | 823 |       if (instruction_set_str == "arm") { | 
 | 824 |         instruction_set = kThumb2; | 
 | 825 |       } else if (instruction_set_str == "mips") { | 
 | 826 |         instruction_set = kMips; | 
 | 827 |       } else if (instruction_set_str == "x86") { | 
 | 828 |         instruction_set = kX86; | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 829 |       } else if (instruction_set_str == "x86_64") { | 
 | 830 |         instruction_set = kX86_64; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 831 |       } | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 832 |     } else if (option.starts_with("--instruction-set-features=")) { | 
 | 833 |       StringPiece str = option.substr(strlen("--instruction-set-features=")).data(); | 
 | 834 |       instruction_set_features = ParseFeatureList(str.as_string()); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 835 |     } else if (option.starts_with("--compiler-backend=")) { | 
 | 836 |       StringPiece backend_str = option.substr(strlen("--compiler-backend=")).data(); | 
 | 837 |       if (backend_str == "Quick") { | 
| Nicolas Geoffray | f5df897 | 2014-02-14 18:37:08 +0000 | [diff] [blame] | 838 |         compiler_backend = CompilerBackend::kQuick; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 839 |       } else if (backend_str == "Portable") { | 
| Nicolas Geoffray | f5df897 | 2014-02-14 18:37:08 +0000 | [diff] [blame] | 840 |         compiler_backend = CompilerBackend::kPortable; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 841 |       } | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 842 |     } else if (option.starts_with("--compiler-filter=")) { | 
 | 843 |       compiler_filter_string = option.substr(strlen("--compiler-filter=")).data(); | 
 | 844 |     } else if (option.starts_with("--huge-method-max=")) { | 
 | 845 |       const char* threshold = option.substr(strlen("--huge-method-max=")).data(); | 
 | 846 |       if (!ParseInt(threshold, &huge_method_threshold)) { | 
 | 847 |         Usage("Failed to parse --huge-method-max '%s' as an integer", threshold); | 
 | 848 |       } | 
 | 849 |       if (huge_method_threshold < 0) { | 
 | 850 |         Usage("--huge-method-max passed a negative value %s", huge_method_threshold); | 
 | 851 |       } | 
 | 852 |     } else if (option.starts_with("--large-method-max=")) { | 
 | 853 |       const char* threshold = option.substr(strlen("--large-method-max=")).data(); | 
 | 854 |       if (!ParseInt(threshold, &large_method_threshold)) { | 
 | 855 |         Usage("Failed to parse --large-method-max '%s' as an integer", threshold); | 
 | 856 |       } | 
 | 857 |       if (large_method_threshold < 0) { | 
 | 858 |         Usage("--large-method-max passed a negative value %s", large_method_threshold); | 
 | 859 |       } | 
 | 860 |     } else if (option.starts_with("--small-method-max=")) { | 
 | 861 |       const char* threshold = option.substr(strlen("--small-method-max=")).data(); | 
 | 862 |       if (!ParseInt(threshold, &small_method_threshold)) { | 
 | 863 |         Usage("Failed to parse --small-method-max '%s' as an integer", threshold); | 
 | 864 |       } | 
 | 865 |       if (small_method_threshold < 0) { | 
 | 866 |         Usage("--small-method-max passed a negative value %s", small_method_threshold); | 
 | 867 |       } | 
 | 868 |     } else if (option.starts_with("--tiny-method-max=")) { | 
 | 869 |       const char* threshold = option.substr(strlen("--tiny-method-max=")).data(); | 
 | 870 |       if (!ParseInt(threshold, &tiny_method_threshold)) { | 
 | 871 |         Usage("Failed to parse --tiny-method-max '%s' as an integer", threshold); | 
 | 872 |       } | 
 | 873 |       if (tiny_method_threshold < 0) { | 
 | 874 |         Usage("--tiny-method-max passed a negative value %s", tiny_method_threshold); | 
 | 875 |       } | 
 | 876 |     } else if (option.starts_with("--num-dex-methods=")) { | 
 | 877 |       const char* threshold = option.substr(strlen("--num-dex-methods=")).data(); | 
 | 878 |       if (!ParseInt(threshold, &num_dex_methods_threshold)) { | 
 | 879 |         Usage("Failed to parse --num-dex-methods '%s' as an integer", threshold); | 
 | 880 |       } | 
 | 881 |       if (num_dex_methods_threshold < 0) { | 
 | 882 |         Usage("--num-dex-methods passed a negative value %s", num_dex_methods_threshold); | 
 | 883 |       } | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 884 |     } else if (option == "--host") { | 
 | 885 |       is_host = true; | 
 | 886 |     } else if (option == "--runtime-arg") { | 
 | 887 |       if (++i >= argc) { | 
 | 888 |         Usage("Missing required argument for --runtime-arg"); | 
 | 889 |       } | 
 | 890 |       if (log_options) { | 
 | 891 |         LOG(INFO) << "dex2oat: option[" << i << "]=" << argv[i]; | 
 | 892 |       } | 
 | 893 |       runtime_args.push_back(argv[i]); | 
| Ian Rogers | 4639860 | 2013-08-20 07:50:36 -0700 | [diff] [blame] | 894 |     } else if (option == "--dump-timing") { | 
 | 895 |       dump_timing = true; | 
| Nicolas Geoffray | ea3fa0b | 2014-02-10 11:59:41 +0000 | [diff] [blame] | 896 |     } else if (option == "--dump-passes") { | 
 | 897 |       dump_passes = true; | 
| Ian Rogers | e732ef1 | 2013-10-09 15:22:24 -0700 | [diff] [blame] | 898 |     } else if (option == "--dump-stats") { | 
 | 899 |       dump_stats = true; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 900 |     } else { | 
| Brian Carlstrom | e0948e1 | 2013-08-29 09:36:15 -0700 | [diff] [blame] | 901 |       Usage("Unknown argument %s", option.data()); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 902 |     } | 
 | 903 |   } | 
 | 904 |  | 
 | 905 |   if (oat_filename.empty() && oat_fd == -1) { | 
 | 906 |     Usage("Output must be supplied with either --oat-file or --oat-fd"); | 
 | 907 |   } | 
 | 908 |  | 
 | 909 |   if (!oat_filename.empty() && oat_fd != -1) { | 
 | 910 |     Usage("--oat-file should not be used with --oat-fd"); | 
 | 911 |   } | 
 | 912 |  | 
 | 913 |   if (!oat_symbols.empty() && oat_fd != -1) { | 
 | 914 |     Usage("--oat-symbols should not be used with --oat-fd"); | 
 | 915 |   } | 
 | 916 |  | 
 | 917 |   if (!oat_symbols.empty() && is_host) { | 
 | 918 |     Usage("--oat-symbols should not be used with --host"); | 
 | 919 |   } | 
 | 920 |  | 
 | 921 |   if (oat_fd != -1 && !image_filename.empty()) { | 
 | 922 |     Usage("--oat-fd should not be used with --image"); | 
 | 923 |   } | 
 | 924 |  | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 925 |   if (android_root.empty()) { | 
 | 926 |     const char* android_root_env_var = getenv("ANDROID_ROOT"); | 
 | 927 |     if (android_root_env_var == NULL) { | 
 | 928 |       Usage("--android-root unspecified and ANDROID_ROOT not set"); | 
 | 929 |     } | 
 | 930 |     android_root += android_root_env_var; | 
 | 931 |   } | 
 | 932 |  | 
 | 933 |   bool image = (!image_filename.empty()); | 
 | 934 |   if (!image && boot_image_filename.empty()) { | 
| Nicolas Geoffray | 9583fbc | 2014-02-28 15:21:07 +0000 | [diff] [blame] | 935 |     boot_image_filename += GetAndroidRoot(); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 936 |     boot_image_filename += "/framework/boot.art"; | 
 | 937 |   } | 
 | 938 |   std::string boot_image_option; | 
 | 939 |   if (!boot_image_filename.empty()) { | 
 | 940 |     boot_image_option += "-Ximage:"; | 
 | 941 |     boot_image_option += boot_image_filename; | 
 | 942 |   } | 
 | 943 |  | 
 | 944 |   if (image_classes_filename != NULL && !image) { | 
 | 945 |     Usage("--image-classes should only be used with --image"); | 
 | 946 |   } | 
 | 947 |  | 
 | 948 |   if (image_classes_filename != NULL && !boot_image_option.empty()) { | 
 | 949 |     Usage("--image-classes should not be used with --boot-image"); | 
 | 950 |   } | 
 | 951 |  | 
 | 952 |   if (image_classes_zip_filename != NULL && image_classes_filename == NULL) { | 
 | 953 |     Usage("--image-classes-zip should be used with --image-classes"); | 
 | 954 |   } | 
 | 955 |  | 
 | 956 |   if (dex_filenames.empty() && zip_fd == -1) { | 
 | 957 |     Usage("Input must be supplied with either --dex-file or --zip-fd"); | 
 | 958 |   } | 
 | 959 |  | 
 | 960 |   if (!dex_filenames.empty() && zip_fd != -1) { | 
 | 961 |     Usage("--dex-file should not be used with --zip-fd"); | 
 | 962 |   } | 
 | 963 |  | 
 | 964 |   if (!dex_filenames.empty() && !zip_location.empty()) { | 
 | 965 |     Usage("--dex-file should not be used with --zip-location"); | 
 | 966 |   } | 
 | 967 |  | 
 | 968 |   if (dex_locations.empty()) { | 
 | 969 |     for (size_t i = 0; i < dex_filenames.size(); i++) { | 
 | 970 |       dex_locations.push_back(dex_filenames[i]); | 
 | 971 |     } | 
 | 972 |   } else if (dex_locations.size() != dex_filenames.size()) { | 
 | 973 |     Usage("--dex-location arguments do not match --dex-file arguments"); | 
 | 974 |   } | 
 | 975 |  | 
 | 976 |   if (zip_fd != -1 && zip_location.empty()) { | 
 | 977 |     Usage("--zip-location should be supplied with --zip-fd"); | 
 | 978 |   } | 
 | 979 |  | 
 | 980 |   if (boot_image_option.empty()) { | 
 | 981 |     if (image_base == 0) { | 
| Brian Carlstrom | e0948e1 | 2013-08-29 09:36:15 -0700 | [diff] [blame] | 982 |       Usage("Non-zero --base not specified"); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 983 |     } | 
 | 984 |   } | 
 | 985 |  | 
 | 986 |   std::string oat_stripped(oat_filename); | 
 | 987 |   std::string oat_unstripped; | 
 | 988 |   if (!oat_symbols.empty()) { | 
 | 989 |     oat_unstripped += oat_symbols; | 
 | 990 |   } else { | 
 | 991 |     oat_unstripped += oat_filename; | 
 | 992 |   } | 
 | 993 |  | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 994 |   if (compiler_filter_string == NULL) { | 
| Ian Rogers | befbd57 | 2014-03-06 01:13:39 -0800 | [diff] [blame^] | 995 |     if (instruction_set == kX86_64) { | 
 | 996 |       // TODO: currently x86-64 is only interpreted. | 
 | 997 |       compiler_filter_string = "interpret-only"; | 
 | 998 |     } else if (image) { | 
| Brian Carlstrom | 5e754d8 | 2014-03-05 10:59:04 -0800 | [diff] [blame] | 999 |       compiler_filter_string = "speed"; | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 1000 |     } else { | 
 | 1001 | #if ART_SMALL_MODE | 
 | 1002 |       compiler_filter_string = "interpret-only"; | 
 | 1003 | #else | 
 | 1004 |       compiler_filter_string = "speed"; | 
 | 1005 | #endif | 
 | 1006 |     } | 
 | 1007 |   } | 
 | 1008 |   CHECK(compiler_filter_string != nullptr); | 
 | 1009 |   CompilerOptions::CompilerFilter compiler_filter = CompilerOptions::kDefaultCompilerFilter; | 
 | 1010 |   if (strcmp(compiler_filter_string, "interpret-only") == 0) { | 
 | 1011 |     compiler_filter = CompilerOptions::kInterpretOnly; | 
 | 1012 |   } else if (strcmp(compiler_filter_string, "space") == 0) { | 
 | 1013 |     compiler_filter = CompilerOptions::kSpace; | 
 | 1014 |   } else if (strcmp(compiler_filter_string, "balanced") == 0) { | 
 | 1015 |     compiler_filter = CompilerOptions::kBalanced; | 
 | 1016 |   } else if (strcmp(compiler_filter_string, "speed") == 0) { | 
 | 1017 |     compiler_filter = CompilerOptions::kSpeed; | 
 | 1018 |   } else if (strcmp(compiler_filter_string, "everything") == 0) { | 
 | 1019 |     compiler_filter = CompilerOptions::kEverything; | 
 | 1020 |   } else { | 
 | 1021 |     Usage("Unknown --compiler-filter value %s", compiler_filter_string); | 
 | 1022 |   } | 
 | 1023 |  | 
 | 1024 |   CompilerOptions compiler_options(compiler_filter, | 
 | 1025 |                                    huge_method_threshold, | 
 | 1026 |                                    large_method_threshold, | 
 | 1027 |                                    small_method_threshold, | 
 | 1028 |                                    tiny_method_threshold, | 
| Mark Mendell | ae9fd93 | 2014-02-10 16:14:35 -0800 | [diff] [blame] | 1029 |                                    num_dex_methods_threshold, | 
 | 1030 |                                    generate_gdb_information | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 1031 | #ifdef ART_SEA_IR_MODE | 
 | 1032 |                                    , compiler_options.sea_ir_ = true; | 
 | 1033 | #endif | 
 | 1034 |                                    );  // NOLINT(whitespace/parens) | 
 | 1035 |  | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1036 |   // Done with usage checks, enable watchdog if requested | 
 | 1037 |   WatchDog watch_dog(watch_dog_enabled); | 
 | 1038 |  | 
 | 1039 |   // Check early that the result of compilation can be written | 
 | 1040 |   UniquePtr<File> oat_file; | 
 | 1041 |   bool create_file = !oat_unstripped.empty();  // as opposed to using open file descriptor | 
 | 1042 |   if (create_file) { | 
| Brian Carlstrom | 7571e8b | 2013-08-12 17:04:14 -0700 | [diff] [blame] | 1043 |     oat_file.reset(OS::CreateEmptyFile(oat_unstripped.c_str())); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1044 |     if (oat_location.empty()) { | 
 | 1045 |       oat_location = oat_filename; | 
 | 1046 |     } | 
 | 1047 |   } else { | 
 | 1048 |     oat_file.reset(new File(oat_fd, oat_location)); | 
 | 1049 |     oat_file->DisableAutoClose(); | 
 | 1050 |   } | 
 | 1051 |   if (oat_file.get() == NULL) { | 
 | 1052 |     PLOG(ERROR) << "Failed to create oat file: " << oat_location; | 
 | 1053 |     return EXIT_FAILURE; | 
 | 1054 |   } | 
 | 1055 |   if (create_file && fchmod(oat_file->Fd(), 0644) != 0) { | 
 | 1056 |     PLOG(ERROR) << "Failed to make oat file world readable: " << oat_location; | 
 | 1057 |     return EXIT_FAILURE; | 
 | 1058 |   } | 
 | 1059 |  | 
| Ian Rogers | e6bb3b2 | 2013-08-19 21:51:45 -0700 | [diff] [blame] | 1060 |   timings.StartSplit("dex2oat Setup"); | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 1061 |   LOG(INFO) << "dex2oat: " << CommandLine(); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1062 |  | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 1063 |   Runtime::Options runtime_options; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1064 |   std::vector<const DexFile*> boot_class_path; | 
 | 1065 |   if (boot_image_option.empty()) { | 
| Brian Carlstrom | 3cf59d5 | 2013-11-10 21:04:10 -0800 | [diff] [blame] | 1066 |     size_t failure_count = OpenDexFiles(dex_filenames, dex_locations, boot_class_path); | 
 | 1067 |     if (failure_count > 0) { | 
 | 1068 |       LOG(ERROR) << "Failed to open some dex files: " << failure_count; | 
 | 1069 |       return EXIT_FAILURE; | 
 | 1070 |     } | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 1071 |     runtime_options.push_back(std::make_pair("bootclasspath", &boot_class_path)); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1072 |   } else { | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 1073 |     runtime_options.push_back(std::make_pair(boot_image_option.c_str(), | 
 | 1074 |                                              reinterpret_cast<void*>(NULL))); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1075 |   } | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1076 |   for (size_t i = 0; i < runtime_args.size(); i++) { | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 1077 |     runtime_options.push_back(std::make_pair(runtime_args[i], reinterpret_cast<void*>(NULL))); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1078 |   } | 
 | 1079 |  | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 1080 |   VerificationResults verification_results(&compiler_options); | 
 | 1081 |   DexFileToMethodInlinerMap method_inliner_map; | 
 | 1082 |   CompilerCallbacksImpl callbacks(&verification_results, &method_inliner_map); | 
 | 1083 |   runtime_options.push_back(std::make_pair("compilercallbacks", &callbacks)); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1084 |  | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1085 |   Dex2Oat* p_dex2oat; | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 1086 |   if (!Dex2Oat::Create(&p_dex2oat, | 
 | 1087 |                        runtime_options, | 
 | 1088 |                        compiler_options, | 
 | 1089 |                        compiler_backend, | 
 | 1090 |                        instruction_set, | 
 | 1091 |                        instruction_set_features, | 
 | 1092 |                        &verification_results, | 
 | 1093 |                        &method_inliner_map, | 
 | 1094 |                        thread_count)) { | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1095 |     LOG(ERROR) << "Failed to create dex2oat"; | 
 | 1096 |     return EXIT_FAILURE; | 
 | 1097 |   } | 
 | 1098 |   UniquePtr<Dex2Oat> dex2oat(p_dex2oat); | 
 | 1099 |   // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start, | 
| Ian Rogers | 3f3d22c | 2013-08-27 18:11:09 -0700 | [diff] [blame] | 1100 |   // give it away now so that we don't starve GC. | 
 | 1101 |   Thread* self = Thread::Current(); | 
 | 1102 |   self->TransitionFromRunnableToSuspended(kNative); | 
| Ian Rogers | 0f40ac3 | 2013-08-13 22:10:30 -0700 | [diff] [blame] | 1103 |   // If we're doing the image, override the compiler filter to force full compilation. Must be | 
| buzbee | fe9ca40 | 2013-08-21 09:48:11 -0700 | [diff] [blame] | 1104 |   // done ahead of WellKnownClasses::Init that causes verification.  Note: doesn't force | 
 | 1105 |   // compilation of class initializers. | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1106 |   // Whilst we're in native take the opportunity to initialize well known classes. | 
| Ian Rogers | 3f3d22c | 2013-08-27 18:11:09 -0700 | [diff] [blame] | 1107 |   WellKnownClasses::Init(self->GetJniEnv()); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1108 |  | 
 | 1109 |   // If --image-classes was specified, calculate the full list of classes to include in the image | 
 | 1110 |   UniquePtr<CompilerDriver::DescriptorSet> image_classes(NULL); | 
 | 1111 |   if (image_classes_filename != NULL) { | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 1112 |     std::string error_msg; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1113 |     if (image_classes_zip_filename != NULL) { | 
 | 1114 |       image_classes.reset(dex2oat->ReadImageClassesFromZip(image_classes_zip_filename, | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 1115 |                                                            image_classes_filename, | 
 | 1116 |                                                            &error_msg)); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1117 |     } else { | 
 | 1118 |       image_classes.reset(dex2oat->ReadImageClassesFromFile(image_classes_filename)); | 
 | 1119 |     } | 
 | 1120 |     if (image_classes.get() == NULL) { | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 1121 |       LOG(ERROR) << "Failed to create list of image classes from '" << image_classes_filename << | 
 | 1122 |           "': " << error_msg; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1123 |       return EXIT_FAILURE; | 
 | 1124 |     } | 
 | 1125 |   } | 
 | 1126 |  | 
 | 1127 |   std::vector<const DexFile*> dex_files; | 
 | 1128 |   if (boot_image_option.empty()) { | 
 | 1129 |     dex_files = Runtime::Current()->GetClassLinker()->GetBootClassPath(); | 
 | 1130 |   } else { | 
 | 1131 |     if (dex_filenames.empty()) { | 
| Ian Rogers | 740a11d | 2014-01-14 10:11:25 -0800 | [diff] [blame] | 1132 |       ATRACE_BEGIN("Opening zip archive from file descriptor"); | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 1133 |       std::string error_msg; | 
 | 1134 |       UniquePtr<ZipArchive> zip_archive(ZipArchive::OpenFromFd(zip_fd, zip_location.c_str(), | 
 | 1135 |                                                                &error_msg)); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1136 |       if (zip_archive.get() == NULL) { | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 1137 |         LOG(ERROR) << "Failed to open zip from file descriptor for '" << zip_location << "': " | 
 | 1138 |             << error_msg; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1139 |         return EXIT_FAILURE; | 
 | 1140 |       } | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 1141 |       const DexFile* dex_file = DexFile::Open(*zip_archive.get(), zip_location, &error_msg); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1142 |       if (dex_file == NULL) { | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 1143 |         LOG(ERROR) << "Failed to open dex from file descriptor for zip file '" << zip_location | 
 | 1144 |             << "': " << error_msg; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1145 |         return EXIT_FAILURE; | 
 | 1146 |       } | 
 | 1147 |       dex_files.push_back(dex_file); | 
| Ian Rogers | 740a11d | 2014-01-14 10:11:25 -0800 | [diff] [blame] | 1148 |       ATRACE_END(); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1149 |     } else { | 
| Brian Carlstrom | 3cf59d5 | 2013-11-10 21:04:10 -0800 | [diff] [blame] | 1150 |       size_t failure_count = OpenDexFiles(dex_filenames, dex_locations, dex_files); | 
 | 1151 |       if (failure_count > 0) { | 
 | 1152 |         LOG(ERROR) << "Failed to open some dex files: " << failure_count; | 
 | 1153 |         return EXIT_FAILURE; | 
 | 1154 |       } | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1155 |     } | 
| Brian Carlstrom | d76e083 | 2013-08-29 15:17:42 -0700 | [diff] [blame] | 1156 |  | 
| Brian Carlstrom | f79fccb | 2014-02-20 08:55:10 -0800 | [diff] [blame] | 1157 |     const bool kSaveDexInput = false; | 
 | 1158 |     if (kSaveDexInput) { | 
 | 1159 |       for (size_t i = 0; i < dex_files.size(); ++i) { | 
 | 1160 |         const DexFile* dex_file = dex_files[i]; | 
| Ian Rogers | 5180cc1 | 2014-02-21 13:34:16 -0800 | [diff] [blame] | 1161 |         std::string tmp_file_name(StringPrintf("/data/local/tmp/dex2oat.%d.%zd.dex", getpid(), i)); | 
| Brian Carlstrom | f79fccb | 2014-02-20 08:55:10 -0800 | [diff] [blame] | 1162 |         UniquePtr<File> tmp_file(OS::CreateEmptyFile(tmp_file_name.c_str())); | 
 | 1163 |         if (tmp_file.get() == nullptr) { | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 1164 |             PLOG(ERROR) << "Failed to open file " << tmp_file_name | 
 | 1165 |                         << ". Try: adb shell chmod 777 /data/local/tmp"; | 
| Brian Carlstrom | f79fccb | 2014-02-20 08:55:10 -0800 | [diff] [blame] | 1166 |             continue; | 
 | 1167 |         } | 
 | 1168 |         tmp_file->WriteFully(dex_file->Begin(), dex_file->Size()); | 
 | 1169 |         LOG(INFO) << "Wrote input to " << tmp_file_name; | 
 | 1170 |       } | 
 | 1171 |     } | 
| Brian Carlstrom | 2ec6520 | 2014-03-03 15:16:37 -0800 | [diff] [blame] | 1172 |   } | 
 | 1173 |   // Ensure opened dex files are writable for dex-to-dex transformations. | 
 | 1174 |   for (const auto& dex_file : dex_files) { | 
 | 1175 |     if (!dex_file->EnableWrite()) { | 
 | 1176 |       PLOG(ERROR) << "Failed to make .dex file writeable '" << dex_file->GetLocation() << "'\n"; | 
| Brian Carlstrom | d76e083 | 2013-08-29 15:17:42 -0700 | [diff] [blame] | 1177 |     } | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1178 |   } | 
 | 1179 |  | 
| buzbee | a024a06 | 2013-07-31 10:47:37 -0700 | [diff] [blame] | 1180 |   /* | 
 | 1181 |    * If we're not in interpret-only mode, go ahead and compile small applications. Don't | 
 | 1182 |    * bother to check if we're doing the image. | 
 | 1183 |    */ | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 1184 |   if (!image && (compiler_options.GetCompilerFilter() != CompilerOptions::kInterpretOnly)) { | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1185 |     size_t num_methods = 0; | 
 | 1186 |     for (size_t i = 0; i != dex_files.size(); ++i) { | 
 | 1187 |       const DexFile* dex_file = dex_files[i]; | 
 | 1188 |       CHECK(dex_file != NULL); | 
 | 1189 |       num_methods += dex_file->NumMethodIds(); | 
 | 1190 |     } | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 1191 |     if (num_methods <= compiler_options.GetNumDexMethodsThreshold()) { | 
 | 1192 |       compiler_options.SetCompilerFilter(CompilerOptions::kSpeed); | 
| Anwar Ghuloum | 75a43f1 | 2013-08-13 17:22:14 -0700 | [diff] [blame] | 1193 |       VLOG(compiler) << "Below method threshold, compiling anyways"; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1194 |     } | 
 | 1195 |   } | 
 | 1196 |  | 
 | 1197 |   UniquePtr<const CompilerDriver> compiler(dex2oat->CreateOatFile(boot_image_option, | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1198 |                                                                   android_root, | 
 | 1199 |                                                                   is_host, | 
 | 1200 |                                                                   dex_files, | 
 | 1201 |                                                                   oat_file.get(), | 
 | 1202 |                                                                   bitcode_filename, | 
 | 1203 |                                                                   image, | 
 | 1204 |                                                                   image_classes, | 
 | 1205 |                                                                   dump_stats, | 
| Nicolas Geoffray | ea3fa0b | 2014-02-10 11:59:41 +0000 | [diff] [blame] | 1206 |                                                                   dump_passes, | 
 | 1207 |                                                                   timings, | 
 | 1208 |                                                                   compiler_phases_timings)); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1209 |  | 
 | 1210 |   if (compiler.get() == NULL) { | 
 | 1211 |     LOG(ERROR) << "Failed to create oat file: " << oat_location; | 
 | 1212 |     return EXIT_FAILURE; | 
 | 1213 |   } | 
 | 1214 |  | 
| Anwar Ghuloum | 75a43f1 | 2013-08-13 17:22:14 -0700 | [diff] [blame] | 1215 |   VLOG(compiler) << "Oat file written successfully (unstripped): " << oat_location; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1216 |  | 
 | 1217 |   // Notes on the interleaving of creating the image and oat file to | 
 | 1218 |   // ensure the references between the two are correct. | 
 | 1219 |   // | 
 | 1220 |   // Currently we have a memory layout that looks something like this: | 
 | 1221 |   // | 
 | 1222 |   // +--------------+ | 
 | 1223 |   // | image        | | 
 | 1224 |   // +--------------+ | 
 | 1225 |   // | boot oat     | | 
 | 1226 |   // +--------------+ | 
 | 1227 |   // | alloc spaces | | 
 | 1228 |   // +--------------+ | 
 | 1229 |   // | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 1230 |   // There are several constraints on the loading of the image and boot.oat. | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1231 |   // | 
 | 1232 |   // 1. The image is expected to be loaded at an absolute address and | 
 | 1233 |   // contains Objects with absolute pointers within the image. | 
 | 1234 |   // | 
 | 1235 |   // 2. There are absolute pointers from Methods in the image to their | 
 | 1236 |   // code in the oat. | 
 | 1237 |   // | 
 | 1238 |   // 3. There are absolute pointers from the code in the oat to Methods | 
 | 1239 |   // in the image. | 
 | 1240 |   // | 
 | 1241 |   // 4. There are absolute pointers from code in the oat to other code | 
 | 1242 |   // in the oat. | 
 | 1243 |   // | 
 | 1244 |   // To get this all correct, we go through several steps. | 
 | 1245 |   // | 
 | 1246 |   // 1. We have already created that oat file above with | 
 | 1247 |   // CreateOatFile. Originally this was just our own proprietary file | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 1248 |   // but now it is contained within an ELF dynamic object (aka an .so | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1249 |   // file). The Compiler returned by CreateOatFile provides | 
 | 1250 |   // PatchInformation for references to oat code and Methods that need | 
 | 1251 |   // to be update once we know where the oat file will be located | 
 | 1252 |   // after the image. | 
 | 1253 |   // | 
 | 1254 |   // 2. We create the image file. It needs to know where the oat file | 
 | 1255 |   // will be loaded after itself. Originally when oat file was simply | 
 | 1256 |   // memory mapped so we could predict where its contents were based | 
 | 1257 |   // on the file size. Now that it is an ELF file, we need to inspect | 
 | 1258 |   // the ELF file to understand the in memory segment layout including | 
 | 1259 |   // where the oat header is located within. ImageWriter's | 
 | 1260 |   // PatchOatCodeAndMethods uses the PatchInformation from the | 
 | 1261 |   // Compiler to touch up absolute references in the oat file. | 
 | 1262 |   // | 
 | 1263 |   // 3. We fixup the ELF program headers so that dlopen will try to | 
 | 1264 |   // load the .so at the desired location at runtime by offsetting the | 
 | 1265 |   // Elf32_Phdr.p_vaddr values by the desired base address. | 
 | 1266 |   // | 
 | 1267 |   if (image) { | 
| Anwar Ghuloum | 6f28d91 | 2013-07-24 15:02:53 -0700 | [diff] [blame] | 1268 |     timings.NewSplit("dex2oat ImageWriter"); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1269 |     bool image_creation_success = dex2oat->CreateImageFile(image_filename, | 
 | 1270 |                                                            image_base, | 
 | 1271 |                                                            oat_unstripped, | 
 | 1272 |                                                            oat_location, | 
 | 1273 |                                                            *compiler.get()); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1274 |     if (!image_creation_success) { | 
 | 1275 |       return EXIT_FAILURE; | 
 | 1276 |     } | 
| Anwar Ghuloum | 75a43f1 | 2013-08-13 17:22:14 -0700 | [diff] [blame] | 1277 |     VLOG(compiler) << "Image written successfully: " << image_filename; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1278 |   } | 
 | 1279 |  | 
 | 1280 |   if (is_host) { | 
| Ian Rogers | 4639860 | 2013-08-20 07:50:36 -0700 | [diff] [blame] | 1281 |     if (dump_timing || (dump_slow_timing && timings.GetTotalNs() > MsToNs(1000))) { | 
| Ian Rogers | 5fe9af7 | 2013-11-14 00:17:20 -0800 | [diff] [blame] | 1282 |       LOG(INFO) << Dumpable<TimingLogger>(timings); | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 1283 |     } | 
| Nicolas Geoffray | ea3fa0b | 2014-02-10 11:59:41 +0000 | [diff] [blame] | 1284 |     if (dump_passes) { | 
| Ian Rogers | 3d50407 | 2014-03-01 09:16:49 -0800 | [diff] [blame] | 1285 |       LOG(INFO) << Dumpable<CumulativeLogger>(*compiler.get()->GetTimingsLogger()); | 
| Nicolas Geoffray | ea3fa0b | 2014-02-10 11:59:41 +0000 | [diff] [blame] | 1286 |     } | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1287 |     return EXIT_SUCCESS; | 
 | 1288 |   } | 
 | 1289 |  | 
 | 1290 |   // If we don't want to strip in place, copy from unstripped location to stripped location. | 
 | 1291 |   // We need to strip after image creation because FixupElf needs to use .strtab. | 
 | 1292 |   if (oat_unstripped != oat_stripped) { | 
| Anwar Ghuloum | 6f28d91 | 2013-07-24 15:02:53 -0700 | [diff] [blame] | 1293 |     timings.NewSplit("dex2oat OatFile copy"); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1294 |     oat_file.reset(); | 
| Brian Carlstrom | 7571e8b | 2013-08-12 17:04:14 -0700 | [diff] [blame] | 1295 |      UniquePtr<File> in(OS::OpenFileForReading(oat_unstripped.c_str())); | 
 | 1296 |     UniquePtr<File> out(OS::CreateEmptyFile(oat_stripped.c_str())); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1297 |     size_t buffer_size = 8192; | 
 | 1298 |     UniquePtr<uint8_t> buffer(new uint8_t[buffer_size]); | 
 | 1299 |     while (true) { | 
 | 1300 |       int bytes_read = TEMP_FAILURE_RETRY(read(in->Fd(), buffer.get(), buffer_size)); | 
 | 1301 |       if (bytes_read <= 0) { | 
 | 1302 |         break; | 
 | 1303 |       } | 
 | 1304 |       bool write_ok = out->WriteFully(buffer.get(), bytes_read); | 
 | 1305 |       CHECK(write_ok); | 
 | 1306 |     } | 
 | 1307 |     oat_file.reset(out.release()); | 
| Anwar Ghuloum | 75a43f1 | 2013-08-13 17:22:14 -0700 | [diff] [blame] | 1308 |     VLOG(compiler) << "Oat file copied successfully (stripped): " << oat_stripped; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1309 |   } | 
 | 1310 |  | 
| Brian Carlstrom | 7fcba11 | 2013-07-22 10:28:48 -0700 | [diff] [blame] | 1311 | #if ART_USE_PORTABLE_COMPILER  // We currently only generate symbols on Portable | 
| Anwar Ghuloum | 6f28d91 | 2013-07-24 15:02:53 -0700 | [diff] [blame] | 1312 |   timings.NewSplit("dex2oat ElfStripper"); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1313 |   // Strip unneeded sections for target | 
 | 1314 |   off_t seek_actual = lseek(oat_file->Fd(), 0, SEEK_SET); | 
 | 1315 |   CHECK_EQ(0, seek_actual); | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 1316 |   std::string error_msg; | 
 | 1317 |   CHECK(ElfStripper::Strip(oat_file.get(), &error_msg)) << error_msg; | 
| Anwar Ghuloum | 6f28d91 | 2013-07-24 15:02:53 -0700 | [diff] [blame] | 1318 |  | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1319 |  | 
 | 1320 |   // We wrote the oat file successfully, and want to keep it. | 
| Anwar Ghuloum | 75a43f1 | 2013-08-13 17:22:14 -0700 | [diff] [blame] | 1321 |   VLOG(compiler) << "Oat file written successfully (stripped): " << oat_location; | 
| Brian Carlstrom | 7934ac2 | 2013-07-26 10:54:15 -0700 | [diff] [blame] | 1322 | #endif  // ART_USE_PORTABLE_COMPILER | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 1323 |  | 
| Anwar Ghuloum | 6f28d91 | 2013-07-24 15:02:53 -0700 | [diff] [blame] | 1324 |   timings.EndSplit(); | 
 | 1325 |  | 
| Brian Carlstrom | c6dfdac | 2013-08-26 18:57:31 -0700 | [diff] [blame] | 1326 |   if (dump_timing || (dump_slow_timing && timings.GetTotalNs() > MsToNs(1000))) { | 
| Ian Rogers | 5fe9af7 | 2013-11-14 00:17:20 -0800 | [diff] [blame] | 1327 |     LOG(INFO) << Dumpable<TimingLogger>(timings); | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 1328 |   } | 
| Nicolas Geoffray | ea3fa0b | 2014-02-10 11:59:41 +0000 | [diff] [blame] | 1329 |   if (dump_passes) { | 
 | 1330 |     LOG(INFO) << Dumpable<CumulativeLogger>(compiler_phases_timings); | 
 | 1331 |   } | 
| Ian Rogers | 2672a9f | 2013-09-05 17:24:22 -0700 | [diff] [blame] | 1332 |  | 
 | 1333 |   // Everything was successfully written, do an explicit exit here to avoid running Runtime | 
 | 1334 |   // destructors that take time (bug 10645725) unless we're a debug build or running on valgrind. | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 1335 |   if (!kIsDebugBuild && (RUNNING_ON_VALGRIND == 0)) { | 
| Brian Carlstrom | 65c23bb | 2014-02-01 22:12:39 -0800 | [diff] [blame] | 1336 |     dex2oat->LogCompletionTime(); | 
| Ian Rogers | 2672a9f | 2013-09-05 17:24:22 -0700 | [diff] [blame] | 1337 |     exit(EXIT_SUCCESS); | 
 | 1338 |   } | 
 | 1339 |  | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1340 |   return EXIT_SUCCESS; | 
| Brian Carlstrom | 6449c62 | 2014-02-10 23:48:36 -0800 | [diff] [blame] | 1341 | }  // NOLINT(readability/fn_size) | 
| Brian Carlstrom | 7934ac2 | 2013-07-26 10:54:15 -0700 | [diff] [blame] | 1342 | }  // namespace art | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 1343 |  | 
 | 1344 | int main(int argc, char** argv) { | 
 | 1345 |   return art::dex2oat(argc, argv); | 
 | 1346 | } |