dex2oat.cc revision b12552a95d68b9e4a567103190074ae47b6a61dc
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
1669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
1769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom#include <stdio.h>
1869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom#include <stdlib.h>
1969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
20ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom#include <iostream>
21ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom#include <fstream>
2269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom#include <string>
2369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom#include <vector>
2469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
2569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom#include "class_linker.h"
2669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom#include "class_loader.h"
2769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom#include "compiler.h"
285e863ddd72a70d33525f7403a695f7bc1c218938Ian Rogers#include "file.h"
2969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom#include "image_writer.h"
306f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers#include "leb128.h"
31e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "oat_writer.h"
326d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h"
335e863ddd72a70d33525f7403a695f7bc1c218938Ian Rogers#include "os.h"
3469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom#include "runtime.h"
3569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom#include "stringpiece.h"
36bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes#include "timing_logger.h"
37a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom#include "zip_archive.h"
3869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
3969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstromnamespace art {
4069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
4169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstromstatic void usage() {
4269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  fprintf(stderr,
4369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom          "Usage: dex2oat [options]...\n"
4469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom          "\n");
4569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  fprintf(stderr,
46a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "  --dex-file=<dex-file>: specifies a .dex file to compile.\n"
4769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom          "      Example: --dex-file=/system/framework/core.jar\n"
4869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom          "\n");
4969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  fprintf(stderr,
50a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "  --zip-fd=<file-descriptor>: specifies a file descriptor of a zip file\n"
51a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "      containing a classes.dex file to compile.\n"
52a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "      Example: --zip-fd=5\n"
53a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "\n");
54a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  fprintf(stderr,
55a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "  --zip-name=<zip-name>: specifies a symbolic name for the file corresponding\n"
56a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "      to the file descriptor specified by --zip-fd.\n"
57a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "      Example: --zip-name=/system/app/Calculator.apk\n"
58a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "\n");
59a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  fprintf(stderr,
60a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "  --oat-file=<file.oat>: specifies the required oat filename.\n"
61a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "      Example: --oat-file=/system/framework/boot.oat\n"
62a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "\n");
63a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  fprintf(stderr,
64a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "  --oat-name=<oat-name>: specifies a symbolic name for the file corresponding\n"
65a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "      to the file descriptor specified by --oat-fd.\n"
66a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "      Example: --oat-name=/data/art-cache/system@app@Calculator.apk.oat\n"
67ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom          "\n");
68ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  fprintf(stderr,
69ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom          "  --image=<file.art>: specifies the output image filename.\n"
7029e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "      Example: --image=/system/framework/boot.art\n"
71e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom          "\n");
72e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  fprintf(stderr,
73ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom          "  --image-classes=<classname-file>: specifies classes to include in an image.\n"
74ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom          "      Example: --image=frameworks/base/preloaded-classes\n"
7569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom          "\n");
7669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  fprintf(stderr,
7769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom          "  --base=<hex-address>: specifies the base address when creating a boot image.\n"
7869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom          "      Example: --base=0x50000000\n"
7969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom          "\n");
8069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  fprintf(stderr,
81e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom          "  --boot-image=<file.art>: provide the image file for the boot class path.\n"
8229e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "      Example: --boot-image=/system/framework/boot.art\n"
8329e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "      Default: <host-prefix>/system/framework/boot.art\n"
84e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom          "\n");
8569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  fprintf(stderr,
8658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom          "  --host-prefix may be used to translate host paths to target paths during\n"
8758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom          "      cross compilation.\n"
8858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom          "      Example: --host-prefix=out/target/product/crespo\n"
89b001126eb9e47d0088b3672652454c53f4e17e9fBrian Carlstrom          "      Default: $ANDROID_PRODUCT_OUT\n"
90161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom          "\n");
9127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  fprintf(stderr,
925d84040e2231de1d48e6f30cab2cc8d4beb8effejeffhao          "  --runtime-arg <argument>: used to specify various arguments for the runtime,\n"
935d84040e2231de1d48e6f30cab2cc8d4beb8effejeffhao          "      such as initial heap size, maximum heap size, and verbose output.\n"
945d84040e2231de1d48e6f30cab2cc8d4beb8effejeffhao          "      Use a separate --runtime-arg switch for each argument.\n"
955d84040e2231de1d48e6f30cab2cc8d4beb8effejeffhao          "      Example: --runtime-arg -Xms256m\n"
9627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom          "\n");
9769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  exit(EXIT_FAILURE);
9869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom}
9969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
100ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromclass Dex2Oat {
101ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom public:
102ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
1035523ee070b005576c6f889415205d49ea77cf243Elliott Hughes  static Dex2Oat* Create(Runtime::Options& options, size_t thread_count) {
104ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    UniquePtr<Runtime> runtime(CreateRuntime(options));
105ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    if (runtime.get() == NULL) {
106ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      return NULL;
107254db0ff7ea6509a1c2914b1d9532e2041a0c4c4Jesse Wilson    }
1085523ee070b005576c6f889415205d49ea77cf243Elliott Hughes    return new Dex2Oat(runtime.release(), thread_count);
109ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
110ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
111ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  ~Dex2Oat() {
112ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    delete runtime_;
1135523ee070b005576c6f889415205d49ea77cf243Elliott Hughes    LOG(INFO) << "dex2oat took " << PrettyDuration(NanoTime() - start_ns_) << " (threads: " << thread_count_ << ")";
114ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
115ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
116ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  // Make a list of descriptors for classes to include in the image
117ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  const std::set<std::string>* GetImageClassDescriptors(const char* image_classes_filename) {
118ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    UniquePtr<std::ifstream> image_classes_file(new std::ifstream(image_classes_filename, std::ifstream::in));
119ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    if (image_classes_file.get() == NULL) {
120ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      LOG(ERROR) << "Failed to open image classes file " << image_classes_filename;
121ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      return NULL;
122ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
123ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
1246f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    // Load all the classes specified in the file
125ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    ClassLinker* class_linker = runtime_->GetClassLinker();
126ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    while (image_classes_file->good()) {
127ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      std::string dot;
128ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      std::getline(*image_classes_file.get(), dot);
129ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      if (StringPiece(dot).starts_with("#") || dot.empty()) {
130ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom        continue;
131ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      }
132955724179c6c739524f610023287f56b24dc31deElliott Hughes      std::string descriptor(DotToDescriptor(dot.c_str()));
133c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes      SirtRef<Class> klass(class_linker->FindSystemClass(descriptor.c_str()));
134ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      if (klass.get() == NULL) {
135ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom        LOG(WARNING) << "Failed to find class " << descriptor;
136ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom        Thread::Current()->ClearException();
137ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      }
138ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
139ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    image_classes_file->close();
140ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
1416f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    // Resolve exception classes referenced by the loaded classes. The catch logic assumes
1426f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    // exceptions are resolved by the verifier when there is a catch block in an interested method.
1436f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    // Do this here so that exception classes appear to have been specified image classes.
1446f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    std::set<std::pair<uint16_t, const DexFile*> > unresolved_exception_types;
1456f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    do {
1466f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      unresolved_exception_types.clear();
1476f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      class_linker->VisitClasses(ResolveCatchBlockExceptionsClassVisitor,
1486f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers                                 &unresolved_exception_types);
1496f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      typedef std::set<std::pair<uint16_t, const DexFile*> >::const_iterator It;  // TODO: C++0x auto
1506f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      for (It it = unresolved_exception_types.begin(),
1516f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers           end = unresolved_exception_types.end();
1526f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers           it != end; ++it) {
1536f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        uint16_t exception_type_idx = it->first;
1546f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        const DexFile* dex_file = it->second;
1556f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        DexCache* dex_cache = class_linker->FindDexCache(*dex_file);
1566f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        ClassLoader* class_loader = NULL;
1576f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        SirtRef<Class> klass(class_linker->ResolveType(*dex_file, exception_type_idx, dex_cache,
1586f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers                                                       class_loader));
1596f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        if (klass.get() == NULL) {
1606f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers          const DexFile::TypeId& type_id = dex_file->GetTypeId(exception_type_idx);
1616f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers          const char* descriptor = dex_file->GetTypeDescriptor(type_id);
1626f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers          LOG(FATAL) << "Failed to resolve class " << descriptor;
1636f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        }
1646f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        DCHECK(klass->IsThrowableClass());
1656f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      }
1666f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      // Resolving exceptions may load classes that reference more exceptions, iterate until no
1676f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      // more are found
1686f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    } while (!unresolved_exception_types.empty());
1696f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers
170ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    // We walk the roots looking for classes so that we'll pick up the
171ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    // above classes plus any classes them depend on such super
172ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    // classes, interfaces, and the required ClassLinker roots.
173ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    UniquePtr<std::set<std::string> > image_classes(new std::set<std::string>());
1746f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    class_linker->VisitClasses(RecordImageClassesVisitor, image_classes.get());
175ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    CHECK_NE(image_classes->size(), 0U);
176ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    return image_classes.release();
177254db0ff7ea6509a1c2914b1d9532e2041a0c4c4Jesse Wilson  }
178254db0ff7ea6509a1c2914b1d9532e2041a0c4c4Jesse Wilson
179ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  bool CreateOatFile(const std::string& boot_image_option,
180a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom                     const std::vector<const DexFile*>& dex_files,
181ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                     File* oat_file,
182ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                     bool image,
183ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                     const std::set<std::string>* image_classes) {
184ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    // SirtRef and ClassLoader creation needs to come after Runtime::Create
185ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    UniquePtr<SirtRef<ClassLoader> > class_loader(new SirtRef<ClassLoader>(NULL));
186ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    if (class_loader.get() == NULL) {
187ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      LOG(ERROR) << "Failed to create SirtRef for class loader";
188ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      return false;
189254db0ff7ea6509a1c2914b1d9532e2041a0c4c4Jesse Wilson    }
190ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
191ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    if (!boot_image_option.empty()) {
192ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
193ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      std::vector<const DexFile*> class_path_files(dex_files);
194ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      OpenClassPathFiles(runtime_->GetClassPath(), class_path_files);
195ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      for (size_t i = 0; i < class_path_files.size(); i++) {
196ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom        class_linker->RegisterDexFile(*class_path_files[i]);
197ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      }
198ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      class_loader.get()->reset(PathClassLoader::AllocCompileTime(class_path_files));
199254db0ff7ea6509a1c2914b1d9532e2041a0c4c4Jesse Wilson    }
200ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
2015523ee070b005576c6f889415205d49ea77cf243Elliott Hughes    Compiler compiler(instruction_set_, image, thread_count_, image_classes);
202ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    compiler.CompileAll(class_loader->get(), dex_files);
203ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
20410037c866b04550fc5461058c398c2e3e509381ajeffhao    if (!OatWriter::Create(oat_file, class_loader->get(), dex_files, compiler)) {
205ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      LOG(ERROR) << "Failed to create oat file " << oat_file->name();
206ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      return false;
207ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
208ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    return true;
209254db0ff7ea6509a1c2914b1d9532e2041a0c4c4Jesse Wilson  }
210ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
211ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  bool CreateImageFile(const char* image_filename,
212ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       uintptr_t image_base,
213ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       const std::set<std::string>* image_classes,
214ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       const std::string& oat_filename,
215ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       const std::string& host_prefix) {
216ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    // If we have an existing boot image, position new space after its oat file
217ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    if (Heap::GetSpaces().size() > 1) {
21830fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers      ImageSpace* last_image_space = NULL;
21930fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers      const std::vector<Space*>& spaces = Heap::GetSpaces();
22030fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers      for (size_t i=0; i < spaces.size(); i++) {
22130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers        if (spaces[i]->IsImageSpace()) {
22230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers          last_image_space = spaces[i]->AsImageSpace();
22330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers        }
22430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers      }
225ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      CHECK(last_image_space != NULL);
226ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      CHECK(last_image_space->IsImageSpace());
227ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      CHECK(!Heap::GetSpaces()[Heap::GetSpaces().size()-1]->IsImageSpace());
22830fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers      byte* oat_limit_addr = last_image_space->GetImageHeader().GetOatEnd();
229ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      image_base = RoundUp(reinterpret_cast<uintptr_t>(oat_limit_addr), kPageSize);
230ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
231ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
232ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    ImageWriter image_writer(image_classes);
233ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    if (!image_writer.Write(image_filename, image_base, oat_filename, host_prefix)) {
234ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      LOG(ERROR) << "Failed to create image file " << image_filename;
235ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      return false;
236ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
237ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    return true;
238ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
239ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
240ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom private:
241ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
2425523ee070b005576c6f889415205d49ea77cf243Elliott Hughes  explicit Dex2Oat(Runtime* runtime, size_t thread_count)
2435523ee070b005576c6f889415205d49ea77cf243Elliott Hughes      : runtime_(runtime), thread_count_(thread_count), start_ns_(NanoTime()) {
244bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes  }
245ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
246ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  static Runtime* CreateRuntime(Runtime::Options& options) {
247ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    Runtime* runtime = Runtime::Create(options, false);
248ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    if (runtime == NULL) {
249ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      LOG(ERROR) << "Failed to create runtime";
250ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      return NULL;
251ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
252ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
253ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    // if we loaded an existing image, we will reuse values from the image roots.
254ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    if (!runtime->HasJniDlsymLookupStub()) {
2558add92dcf59568c72c17e9a979948b1a7a0b1264Elliott Hughes      runtime->SetJniDlsymLookupStub(Compiler::CreateJniDlsymLookupStub(instruction_set_));
256ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
257ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    if (!runtime->HasAbstractMethodErrorStubArray()) {
258ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      runtime->SetAbstractMethodErrorStubArray(Compiler::CreateAbstractMethodErrorStub(instruction_set_));
259ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
260ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
261ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      Runtime::TrampolineType type = Runtime::TrampolineType(i);
262ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      if (!runtime->HasResolutionStubArray(type)) {
263ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom        runtime->SetResolutionStubArray(Compiler::CreateResolutionStub(instruction_set_, type), type);
264ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      }
265ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
266ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
267ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      Runtime::CalleeSaveType type = Runtime::CalleeSaveType(i);
268ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      if (!runtime->HasCalleeSaveMethod(type)) {
269ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom        runtime->SetCalleeSaveMethod(runtime->CreateCalleeSaveMethod(instruction_set_, type), type);
270ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      }
271ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
272ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    return runtime;
273ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
274ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
2756f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers  static void ResolveExceptionsForMethod(MethodHelper* mh,
2766f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers                           std::set<std::pair<uint16_t, const DexFile*> >& exceptions_to_resolve) {
2776f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    const DexFile::CodeItem* code_item = mh->GetCodeItem();
2786f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    if (code_item == NULL) {
2796f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      return;  // native or abstract method
2806f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    }
2816f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    if (code_item->tries_size_ == 0) {
2826f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      return;  // nothing to process
2836f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    }
2846f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    const byte* encoded_catch_handler_list = DexFile::GetCatchHandlerData(*code_item, 0);
2856f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    size_t num_encoded_catch_handlers = DecodeUnsignedLeb128(&encoded_catch_handler_list);
2866f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    for (size_t i = 0; i < num_encoded_catch_handlers; i++) {
2876f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      int32_t encoded_catch_handler_size = DecodeSignedLeb128(&encoded_catch_handler_list);
2886f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      bool has_catch_all = false;
2896f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      if (encoded_catch_handler_size <= 0) {
2906f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        encoded_catch_handler_size = -encoded_catch_handler_size;
2916f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        has_catch_all = true;
2926f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      }
2936f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      for (int32_t j = 0; j < encoded_catch_handler_size; j++) {
2946f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        uint16_t encoded_catch_handler_handlers_type_idx =
2956f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers            DecodeUnsignedLeb128(&encoded_catch_handler_list);
2966f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        // Add to set of types to resolve if not already in the dex cache resolved types
2976f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        if (!mh->IsResolvedTypeIdx(encoded_catch_handler_handlers_type_idx)) {
2986f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers          exceptions_to_resolve.insert(
2996f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers              std::pair<uint16_t, const DexFile*>(encoded_catch_handler_handlers_type_idx,
3006f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers                                                  &mh->GetDexFile()));
3016f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        }
3026f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        // ignore address associated with catch handler
3036f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        DecodeUnsignedLeb128(&encoded_catch_handler_list);
3046f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      }
3056f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      if (has_catch_all) {
3066f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        // ignore catch all address
3076f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        DecodeUnsignedLeb128(&encoded_catch_handler_list);
3086f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      }
3096f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    }
3106f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers  }
3116f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers  static bool ResolveCatchBlockExceptionsClassVisitor(Class* c, void* arg) {
3126f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    std::set<std::pair<uint16_t, const DexFile*> >* exceptions_to_resolve =
3136f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers        reinterpret_cast<std::set<std::pair<uint16_t, const DexFile*> >*>(arg);
3146f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    MethodHelper mh;
3156f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
3166f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      Method* m = c->GetVirtualMethod(i);
3176f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      mh.ChangeMethod(m);
3186f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      ResolveExceptionsForMethod(&mh, *exceptions_to_resolve);
3196f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    }
3206f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
3216f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      Method* m = c->GetDirectMethod(i);
3226f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      mh.ChangeMethod(m);
3236f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers      ResolveExceptionsForMethod(&mh, *exceptions_to_resolve);
3246f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    }
3256f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers    return true;
3266f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers  }
3276f1dfe415019de95f0305de66b3afb40005fe382Ian Rogers  static bool RecordImageClassesVisitor(Class* klass, void* arg) {
328ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    std::set<std::string>* image_classes = reinterpret_cast<std::set<std::string>*>(arg);
329ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    if (klass->IsArrayClass() || klass->IsPrimitive()) {
330ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      return true;
331ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
3326d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers    image_classes->insert(ClassHelper(klass).GetDescriptor());
333ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    return true;
334ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
335ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
336ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  // Appends to dex_files any elements of class_path that it doesn't already
337ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  // contain. This will open those dex files as necessary.
338ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  static void OpenClassPathFiles(const std::string& class_path, std::vector<const DexFile*>& dex_files) {
339ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    std::vector<std::string> parsed;
340ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    Split(class_path, ':', parsed);
341ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    for (size_t i = 0; i < parsed.size(); ++i) {
342ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      if (DexFilesContains(dex_files, parsed[i])) {
343ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom        continue;
344ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      }
345ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      const DexFile* dex_file = DexFile::Open(parsed[i], Runtime::Current()->GetHostPrefix());
346ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      if (dex_file == NULL) {
347ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom        LOG(WARNING) << "Failed to open dex file " << parsed[i];
348ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      } else {
349ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom        dex_files.push_back(dex_file);
350ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      }
351ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
352ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
353ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
354ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  // Returns true if dex_files has a dex with the named location.
355ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  static bool DexFilesContains(const std::vector<const DexFile*>& dex_files, const std::string& location) {
356ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    for (size_t i = 0; i < dex_files.size(); ++i) {
357ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      if (dex_files[i]->GetLocation() == location) {
358ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom        return true;
359ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      }
360ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
361ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    return false;
362ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
363ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
364ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  static const InstructionSet instruction_set_ = kThumb2;
365ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
366bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes  Runtime* runtime_;
3675523ee070b005576c6f889415205d49ea77cf243Elliott Hughes  size_t thread_count_;
368bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes  uint64_t start_ns_;
369bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes
370ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  DISALLOW_IMPLICIT_CONSTRUCTORS(Dex2Oat);
371ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom};
372254db0ff7ea6509a1c2914b1d9532e2041a0c4c4Jesse Wilson
373bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughesbool ParseInt(const char* in, int* out) {
374a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  char* end;
375a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  int result = strtol(in, &end, 10);
376a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  if (in == end || *end != '\0') {
377a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    return false;
378a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  }
379a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  *out = result;
380a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  return true;
381a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom}
382a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom
3835b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstromvoid OpenDexFiles(const std::vector<const char*>& dex_filenames,
3845b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom                  std::vector<const DexFile*>& dex_files,
3855b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom                  const std::string& strip_location_prefix) {
3865b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom  for (size_t i = 0; i < dex_filenames.size(); i++) {
3875b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom    const char* dex_filename = dex_filenames[i];
3885b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom    const DexFile* dex_file = DexFile::Open(dex_filename, strip_location_prefix);
3895b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom    if (dex_file == NULL) {
3905b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom      fprintf(stderr, "could not open .dex from file %s\n", dex_filename);
3915b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom      exit(EXIT_FAILURE);
3925b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom    }
3935b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom    dex_files.push_back(dex_file);
3945b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom  }
3955b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom}
3965b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom
3975b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom
39869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstromint dex2oat(int argc, char** argv) {
39969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  // Skip over argv[0].
40069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  argv++;
40169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  argc--;
40269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
40369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  if (argc == 0) {
40469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    fprintf(stderr, "no arguments specified\n");
40569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    usage();
40669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  }
40769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
40869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  std::vector<const char*> dex_filenames;
409a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  int zip_fd = -1;
410a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  std::string zip_name;
411e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  std::string oat_filename;
412a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  int oat_fd = -1;
413a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  std::string oat_name;
41469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  const char* image_filename = NULL;
415ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  const char* image_classes_filename = NULL;
416b001126eb9e47d0088b3672652454c53f4e17e9fBrian Carlstrom  std::string boot_image_filename;
41769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  uintptr_t image_base = 0;
41858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  std::string host_prefix;
4195d84040e2231de1d48e6f30cab2cc8d4beb8effejeffhao  std::vector<const char*> runtime_args;
42097574f4589041ecb652ff30a0fb5e55eeffb5ea0Brian Carlstrom#if defined(__APPLE__)
42197574f4589041ecb652ff30a0fb5e55eeffb5ea0Brian Carlstrom  // Apple lacks GetOwner and therefore working Mutexes, so only use one thread on that platform
42297574f4589041ecb652ff30a0fb5e55eeffb5ea0Brian Carlstrom  int thread_count = 1;
42397574f4589041ecb652ff30a0fb5e55eeffb5ea0Brian Carlstrom#else
4245523ee070b005576c6f889415205d49ea77cf243Elliott Hughes  int thread_count = 2;
42597574f4589041ecb652ff30a0fb5e55eeffb5ea0Brian Carlstrom#endif
426161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom
42769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  for (int i = 0; i < argc; i++) {
42869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    const StringPiece option(argv[i]);
429a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    bool log_options = false;
430a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    if (log_options) {
431b7bbba49d88eae58223d9878da4069bf6d7140bfBrian Carlstrom      LOG(INFO) << "dex2oat: option[" << i << "]=" << argv[i];
432b7bbba49d88eae58223d9878da4069bf6d7140bfBrian Carlstrom    }
43369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    if (option.starts_with("--dex-file=")) {
43469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      dex_filenames.push_back(option.substr(strlen("--dex-file=")).data());
435a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    } else if (option.starts_with("--zip-fd=")) {
436a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      const char* zip_fd_str = option.substr(strlen("--zip-fd=")).data();
437bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes      if (!ParseInt(zip_fd_str, &zip_fd)) {
438866c8627626b7c47fb69b498b341772d7dfa7f60Brian Carlstrom        fprintf(stderr, "could not parse --zip-fd argument '%s' as an integer\n", zip_fd_str);
439a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom        usage();
440a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      }
441a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    } else if (option.starts_with("--zip-name=")) {
442a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      zip_name = option.substr(strlen("--zip-name=")).data();
443a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    } else if (option.starts_with("--oat-file=")) {
444a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      oat_filename = option.substr(strlen("--oat-file=")).data();
445a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    } else if (option.starts_with("--oat-fd=")) {
446a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      const char* oat_fd_str = option.substr(strlen("--oat-fd=")).data();
447bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes      if (!ParseInt(oat_fd_str, &oat_fd)) {
448866c8627626b7c47fb69b498b341772d7dfa7f60Brian Carlstrom        fprintf(stderr, "could not parse --oat-fd argument '%s' as an integer\n", oat_fd_str);
449a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom        usage();
450a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      }
4515523ee070b005576c6f889415205d49ea77cf243Elliott Hughes    } else if (option.starts_with("-j")) {
45297574f4589041ecb652ff30a0fb5e55eeffb5ea0Brian Carlstrom#if! defined(__APPLE__)
453b12552a95d68b9e4a567103190074ae47b6a61dcBrian Carlstrom      const char* thread_count_str = option.substr(strlen("-j")).data();
45497574f4589041ecb652ff30a0fb5e55eeffb5ea0Brian Carlstrom      // Apple lacks GetOwner and therefore working Mutexes, so we ignore -j on that platform
4555523ee070b005576c6f889415205d49ea77cf243Elliott Hughes      if (!ParseInt(thread_count_str, &thread_count)) {
4565523ee070b005576c6f889415205d49ea77cf243Elliott Hughes        fprintf(stderr, "could not parse -j argument '%s' as an integer\n", thread_count_str);
4575523ee070b005576c6f889415205d49ea77cf243Elliott Hughes        usage();
4585523ee070b005576c6f889415205d49ea77cf243Elliott Hughes      }
45997574f4589041ecb652ff30a0fb5e55eeffb5ea0Brian Carlstrom#endif
460a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    } else if (option.starts_with("--oat-name=")) {
461a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      oat_name = option.substr(strlen("--oat-name=")).data();
46269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    } else if (option.starts_with("--image=")) {
46369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      image_filename = option.substr(strlen("--image=")).data();
464ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    } else if (option.starts_with("--image-classes=")) {
465ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      image_classes_filename = option.substr(strlen("--image-classes=")).data();
46669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    } else if (option.starts_with("--base=")) {
46769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      const char* image_base_str = option.substr(strlen("--base=")).data();
46869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      char* end;
46969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      image_base = strtoul(image_base_str, &end, 16);
47069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      if (end == image_base_str || *end != '\0') {
47127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        fprintf(stderr, "Failed to parse hexadecimal value for option %s\n", option.data());
47269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom        usage();
47369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      }
474e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    } else if (option.starts_with("--boot-image=")) {
475b001126eb9e47d0088b3672652454c53f4e17e9fBrian Carlstrom      boot_image_filename = option.substr(strlen("--boot-image=")).data();
47658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    } else if (option.starts_with("--host-prefix=")) {
47758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom      host_prefix = option.substr(strlen("--host-prefix=")).data();
4785d84040e2231de1d48e6f30cab2cc8d4beb8effejeffhao    } else if (option == "--runtime-arg") {
4795d84040e2231de1d48e6f30cab2cc8d4beb8effejeffhao      if (++i >= argc) {
4805d84040e2231de1d48e6f30cab2cc8d4beb8effejeffhao        fprintf(stderr, "Missing required argument for --runtime-arg\n");
4815d84040e2231de1d48e6f30cab2cc8d4beb8effejeffhao        usage();
4825d84040e2231de1d48e6f30cab2cc8d4beb8effejeffhao      }
483a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      if (log_options) {
484a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom        LOG(INFO) << "dex2oat: option[" << i << "]=" << argv[i];
485a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      }
4865d84040e2231de1d48e6f30cab2cc8d4beb8effejeffhao      runtime_args.push_back(argv[i]);
48769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    } else {
48869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      fprintf(stderr, "unknown argument %s\n", option.data());
48969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      usage();
49069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    }
49169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  }
49269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
493a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  if (oat_filename.empty() && oat_fd == -1) {
494a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    fprintf(stderr, "Output must be supplied with either --oat-file or --oat-fd\n");
495a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    return EXIT_FAILURE;
496a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  }
497a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom
498a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  if (!oat_filename.empty() && oat_fd != -1) {
499a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    fprintf(stderr, "--oat-file should not be used with --oat-fd\n");
500a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    return EXIT_FAILURE;
501a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  }
502a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom
503a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  if (!oat_filename.empty() && oat_fd != -1) {
504a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    fprintf(stderr, "--oat-file should not be used with --oat-fd\n");
505a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    return EXIT_FAILURE;
506a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  }
507a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom
508a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  if (!oat_filename.empty() && !oat_name.empty()) {
509a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    fprintf(stderr, "--oat-file should not be used with --oat-name\n");
510a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    return EXIT_FAILURE;
511a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  }
512a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom
513a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  if (oat_fd != -1 && oat_name.empty()) {
514a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    fprintf(stderr, "--oat-name should be supplied with --oat-fd\n");
515a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    return EXIT_FAILURE;
516a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  }
517a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom
518a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  if (oat_fd != -1 && image_filename != NULL) {
519a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    fprintf(stderr, "--oat-fd should not be used with --image\n");
520362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    return EXIT_FAILURE;
521e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
522e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
523b001126eb9e47d0088b3672652454c53f4e17e9fBrian Carlstrom  if (host_prefix.empty()) {
524b001126eb9e47d0088b3672652454c53f4e17e9fBrian Carlstrom    const char* android_product_out = getenv("ANDROID_PRODUCT_OUT");
525b001126eb9e47d0088b3672652454c53f4e17e9fBrian Carlstrom    if (android_product_out != NULL) {
526b001126eb9e47d0088b3672652454c53f4e17e9fBrian Carlstrom        host_prefix = android_product_out;
527b001126eb9e47d0088b3672652454c53f4e17e9fBrian Carlstrom    }
528b001126eb9e47d0088b3672652454c53f4e17e9fBrian Carlstrom  }
529b001126eb9e47d0088b3672652454c53f4e17e9fBrian Carlstrom
530ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  bool image = (image_filename != NULL);
531b001126eb9e47d0088b3672652454c53f4e17e9fBrian Carlstrom  if (!image && boot_image_filename.empty()) {
532b001126eb9e47d0088b3672652454c53f4e17e9fBrian Carlstrom    boot_image_filename += host_prefix;
533a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    boot_image_filename += "/system/framework/boot.art";
534b001126eb9e47d0088b3672652454c53f4e17e9fBrian Carlstrom  }
535b001126eb9e47d0088b3672652454c53f4e17e9fBrian Carlstrom  std::string boot_image_option;
536b001126eb9e47d0088b3672652454c53f4e17e9fBrian Carlstrom  if (boot_image_filename != NULL) {
537b001126eb9e47d0088b3672652454c53f4e17e9fBrian Carlstrom    boot_image_option += "-Ximage:";
538b001126eb9e47d0088b3672652454c53f4e17e9fBrian Carlstrom    boot_image_option += boot_image_filename;
53969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  }
54069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
541ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (image_classes_filename != NULL && !image) {
542ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    fprintf(stderr, "--image-classes should only be used with --image\n");
543ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    return EXIT_FAILURE;
544ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
545ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
546ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (image_classes_filename != NULL && !boot_image_option.empty()) {
547ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    fprintf(stderr, "--image-classes should not be used with --boot-image\n");
548362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    return EXIT_FAILURE;
54978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
55078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
551a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  if (dex_filenames.empty() && zip_fd == -1) {
552a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    fprintf(stderr, "Input must be supplied with either --dex-file or --zip-fd\n");
553a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    return EXIT_FAILURE;
554a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  }
555a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom
556a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  if (!dex_filenames.empty() && zip_fd != -1) {
557a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    fprintf(stderr, "--dex-file should not be used with --zip-fd\n");
558a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    return EXIT_FAILURE;
559a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  }
560a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom
561a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  if (!dex_filenames.empty() && !zip_name.empty()) {
562a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    fprintf(stderr, "--dex-file should not be used with --zip-name\n");
563a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    return EXIT_FAILURE;
564a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  }
565a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom
566a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  if (zip_fd != -1 && zip_name.empty()) {
567a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    fprintf(stderr, "--zip-name should be supplied with --zip-fd\n");
568a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    return EXIT_FAILURE;
569a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  }
570a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom
57169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  if (boot_image_option.empty()) {
57269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    if (image_base == 0) {
57369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      fprintf(stderr, "non-zero --base not specified\n");
57469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      return EXIT_FAILURE;
57569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    }
57669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  }
57769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
5786ef827a33b04fd5413d2ad88fd4599ca1920c824Brian Carlstrom  // Check early that the result of compilation can be written
579a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  UniquePtr<File> oat_file;
580a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  if (!oat_filename.empty()) {
581a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    oat_file.reset(OS::OpenFile(oat_filename.c_str(), true));
582a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    oat_name = oat_filename;
583a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  } else {
584a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    oat_file.reset(OS::FileFromFd(oat_name.c_str(), oat_fd));
585a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  }
5866ef827a33b04fd5413d2ad88fd4599ca1920c824Brian Carlstrom  if (oat_file.get() == NULL) {
587fd8cba4ad6d4d0586dc783c031383a9ca953372dElliott Hughes    PLOG(ERROR) << "Unable to create oat file: " << oat_name;
5886ef827a33b04fd5413d2ad88fd4599ca1920c824Brian Carlstrom    return EXIT_FAILURE;
589234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes  }
590a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom
591a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  LOG(INFO) << "dex2oat: " << oat_name;
5925e863ddd72a70d33525f7403a695f7bc1c218938Ian Rogers
59369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  Runtime::Options options;
5945de8fe5253ca8bd285cba0eb2e56930573ea4c7fBrian Carlstrom  options.push_back(std::make_pair("compiler", reinterpret_cast<void*>(NULL)));
595b7bbba49d88eae58223d9878da4069bf6d7140bfBrian Carlstrom  std::string boot_class_path_string;
59669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  if (boot_image_option.empty()) {
59758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    boot_class_path_string += "-Xbootclasspath:";
59858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    for (size_t i = 0; i < dex_filenames.size()-1; i++) {
59958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom      boot_class_path_string += dex_filenames[i];
60058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom      boot_class_path_string += ":";
60158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    }
60258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    boot_class_path_string += dex_filenames[dex_filenames.size()-1];
60358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    options.push_back(std::make_pair(boot_class_path_string.c_str(), reinterpret_cast<void*>(NULL)));
60469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  } else {
60569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL)));
60669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  }
60758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  if (!host_prefix.empty()) {
60858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    options.push_back(std::make_pair("host-prefix", host_prefix.c_str()));
60958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  }
6105d84040e2231de1d48e6f30cab2cc8d4beb8effejeffhao  for (size_t i = 0; i < runtime_args.size(); i++) {
6115d84040e2231de1d48e6f30cab2cc8d4beb8effejeffhao    options.push_back(std::make_pair(runtime_args[i], reinterpret_cast<void*>(NULL)));
6125d84040e2231de1d48e6f30cab2cc8d4beb8effejeffhao  }
61369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
6145523ee070b005576c6f889415205d49ea77cf243Elliott Hughes  UniquePtr<Dex2Oat> dex2oat(Dex2Oat::Create(options, thread_count));
61569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
616bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes  // If --image-classes was specified, calculate the full list of classes to include in the image
617ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  UniquePtr<const std::set<std::string> > image_classes(NULL);
618ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (image_classes_filename != NULL) {
619ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    image_classes.reset(dex2oat->GetImageClassDescriptors(image_classes_filename));
620ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    if (image_classes.get() == NULL) {
621ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      LOG(ERROR) << "Failed to create list of image classes from " << image_classes_filename;
622ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      return EXIT_FAILURE;
62369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    }
62469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  }
62569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
626a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  std::vector<const DexFile*> dex_files;
627a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  if (boot_image_option.empty()) {
628a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    dex_files = Runtime::Current()->GetClassLinker()->GetBootClassPath();
629a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  } else {
630a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    if (dex_filenames.empty()) {
631a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      UniquePtr<ZipArchive> zip_archive(ZipArchive::OpenFromFd(zip_fd));
632a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      if (zip_archive.get() == NULL) {
633a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom        LOG(ERROR) << "Failed to zip from file descriptor for " << zip_name;
6342e3d1b262af0839380e1d60e86d8b281943ef944Brian Carlstrom        return EXIT_FAILURE;
635a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      }
636a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      const DexFile* dex_file = DexFile::Open(*zip_archive.get(), zip_name);
637a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      if (dex_file == NULL) {
638fd8cba4ad6d4d0586dc783c031383a9ca953372dElliott Hughes        LOG(ERROR) << "Failed to open dex from file descriptor for zip file: " << zip_name;
639a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom        return EXIT_FAILURE;
640a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      }
641a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      dex_files.push_back(dex_file);
642a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    } else {
6435b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom      OpenDexFiles(dex_filenames, dex_files, host_prefix);
644a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    }
645a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom  }
646a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom
647ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (!dex2oat->CreateOatFile(boot_image_option,
648a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom                              dex_files,
649ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                              oat_file.get(),
650ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                              image,
651ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                              image_classes.get())) {
652fd8cba4ad6d4d0586dc783c031383a9ca953372dElliott Hughes    LOG(ERROR) << "Failed to create oat file: " << oat_name;
653e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    return EXIT_FAILURE;
654e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
655e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
656ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (!image) {
657fd8cba4ad6d4d0586dc783c031383a9ca953372dElliott Hughes    LOG(INFO) << "Oat file written successfully: " << oat_name;
658aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    return EXIT_SUCCESS;
659aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
660aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
661ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (!dex2oat->CreateImageFile(image_filename,
662ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                image_base,
663ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                image_classes.get(),
664ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                oat_filename,
665ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                host_prefix)) {
66669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    return EXIT_FAILURE;
66769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  }
66869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
669ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  // We wrote the oat file successfully, and want to keep it.
670bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes  LOG(INFO) << "Oat file written successfully: " << oat_filename;
671bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes  LOG(INFO) << "Image written successfully: " << image_filename;
67269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  return EXIT_SUCCESS;
67369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom}
67469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
67569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom} // namespace art
67669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
67769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstromint main(int argc, char** argv) {
67869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  return art::dex2oat(argc, argv);
67969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom}
680