oatdump.cc revision b23a7729cf7855fa05345d03a4d84111d5ec7172
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 */
1678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
1778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include <stdio.h>
1878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include <stdlib.h>
1978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
2027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom#include <fstream>
2127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom#include <iostream>
2278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include <string>
2378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include <vector>
2478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
2578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "class_linker.h"
26e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes#include "dex_instruction.h"
273a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers#include "disassembler.h"
28916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom#include "file.h"
2978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "image.h"
3057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers#include "oat/runtime/context.h"  // For VmapTable
316d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h"
32e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes#include "os.h"
3378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "runtime.h"
34a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes#include "safe_map.h"
3500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h"
367469ebf3888b8037421cb6834f37f946646265ecMathieu Chartier#include "gc/space.h"
3778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "stringpiece.h"
380c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "gc_map.h"
3978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
4078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromnamespace art {
4178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
4278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromstatic void usage() {
4378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  fprintf(stderr,
4478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom          "Usage: oatdump [options] ...\n"
4529e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "    Example: oatdump --image=$ANDROID_PRODUCT_OUT/system/framework/boot.art --host-prefix=$ANDROID_PRODUCT_OUT\n"
4629e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "    Example: adb shell oatdump --image=/system/framework/boot.art\n"
4778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom          "\n");
4878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  fprintf(stderr,
49a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "  --oat-file=<file.oat>: specifies an input oat filename.\n"
5029e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "      Example: --image=/system/framework/boot.oat\n"
51aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom          "\n");
52aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  fprintf(stderr,
53aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom          "  --image=<file.art>: specifies an input image filename.\n"
5429e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "      Example: --image=/system/framework/boot.art\n"
55e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom          "\n");
5678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  fprintf(stderr,
57e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom          "  --boot-image=<file.art>: provide the image file for the boot class path.\n"
5829e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "      Example: --boot-image=/system/framework/boot.art\n"
59e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom          "\n");
60e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  fprintf(stderr,
6158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom          "  --host-prefix may be used to translate host paths to target paths during\n"
6258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom          "      cross compilation.\n"
6358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom          "      Example: --host-prefix=out/target/product/crespo\n"
64fe487d0c789b94e75c93a2b799f1955c3e4edb10Brian Carlstrom          "      Default: $ANDROID_PRODUCT_OUT\n"
6578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom          "\n");
6627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  fprintf(stderr,
6727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom          "  --output=<file> may be used to send the output to a file.\n"
6827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom          "      Example: --output=/tmp/oatdump.txt\n"
6927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom          "\n");
7078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  exit(EXIT_FAILURE);
7178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom}
7278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
73ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogersconst char* image_roots_descriptions_[] = {
7478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  "kJniStubArray",
75e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  "kAbstractMethodErrorStubArray",
76ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  "kStaticResolutionStubArray",
771cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  "kUnknownMethodResolutionStubArray",
781984651929744dd603fd082e23eacd877b9bc177Ian Rogers  "kResolutionMethod",
79e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  "kCalleeSaveMethod",
80aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  "kRefsOnlySaveMethod",
81aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  "kRefsAndArgsSaveMethod",
82e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  "kOatLocation",
8358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  "kDexCaches",
8434f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom  "kClassRoots",
8578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom};
8678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
87e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughesclass OatDumper {
88aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom public:
8981f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom  explicit OatDumper(const std::string& host_prefix, const OatFile& oat_file)
9081f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    : host_prefix_(host_prefix),
9181f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom      oat_file_(oat_file),
92a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes      oat_dex_files_(oat_file.GetOatDexFiles()),
93a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes      disassembler_(Disassembler::Create(oat_file_.GetOatHeader().GetInstructionSet())) {
943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    AddAllOffsets();
953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
963a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
973a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void Dump(std::ostream& os) {
983a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    const OatHeader& oat_header = oat_file_.GetOatHeader();
99aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
100aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "MAGIC:\n";
101aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << oat_header.GetMagic() << "\n\n";
102aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
103aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "CHECKSUM:\n";
104ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes    os << StringPrintf("0x%08x\n\n", oat_header.GetChecksum());
105aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
106a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes    os << "INSTRUCTION SET:\n";
107a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes    os << oat_header.GetInstructionSet() << "\n\n";
108a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes
109aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "DEX FILE COUNT:\n";
110aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << oat_header.GetDexFileCount() << "\n\n";
111aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
112aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "EXECUTABLE OFFSET:\n";
113ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes    os << StringPrintf("0x%08x\n\n", oat_header.GetExecutableOffset());
114aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
11581f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    os << "IMAGE FILE LOCATION CHECKSUM:\n";
11681f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationChecksum());
11781f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
11881f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    os << "IMAGE FILE LOCATION:\n";
11981f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    const std::string image_file_location(oat_header.GetImageFileLocation());
12081f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    os << image_file_location;
12181f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    if (!image_file_location.empty() && !host_prefix_.empty()) {
12281f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom      os << " (" << host_prefix_ << image_file_location << ")";
12381f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    }
12481f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    os << "\n\n";
12581f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
12630fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << "BEGIN:\n";
1273a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << reinterpret_cast<const void*>(oat_file_.Begin()) << "\n\n";
128aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
12930fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << "END:\n";
1303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << reinterpret_cast<const void*>(oat_file_.End()) << "\n\n";
131aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
132aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << std::flush;
133aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
1343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    for (size_t i = 0; i < oat_dex_files_.size(); i++) {
1353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
1363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      CHECK(oat_dex_file != NULL);
1373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      DumpOatDexFile(os, *oat_dex_file);
1383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
1393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
1403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  size_t ComputeSize(const void* oat_data) {
1423a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (reinterpret_cast<const byte*>(oat_data) < oat_file_.Begin() ||
1433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        reinterpret_cast<const byte*>(oat_data) > oat_file_.End()) {
1443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      return 0;  // Address not in oat file
1453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
1463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    uint32_t begin_offset = reinterpret_cast<size_t>(oat_data) -
1473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                            reinterpret_cast<size_t>(oat_file_.Begin());
1483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    typedef std::set<uint32_t>::iterator It;
1493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    It it = offsets_.upper_bound(begin_offset);
1503a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    CHECK(it != offsets_.end());
1513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    uint32_t end_offset = *it;
1523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    return end_offset - begin_offset;
1533a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
154e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
155f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  InstructionSet GetInstructionSet() {
156f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    return oat_file_.GetOatHeader().GetInstructionSet();
157f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  }
158f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom
15966f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier  const void* GetOatCode(AbstractMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    MethodHelper mh(m);
1613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    for (size_t i = 0; i < oat_dex_files_.size(); i++) {
1623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
163aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      CHECK(oat_dex_file != NULL);
1643a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      UniquePtr<const DexFile> dex_file(oat_dex_file->OpenDexFile());
1653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if (dex_file.get() != NULL) {
1663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        uint32_t class_def_index;
1673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        bool found = dex_file->FindClassDefIndex(mh.GetDeclaringClassDescriptor(), class_def_index);
1683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (found) {
1693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          const OatFile::OatClass* oat_class = oat_dex_file->GetOatClass(class_def_index);
1703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          CHECK(oat_class != NULL);
1713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          size_t method_index = m->GetMethodIndex();
1723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          return oat_class->GetOatMethod(method_index).GetCode();
1733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
1743a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
175aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
1763a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    return NULL;
177aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
178aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
179aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom private:
1803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void AddAllOffsets() {
181e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // We don't know the length of the code for each method, but we need to know where to stop
182e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // when disassembling. What we do know is that a region of code will be followed by some other
183e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // region, so if we keep a sorted sequence of the start of each region, we can infer the length
184e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // of a piece of code by using upper_bound to find the start of the next region.
1853a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    for (size_t i = 0; i < oat_dex_files_.size(); i++) {
1863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
187e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      CHECK(oat_dex_file != NULL);
188e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      UniquePtr<const DexFile> dex_file(oat_dex_file->OpenDexFile());
189e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      if (dex_file.get() == NULL) {
1903a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        continue;
191e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      }
1923a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      offsets_.insert(reinterpret_cast<uint32_t>(&dex_file->GetHeader()));
193e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      for (size_t class_def_index = 0; class_def_index < dex_file->NumClassDefs(); class_def_index++) {
194e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes        const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
195e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes        UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(class_def_index));
196e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes        const byte* class_data = dex_file->GetClassData(class_def);
197e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes        if (class_data != NULL) {
198e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          ClassDataItemIterator it(*dex_file, class_data);
199e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          SkipAllFields(it);
200e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          uint32_t class_method_index = 0;
201e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          while (it.HasNextDirectMethod()) {
202e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes            AddOffsets(oat_class->GetOatMethod(class_method_index++));
203e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes            it.Next();
204e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          }
205e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          while (it.HasNextVirtualMethod()) {
206e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes            AddOffsets(oat_class->GetOatMethod(class_method_index++));
207e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes            it.Next();
208e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          }
209e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes        }
210e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      }
211e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    }
212e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
213e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // If the last thing in the file is code for a method, there won't be an offset for the "next"
214e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // thing. Instead of having a special case in the upper_bound code, let's just add an entry
215e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // for the end of the file.
2163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    offsets_.insert(static_cast<uint32_t>(oat_file_.End() - oat_file_.Begin()));
217e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  }
218e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
219e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  void AddOffsets(const OatFile::OatMethod& oat_method) {
22095ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom    uint32_t code_offset = oat_method.GetCodeOffset();
22195ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom    if (oat_file_.GetOatHeader().GetInstructionSet() == kThumb2) {
22295ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom      code_offset &= ~0x1;
22395ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom    }
22495ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom    offsets_.insert(code_offset);
225e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    offsets_.insert(oat_method.GetMappingTableOffset());
226e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    offsets_.insert(oat_method.GetVmapTableOffset());
2270c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    offsets_.insert(oat_method.GetNativeGcMapOffset());
228e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    offsets_.insert(oat_method.GetInvokeStubOffset());
229e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  }
230e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
2313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpOatDexFile(std::ostream& os, const OatFile::OatDexFile& oat_dex_file) {
232aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "OAT DEX FILE:\n";
233a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    os << StringPrintf("location: %s\n", oat_dex_file.GetDexFileLocation().c_str());
234ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes    os << StringPrintf("checksum: 0x%08x\n", oat_dex_file.GetDexFileLocationChecksum());
235a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    UniquePtr<const DexFile> dex_file(oat_dex_file.OpenDexFile());
236a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    if (dex_file.get() == NULL) {
237aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      os << "NOT FOUND\n\n";
238aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      return;
239aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
240aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    for (size_t class_def_index = 0; class_def_index < dex_file->NumClassDefs(); class_def_index++) {
241aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
242aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      const char* descriptor = dex_file->GetClassDescriptor(class_def);
243aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file.GetOatClass(class_def_index));
244aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      CHECK(oat_class.get() != NULL);
245ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("%zd: %s (type_idx=%d) (", class_def_index, descriptor, class_def.class_idx_)
246e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom         << oat_class->GetStatus() << ")\n";
2473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      DumpOatClass(os, *oat_class.get(), *(dex_file.get()), class_def);
248aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
249aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
250aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << std::flush;
251aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
252aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
253e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  static void SkipAllFields(ClassDataItemIterator& it) {
2540571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextStaticField()) {
2550571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
256aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
2570571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextInstanceField()) {
2580571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
259aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
260e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  }
261aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
2623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpOatClass(std::ostream& os, const OatFile::OatClass& oat_class, const DexFile& dex_file,
2633a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                    const DexFile::ClassDef& class_def) {
264e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    const byte* class_data = dex_file.GetClassData(class_def);
265e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    if (class_data == NULL) {  // empty class such as a marker interface?
266e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      return;
267e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    }
268e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    ClassDataItemIterator it(dex_file, class_data);
269e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    SkipAllFields(it);
270e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
271e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    uint32_t class_method_index = 0;
2720571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextDirectMethod()) {
273e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      const OatFile::OatMethod oat_method = oat_class.GetOatMethod(class_method_index);
2743a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      DumpOatMethod(os, class_method_index, oat_method, dex_file,
2753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                    it.GetMemberIndex(), it.GetMethodCodeItem());
276e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      class_method_index++;
2770571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
278aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
2790571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextVirtualMethod()) {
280e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      const OatFile::OatMethod oat_method = oat_class.GetOatMethod(class_method_index);
2813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      DumpOatMethod(os, class_method_index, oat_method, dex_file,
2823a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                    it.GetMemberIndex(), it.GetMethodCodeItem());
283e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      class_method_index++;
2840571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
285aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
2860571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    DCHECK(!it.HasNext());
287aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << std::flush;
288aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
289e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
2903a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpOatMethod(std::ostream& os, uint32_t class_method_index,
291e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes                     const OatFile::OatMethod& oat_method, const DexFile& dex_file,
292e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes                     uint32_t dex_method_idx, const DexFile::CodeItem* code_item) {
293db7bdc1086c44fe628b6743f98d7d85a5c03343aIan Rogers    os << StringPrintf("\t%d: %s (dex_method_idx=%d)\n",
294db7bdc1086c44fe628b6743f98d7d85a5c03343aIan Rogers                       class_method_index, PrettyMethod(dex_method_idx, dex_file, true).c_str(),
295db7bdc1086c44fe628b6743f98d7d85a5c03343aIan Rogers                       dex_method_idx);
296b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    os << StringPrintf("\t\tframe_size_in_bytes: %zd\n", oat_method.GetFrameSizeInBytes());
297b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    os << StringPrintf("\t\tcore_spill_mask: 0x%08x\n", oat_method.GetCoreSpillMask());
2983a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    DumpSpillMask(os, oat_method.GetCoreSpillMask(), false);
299b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    os << StringPrintf("\n\t\tfp_spill_mask: 0x%08x\n", oat_method.GetFpSpillMask());
3003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    DumpSpillMask(os, oat_method.GetFpSpillMask(), true);
301ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes    os << StringPrintf("\t\tvmap_table: %p (offset=0x%08x)\n",
302ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetVmapTable(), oat_method.GetVmapTableOffset());
303b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    DumpVmap(os, oat_method);
304b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    const bool kDumpRawMappingTable = false;
305b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    if (kDumpRawMappingTable) {
306b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      os << StringPrintf("\t\tmapping_table: %p (offset=0x%08x)\n",
307b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers                         oat_method.GetMappingTable(), oat_method.GetMappingTableOffset());
308b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      DumpMappingTable(os, oat_method);
309b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    }
310b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    const bool kDumpRawGcMap = false;
311b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    if (kDumpRawGcMap) {
312b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      os << StringPrintf("\t\tgc_map: %p (offset=0x%08x)\n",
313b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers                         oat_method.GetNativeGcMap(), oat_method.GetNativeGcMapOffset());
314b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      DumpGcMap(os, oat_method, code_item);
315b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    }
316b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    os << "\t\tDEX CODE:\n";
317b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    DumpDexCode(os, dex_file, code_item);
318971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien    os << StringPrintf("\t\tCODE: %p (offset=0x%08x size=%d)%s\n",
31977405796564c6c1353807cda18b28678a719bd68Elliott Hughes                       oat_method.GetCode(),
32077405796564c6c1353807cda18b28678a719bd68Elliott Hughes                       oat_method.GetCodeOffset(),
32177405796564c6c1353807cda18b28678a719bd68Elliott Hughes                       oat_method.GetCodeSize(),
32277405796564c6c1353807cda18b28678a719bd68Elliott Hughes                       oat_method.GetCode() != NULL ? "..." : "");
323b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    DumpCode(os, oat_method, code_item);
324971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien    os << StringPrintf("\t\tINVOKE STUB: %p (offset=0x%08x size=%d)%s\n",
32577405796564c6c1353807cda18b28678a719bd68Elliott Hughes                       oat_method.GetInvokeStub(),
32677405796564c6c1353807cda18b28678a719bd68Elliott Hughes                       oat_method.GetInvokeStubOffset(),
32777405796564c6c1353807cda18b28678a719bd68Elliott Hughes                       oat_method.GetInvokeStubSize(),
32877405796564c6c1353807cda18b28678a719bd68Elliott Hughes                       oat_method.GetInvokeStub() != NULL ? "..." : "");
329b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    DumpInvokeStub(os, oat_method);
3303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
3313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
3323a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpSpillMask(std::ostream& os, uint32_t spill_mask, bool is_float) {
3333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (spill_mask == 0) {
3343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      return;
3353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
3363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << " (";
3373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    for (size_t i = 0; i < 32; i++) {
3383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if ((spill_mask & (1 << i)) != 0) {
3393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (is_float) {
3403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          os << "fr" << i;
3413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        } else {
3423a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          os << "r" << i;
3433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
3443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        spill_mask ^= 1 << i;  // clear bit
3453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (spill_mask != 0) {
3463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          os << ", ";
3473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        } else {
3483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          break;
3493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
3503a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
3513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
3523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << ")";
3533a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
3543a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
355b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  void DumpVmap(std::ostream& os, const OatFile::OatMethod& oat_method) {
356b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    const uint16_t* raw_table = oat_method.GetVmapTable();
3573a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (raw_table == NULL) {
3583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      return;
3593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
3603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    const VmapTable vmap_table(raw_table);
3613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    bool first = true;
3623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << "\t\t\t";
3633a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    for (size_t i = 0; i < vmap_table.size(); i++) {
3643a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      uint16_t dex_reg = vmap_table[i];
3653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t matches = 0;
3663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t spill_shifts = 0;
367b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      uint32_t spill_mask = oat_method.GetCoreSpillMask();
3683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      bool processing_fp = false;
3693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      while (matches != (i + 1)) {
3703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (spill_mask == 0) {
3713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          CHECK(!processing_fp);
372b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          spill_mask = oat_method.GetFpSpillMask();
3733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          processing_fp = true;
3743a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
3753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        matches += spill_mask & 1;  // Add 1 if the low bit is set
3763a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        spill_mask >>= 1;
3773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        spill_shifts++;
3783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
3793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t arm_reg = spill_shifts - 1;  // wind back one as we want the last match
3803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os << (first ? "v" : ", v")  << dex_reg;
3813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if (arm_reg < 16) {
3823a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        os << "/r" << arm_reg;
3833a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      } else {
3843a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        os << "/fr" << (arm_reg - 16);
3853a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
3863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if (first) {
3873a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        first = false;
3883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
3893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
390c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes    os << "\n";
3913a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
3923a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
393b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  void DescribeVReg(std::ostream& os, const OatFile::OatMethod& oat_method,
394b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers                    const DexFile::CodeItem* code_item, size_t reg) {
395b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    const uint16_t* raw_table = oat_method.GetVmapTable();
396b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    if (raw_table != NULL) {
397b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      const VmapTable vmap_table(raw_table);
398b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      uint32_t vmap_offset;
399b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      if (vmap_table.IsInContext(reg, vmap_offset)) {
400b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        // Compute the register we need to load from the context
401b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        uint32_t spill_mask = oat_method.GetCoreSpillMask();
402b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        CHECK_LT(vmap_offset, static_cast<uint32_t>(__builtin_popcount(spill_mask)));
403b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        uint32_t matches = 0;
404b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        uint32_t spill_shifts = 0;
405b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        while (matches != (vmap_offset + 1)) {
406b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          DCHECK_NE(spill_mask, 0u);
407b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          matches += spill_mask & 1;  // Add 1 if the low bit is set
408b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          spill_mask >>= 1;
409b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          spill_shifts++;
410b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        }
411b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        spill_shifts--;  // wind back one as we want the last match
412b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        os << "r" << spill_shifts;
413b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      } else {
414b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        uint32_t offset = StackVisitor::GetVRegOffset(code_item, oat_method.GetCoreSpillMask(),
415b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers                                                      oat_method.GetFpSpillMask(),
416b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers                                                      oat_method.GetFrameSizeInBytes(), reg);
417b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        os << "[sp + #" << offset << "]";
418b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      }
419b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    }
420b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  }
421b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers
422b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  void DumpGcMap(std::ostream& os, const OatFile::OatMethod& oat_method,
423b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers                 const DexFile::CodeItem* code_item) {
424b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    const uint8_t* gc_map_raw = oat_method.GetNativeGcMap();
4253a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (gc_map_raw == NULL) {
4263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      return;
4273a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
4280c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    NativePcOffsetToReferenceMap map(gc_map_raw);
429b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    const void* code = oat_method.GetCode();
4303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    for (size_t entry = 0; entry < map.NumEntries(); entry++) {
431bb6723f9fa8b038dea8bf1ecdb0d698b25bda5e9Ian Rogers      const uint8_t* native_pc = reinterpret_cast<const uint8_t*>(code) +
432bb6723f9fa8b038dea8bf1ecdb0d698b25bda5e9Ian Rogers                                 map.GetNativePcOffset(entry);
433bb6723f9fa8b038dea8bf1ecdb0d698b25bda5e9Ian Rogers      os << StringPrintf("\t\t\t%p", native_pc);
4343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t num_regs = map.RegWidth() * 8;
4353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      const uint8_t* reg_bitmap = map.GetBitMap(entry);
4363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      bool first = true;
4373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      for (size_t reg = 0; reg < num_regs; reg++) {
4383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (((reg_bitmap[reg / 8] >> (reg % 8)) & 0x01) != 0) {
4393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          if (first) {
440b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers            os << "  v" << reg << " (";
441b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers            DescribeVReg(os, oat_method, code_item, reg);
442b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers            os << ")";
4433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            first = false;
4443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          } else {
445b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers            os << ", v" << reg << " (";
446b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers            DescribeVReg(os, oat_method, code_item, reg);
447b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers            os << ")";
4483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          }
4493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
4503a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
451c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes      os << "\n";
4523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
453aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
454e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
4553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpMappingTable(std::ostream& os, const OatFile::OatMethod& oat_method) {
456e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    const uint32_t* raw_table = oat_method.GetMappingTable();
457e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    const void* code = oat_method.GetCode();
458e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    if (raw_table == NULL || code == NULL) {
459e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      return;
460e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    }
461e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
4624d7a18922ef2fcacae97676375e9c877278e6eafbuzbee    ++raw_table;
463e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    uint32_t length = *raw_table;
464e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    ++raw_table;
465a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    uint32_t pc_to_dex_entries = *raw_table;
466a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    ++raw_table;
467e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
468b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    os << "\t\tsuspend point mappings {";
469e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    for (size_t i = 0; i < length; i += 2) {
4703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      const uint8_t* native_pc = reinterpret_cast<const uint8_t*>(code) + raw_table[i];
471e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      uint32_t dex_pc = raw_table[i + 1];
4723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os << StringPrintf("%p -> 0x%04x", native_pc, dex_pc);
473a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      if (i + 2 == pc_to_dex_entries) {
474a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee        // Separate the pc -> dex from dex -> pc sections
475b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        os << "}\n\t\tcatch entry mappings {";
476a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      } else if (i + 2 < length) {
4773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        os << ", ";
4783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
4793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
480b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    os << "}\n";
4813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
4823a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
483b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  void DumpMappingAtOffset(std::ostream& os, const OatFile::OatMethod& oat_method, size_t offset,
484b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers                           bool suspend_point_mapping) {
485b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    const uint32_t* raw_table = oat_method.GetMappingTable();
486b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    if (raw_table != NULL) {
487b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      ++raw_table;
488b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      uint32_t length = *raw_table;
489b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      ++raw_table;
490b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      uint32_t pc_to_dex_entries = *raw_table;
491b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      ++raw_table;
492b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      size_t start, end;
493b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      if (suspend_point_mapping) {
494b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        start = 0;
495b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        end = pc_to_dex_entries;
496b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      } else {
497b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        start = pc_to_dex_entries;
498b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        end = length;
499b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      }
500b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      for (size_t i = start; i < end; i += 2) {
501b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        if (offset == raw_table[i]) {
502b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          if (suspend_point_mapping) {
503b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers            os << "\t\t\tsuspend point dex PC: ";
504b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          } else {
505b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers            os << "\t\t\tcatch entry dex PC: ";
506b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          }
507b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          os << raw_table[i + 1] << "\n";
508b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          return;
509b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        }
510b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      }
5113a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
512b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  }
5133a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
514b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  void DumpGcMapAtOffset(std::ostream& os, const OatFile::OatMethod& oat_method,
515b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers                         const DexFile::CodeItem* code_item, size_t offset) {
516b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    const uint8_t* gc_map_raw = oat_method.GetNativeGcMap();
517b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    if (gc_map_raw != NULL) {
518b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      NativePcOffsetToReferenceMap map(gc_map_raw);
519b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      if (map.HasEntry(offset)) {
520b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        size_t num_regs = map.RegWidth() * 8;
521b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        const uint8_t* reg_bitmap = map.FindBitMap(offset);
522b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        bool first = true;
523b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        for (size_t reg = 0; reg < num_regs; reg++) {
524b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          if (((reg_bitmap[reg / 8] >> (reg % 8)) & 0x01) != 0) {
525b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers            if (first) {
526b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers              os << "\t\t\tGC map objects:  v" << reg << " (";
527b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers              DescribeVReg(os, oat_method, code_item, reg);
528b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers              os << ")";
529b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers              first = false;
530b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers            } else {
531b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers              os << ", v" << reg << " (";
532b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers              DescribeVReg(os, oat_method, code_item, reg);
533b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers              os << ")";
534b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers            }
535b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          }
536b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        }
537b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        if (!first) {
538b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          os << "\n";
539b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        }
540b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      }
5413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
542b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  }
5433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
544b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  void DumpDexCode(std::ostream& os, const DexFile& dex_file, const DexFile::CodeItem* code_item) {
545b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    if (code_item != NULL) {
546b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      size_t i = 0;
547b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      while (i < code_item->insns_size_in_code_units_) {
548b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        const Instruction* instruction = Instruction::At(&code_item->insns_[i]);
549b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        os << StringPrintf("\t\t\t0x%04x: %s\n", i, instruction->DumpString(&dex_file).c_str());
550b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        i += instruction->SizeInCodeUnits();
551e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      }
552e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    }
553b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  }
554b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers
555b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  void DumpCode(std::ostream& os, const OatFile::OatMethod& oat_method,
556b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers                const DexFile::CodeItem* code_item) {
557b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    const void* code = oat_method.GetCode();
558b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    size_t code_size = oat_method.GetCodeSize();
559b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    if (code == NULL || code_size == 0) {
560b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      os << "\t\t\tNO CODE!\n";
561b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      return;
562b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    }
563b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    const uint8_t* native_pc = reinterpret_cast<const uint8_t*>(code);
564b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    size_t offset = 0;
565b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    while (offset < code_size) {
566b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      DumpMappingAtOffset(os, oat_method, offset, false);
567b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      offset += disassembler_->Dump(os, native_pc + offset);
568b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      DumpMappingAtOffset(os, oat_method, offset, true);
569b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      DumpGcMapAtOffset(os, oat_method, code_item, offset);
570b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    }
571b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  }
572b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers
573b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  void DumpInvokeStub(std::ostream& os, const OatFile::OatMethod& oat_method) {
574b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    const uint8_t* begin = reinterpret_cast<const uint8_t*>(oat_method.GetInvokeStub());
575b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    const uint8_t* end = begin + oat_method.GetInvokeStubSize();
576b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    disassembler_->Dump(os, begin, end);
577e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  }
578e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
57981f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom  const std::string host_prefix_;
5803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  const OatFile& oat_file_;
5813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  std::vector<const OatFile::OatDexFile*> oat_dex_files_;
582e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  std::set<uint32_t> offsets_;
5833a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  UniquePtr<Disassembler> disassembler_;
584aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom};
585aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
5863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogersclass ImageDumper {
58727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom public:
5883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  explicit ImageDumper(std::ostream& os, const std::string& image_filename,
5893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                       const std::string& host_prefix, Space& image_space,
590ca190666fb11820153f74274c495ba1f913d8a69Ian Rogers                       const ImageHeader& image_header)
591ca190666fb11820153f74274c495ba1f913d8a69Ian Rogers      : os_(os), image_filename_(image_filename), host_prefix_(host_prefix),
592ca190666fb11820153f74274c495ba1f913d8a69Ian Rogers        image_space_(image_space), image_header_(image_header) {}
59327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
594b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers  void Dump() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
5953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "MAGIC:\n";
5963a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << image_header_.GetMagic() << "\n\n";
597e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
5983a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "IMAGE BEGIN:\n";
5993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << reinterpret_cast<void*>(image_header_.GetImageBegin()) << "\n\n";
600aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
6013a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "OAT CHECKSUM:\n";
6023a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << StringPrintf("0x%08x\n\n", image_header_.GetOatChecksum());
603916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
6043a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "OAT BEGIN:\n";
6053a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << reinterpret_cast<void*>(image_header_.GetOatBegin()) << "\n\n";
606aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
6073a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "OAT END:\n";
6083a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << reinterpret_cast<void*>(image_header_.GetOatEnd()) << "\n\n";
6093a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
6103a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "ROOTS:\n";
6113a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << reinterpret_cast<void*>(image_header_.GetImageRoots()) << "\n";
612418d20fc407052d4152157f61e7453359f902383Elliott Hughes    CHECK_EQ(arraysize(image_roots_descriptions_), size_t(ImageHeader::kImageRootsMax));
61327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
61427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i);
61534f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom      const char* image_root_description = image_roots_descriptions_[i];
6163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      Object* image_root_object = image_header_.GetImageRoot(image_root);
6173a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os_ << StringPrintf("%s: %p\n", image_root_description, image_root_object);
61834f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom      if (image_root_object->IsObjectArray()) {
61934f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        // TODO: replace down_cast with AsObjectArray (g++ currently has a problem with this)
62034f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        ObjectArray<Object>* image_root_object_array
62134f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom            = down_cast<ObjectArray<Object>*>(image_root_object);
62234f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        //  = image_root_object->AsObjectArray<Object>();
62334f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        for (int i = 0; i < image_root_object_array->GetLength(); i++) {
624d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          Object* value = image_root_object_array->Get(i);
625d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          if (value != NULL) {
6263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            os_ << "\t" << i << ": ";
627d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            std::string summary;
628d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            PrettyObjectValue(summary, value->GetClass(), value);
6293a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            os_ << summary;
630d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          } else {
6313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            os_ << StringPrintf("\t%d: null\n", i);
632d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          }
63334f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        }
63434f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom      }
63527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    }
6363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "\n";
63727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
6384dcbffb3c6e8757d127dede32c8efa6c04e44a70Brian Carlstrom    os_ << "OAT LOCATION:\n" << std::flush;
639aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
6403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    Object* oat_location_object = image_header_.GetImageRoot(ImageHeader::kOatLocation);
6413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    std::string oat_location(oat_location_object->AsString()->ToModifiedUtf8());
6424dcbffb3c6e8757d127dede32c8efa6c04e44a70Brian Carlstrom    os_ << oat_location;
6433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (!host_prefix_.empty()) {
6443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      oat_location = host_prefix_ + oat_location;
6453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os_ << " (" << oat_location << ")";
646aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
6474dcbffb3c6e8757d127dede32c8efa6c04e44a70Brian Carlstrom    os_ << "\n";
648ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    const OatFile* oat_file = class_linker->FindOatFileFromOatLocation(oat_location);
649aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    if (oat_file == NULL) {
6504dcbffb3c6e8757d127dede32c8efa6c04e44a70Brian Carlstrom      os_ << "NOT FOUND\n";
651aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      return;
652aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
6534dcbffb3c6e8757d127dede32c8efa6c04e44a70Brian Carlstrom    os_ << "\n";
654aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
6553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    stats_.oat_file_bytes = oat_file->Size();
65678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
65781f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    oat_dumper_.reset(new OatDumper(host_prefix_, *oat_file));
6583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
6593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "OBJECTS:\n" << std::flush;
660b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier
661b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier    // Loop through all the image spaces and dump their objects.
662b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier    Heap* heap = Runtime::Current()->GetHeap();
663b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier    const Spaces& spaces = heap->GetSpaces();
66450b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    Thread* self = Thread::Current();
665357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier    {
66650b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers      WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
667357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier      heap->FlushAllocStack();
668357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier    }
66950b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
67048efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers    // TODO: C++0x auto
6712fde53367dbe721e5273c34b590e67112322cc9eMathieu Chartier    for (Spaces::const_iterator it = spaces.begin(); it != spaces.end(); ++it) {
6722fde53367dbe721e5273c34b590e67112322cc9eMathieu Chartier      Space* space = *it;
6732fde53367dbe721e5273c34b590e67112322cc9eMathieu Chartier      if (space->IsImageSpace()) {
6742fde53367dbe721e5273c34b590e67112322cc9eMathieu Chartier        ImageSpace* image_space = space->AsImageSpace();
6752fde53367dbe721e5273c34b590e67112322cc9eMathieu Chartier        image_space->GetLiveBitmap()->Walk(ImageDumper::Callback, this);
6762fde53367dbe721e5273c34b590e67112322cc9eMathieu Chartier        os_ << "\n";
6772fde53367dbe721e5273c34b590e67112322cc9eMathieu Chartier      }
678b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier    }
679e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier    // Dump the large objects separately.
680e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier    heap->GetLargeObjectsSpace()->GetLiveObjects()->Walk(ImageDumper::Callback, this);
681e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier    os_ << "\n";
6823a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
6833a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "STATS:\n" << std::flush;
6843a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    UniquePtr<File> file(OS::OpenFile(image_filename_.c_str(), false));
6853a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    stats_.file_bytes = file->Length();
6863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t header_bytes = sizeof(ImageHeader);
6873a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    stats_.header_bytes = header_bytes;
6883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t alignment_bytes = RoundUp(header_bytes, kObjectAlignment) - header_bytes;
6893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    stats_.alignment_bytes += alignment_bytes;
6903a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    stats_.Dump(os_);
6913a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "\n";
69227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
6933a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << std::flush;
6943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
6953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    oat_dumper_->Dump(os_);
6963a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
697d1bb4f6b7c8dda429f61937cd42f3a0b7367c271Elliott Hughes
6983a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers private:
69900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static void PrettyObjectValue(std::string& summary, Class* type, Object* value)
700b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
701d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    CHECK(type != NULL);
702d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (value == NULL) {
703d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "null   %s\n", PrettyDescriptor(type).c_str());
704d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (type->IsStringClass()) {
705d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      String* string = value->AsString();
706d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p   String: \"%s\"\n", string, string->ToModifiedUtf8().c_str());
707d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (value->IsClass()) {
708d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      Class* klass = value->AsClass();
709d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p   Class: %s\n", klass, PrettyDescriptor(klass).c_str());
710d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (value->IsField()) {
711d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      Field* field = value->AsField();
712d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p   Field: %s\n", field, PrettyField(field).c_str());
713d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (value->IsMethod()) {
71466f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier      AbstractMethod* method = value->AsMethod();
715d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p   Method: %s\n", method, PrettyMethod(method).c_str());
716d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else {
717d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p   %s\n", value, PrettyDescriptor(type).c_str());
718d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
719d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  }
720d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers
72100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static void PrintField(std::string& summary, Field* field, Object* obj)
722b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
723d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    FieldHelper fh(field);
72448efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers    const char* descriptor = fh.GetTypeDescriptor();
725d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    StringAppendF(&summary, "\t%s: ", fh.GetName());
72648efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers    if (descriptor[0] != 'L' && descriptor[0] != '[') {
72748efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      Class* type = fh.GetType();
72848efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      if (type->IsPrimitiveLong()) {
72948efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers        StringAppendF(&summary, "%lld (0x%llx)\n", field->Get64(obj), field->Get64(obj));
73048efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      } else if (type->IsPrimitiveDouble()) {
73148efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers        StringAppendF(&summary, "%f (%a)\n", field->GetDouble(obj), field->GetDouble(obj));
73248efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      } else if (type->IsPrimitiveFloat()) {
73348efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers        StringAppendF(&summary, "%f (%a)\n", field->GetFloat(obj), field->GetFloat(obj));
73448efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      } else {
73548efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers        DCHECK(type->IsPrimitive());
73648efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers        StringAppendF(&summary, "%d (0x%x)\n", field->Get32(obj), field->Get32(obj));
73748efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      }
738d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else {
73948efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      // Get the value, don't compute the type unless it is non-null as we don't want
74048efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      // to cause class loading.
741d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      Object* value = field->GetObj(obj);
74248efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      if (value == NULL) {
74348efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers        StringAppendF(&summary, "null   %s\n", PrettyDescriptor(descriptor).c_str());
74448efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      } else {
74548efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers        PrettyObjectValue(summary, fh.GetType(), value);
74648efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      }
747d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
748d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  }
749d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers
75000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static void DumpFields(std::string& summary, Object* obj, Class* klass)
751b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
752d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    Class* super = klass->GetSuperClass();
753d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (super != NULL) {
754d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      DumpFields(summary, obj, super);
755d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
756d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    ObjectArray<Field>* fields = klass->GetIFields();
757d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (fields != NULL) {
758d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      for (int32_t i = 0; i < fields->GetLength(); i++) {
759d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        Field* field = fields->Get(i);
760d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        PrintField(summary, field, obj);
761d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      }
762d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
763d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  }
764d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers
7653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  bool InDumpSpace(const Object* object) {
7663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    return image_space_.Contains(object);
767f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  }
7683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
76966f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier  const void* GetOatCodeBegin(AbstractMethod* m)
770b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
7713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    Runtime* runtime = Runtime::Current();
7723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    const void* code = m->GetCode();
773fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers    if (code == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData()) {
7743a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      code = oat_dumper_->GetOatCode(m);
7753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
776f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    if (oat_dumper_->GetInstructionSet() == kThumb2) {
777f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom      code = reinterpret_cast<void*>(reinterpret_cast<uint32_t>(code) & ~0x1);
778f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    }
7793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    return code;
7803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
7813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
78266f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier  uint32_t GetOatCodeSize(AbstractMethod* m)
783b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
784f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    const uint32_t* oat_code_begin = reinterpret_cast<const uint32_t*>(GetOatCodeBegin(m));
785f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    if (oat_code_begin == NULL) {
786f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom      return 0;
787f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    }
788f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    return oat_code_begin[-1];
789f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  }
790f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom
79166f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier  const void* GetOatCodeEnd(AbstractMethod* m)
792b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
793f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    const uint8_t* oat_code_begin = reinterpret_cast<const uint8_t*>(GetOatCodeBegin(m));
794f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    if (oat_code_begin == NULL) {
795f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom      return NULL;
796f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    }
797f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    return oat_code_begin + GetOatCodeSize(m);
798f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  }
799f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom
80000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static void Callback(Object* obj, void* arg)
801b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
80278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    DCHECK(obj != NULL);
80378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    DCHECK(arg != NULL);
8043a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    ImageDumper* state = reinterpret_cast<ImageDumper*>(arg);
80578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    if (!state->InDumpSpace(obj)) {
80678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      return;
80778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
808916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
809916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t object_bytes = obj->SizeOf();
810916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t alignment_bytes = RoundUp(object_bytes, kObjectAlignment) - object_bytes;
811916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    state->stats_.object_bytes += object_bytes;
812916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    state->stats_.alignment_bytes += alignment_bytes;
813916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
81478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    std::string summary;
815d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    Class* obj_class = obj->GetClass();
816d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (obj_class->IsArrayClass()) {
817d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p: %s length:%d\n", obj, PrettyDescriptor(obj_class).c_str(),
818d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers                    obj->AsArray()->GetLength());
819d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj->IsClass()) {
82078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      Class* klass = obj->AsClass();
821d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p: java.lang.Class \"%s\" (", obj,
822d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers                    PrettyDescriptor(klass).c_str());
8233b6baaa203fa63f1522b2172a1645f90412afdaeElliott Hughes      std::ostringstream ss;
824d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      ss << klass->GetStatus() << ")\n";
825e10b6974d54f38001aee7bec518d45a7d4fb64c1Brian Carlstrom      summary += ss.str();
82678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else if (obj->IsField()) {
827d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p: java.lang.reflect.Field %s\n", obj,
828d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers                    PrettyField(obj->AsField()).c_str());
829d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj->IsMethod()) {
830d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p: java.lang.reflect.Method %s\n", obj,
831d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers                    PrettyMethod(obj->AsMethod()).c_str());
832d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj_class->IsStringClass()) {
83382914b6164fd0109531391975389e4f0ff6832c8Elliott Hughes      StringAppendF(&summary, "%p: java.lang.String %s\n", obj,
83482914b6164fd0109531391975389e4f0ff6832c8Elliott Hughes                    PrintableString(obj->AsString()->ToModifiedUtf8()).c_str());
83578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else {
836d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p: %s\n", obj, PrettyDescriptor(obj_class).c_str());
83778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
838d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    DumpFields(summary, obj, obj_class);
839d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (obj->IsObjectArray()) {
840d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      ObjectArray<Object>* obj_array = obj->AsObjectArray<Object>();
841d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      int32_t length = obj_array->GetLength();
842d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      for (int32_t i = 0; i < length; i++) {
843d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        Object* value = obj_array->Get(i);
844d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        size_t run = 0;
845d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        for (int32_t j = i + 1; j < length; j++) {
846d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          if (value == obj_array->Get(j)) {
847d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            run++;
848d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          } else {
849d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            break;
850d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          }
851d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        }
852d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        if (run == 0) {
853d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          StringAppendF(&summary, "\t%d: ", i);
85478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        } else {
855c1051ae94c5bd45367152a603f3946a933ad91faElliott Hughes          StringAppendF(&summary, "\t%d to %zd: ", i, i + run);
856d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          i = i + run;
85778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        }
858d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        Class* value_class = value == NULL ? obj_class->GetComponentType() : value->GetClass();
859d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        PrettyObjectValue(summary, value_class, value);
860d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      }
861d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj->IsClass()) {
862d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      ObjectArray<Field>* sfields = obj->AsClass()->GetSFields();
863d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      if (sfields != NULL) {
864d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        summary += "\t\tSTATICS:\n";
865d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        for (int32_t i = 0; i < sfields->GetLength(); i++) {
866d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          Field* field = sfields->Get(i);
867d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          PrintField(summary, field, NULL);
868d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        }
869d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      }
870d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj->IsMethod()) {
87166f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier      AbstractMethod* method = obj->AsMethod();
872d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      if (method->IsNative()) {
8730c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers        DCHECK(method->GetNativeGcMap() == NULL) << PrettyMethod(method);
8743320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom        DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method);
8753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        bool first_occurrence;
8763a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t invoke_stub_size = state->ComputeOatSize(
8773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            reinterpret_cast<const void*>(method->GetInvokeStub()), &first_occurrence);
8783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (first_occurrence) {
8793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          state->stats_.managed_to_native_code_bytes += invoke_stub_size;
8803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
881f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom        const void* oat_code = state->GetOatCodeBegin(method);
882db7bdc1086c44fe628b6743f98d7d85a5c03343aIan Rogers        uint32_t oat_code_size = state->GetOatCodeSize(method);
883db7bdc1086c44fe628b6743f98d7d85a5c03343aIan Rogers        state->ComputeOatSize(oat_code, &first_occurrence);
8843a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (first_occurrence) {
885db7bdc1086c44fe628b6743f98d7d85a5c03343aIan Rogers          state->stats_.native_to_managed_code_bytes += oat_code_size;
8863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
8873a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (oat_code != method->GetCode()) {
8883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          StringAppendF(&summary, "\t\tOAT CODE: %p\n", oat_code);
8893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
8901984651929744dd603fd082e23eacd877b9bc177Ian Rogers      } else if (method->IsAbstract() || method->IsCalleeSaveMethod() ||
8911984651929744dd603fd082e23eacd877b9bc177Ian Rogers          method->IsResolutionMethod()) {
8920c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers        DCHECK(method->GetNativeGcMap() == NULL) << PrettyMethod(method);
8933320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom        DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method);
894916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      } else {
8953db5285b363553ea81bd8dd88ec448b66cf33d71TDYa#if !defined(ART_USE_LLVM_COMPILER)
8960c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers        DCHECK(method->GetNativeGcMap() != NULL) << PrettyMethod(method);
8973db5285b363553ea81bd8dd88ec448b66cf33d71TDYa#endif
898916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
8996d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers        const DexFile::CodeItem* code_item = MethodHelper(method).GetCodeItem();
900d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers        size_t dex_instruction_bytes = code_item->insns_size_in_code_units_ * 2;
901916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        state->stats_.dex_instruction_bytes += dex_instruction_bytes;
902e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom
903a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        bool first_occurrence;
9040c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers        size_t gc_map_bytes = state->ComputeOatSize(method->GetNativeGcMap(), &first_occurrence);
905a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        if (first_occurrence) {
9063a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          state->stats_.gc_map_bytes += gc_map_bytes;
9073a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
9083a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
9093a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t pc_mapping_table_bytes =
910a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes            state->ComputeOatSize(method->GetMappingTableRaw(), &first_occurrence);
911a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        if (first_occurrence) {
9123a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          state->stats_.pc_mapping_table_bytes += pc_mapping_table_bytes;
9133a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
9143a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
9153a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t vmap_table_bytes =
916a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes            state->ComputeOatSize(method->GetVmapTableRaw(), &first_occurrence);
917a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        if (first_occurrence) {
9183a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          state->stats_.vmap_table_bytes += vmap_table_bytes;
9193a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
9203a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
921db7bdc1086c44fe628b6743f98d7d85a5c03343aIan Rogers        // TODO: compute invoke stub using length from oat file.
9223a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t invoke_stub_size = state->ComputeOatSize(
923a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes            reinterpret_cast<const void*>(method->GetInvokeStub()), &first_occurrence);
924a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        if (first_occurrence) {
9253a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          state->stats_.native_to_managed_code_bytes += invoke_stub_size;
9263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
927f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom        const void* oat_code_begin = state->GetOatCodeBegin(method);
928f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom        const void* oat_code_end = state->GetOatCodeEnd(method);
929db7bdc1086c44fe628b6743f98d7d85a5c03343aIan Rogers        uint32_t oat_code_size = state->GetOatCodeSize(method);
930a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        state->ComputeOatSize(oat_code_begin, &first_occurrence);
931a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        if (first_occurrence) {
932db7bdc1086c44fe628b6743f98d7d85a5c03343aIan Rogers          state->stats_.managed_code_bytes += oat_code_size;
9330d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers          if (method->IsConstructor()) {
9340d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers            if (method->IsStatic()) {
9350d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers              state->stats_.class_initializer_code_bytes += oat_code_size;
9360d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers            } else if (dex_instruction_bytes > kLargeConstructorDexBytes) {
9370d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers              state->stats_.large_initializer_code_bytes += oat_code_size;
9380d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers            }
9390d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers          } else if (dex_instruction_bytes > kLargeMethodDexBytes) {
9400d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers            state->stats_.large_method_code_bytes += oat_code_size;
9410d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers          }
9423a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
943db7bdc1086c44fe628b6743f98d7d85a5c03343aIan Rogers        state->stats_.managed_code_bytes_ignoring_deduplication += oat_code_size;
9443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
945f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom        StringAppendF(&summary, "\t\tOAT CODE: %p-%p\n", oat_code_begin, oat_code_end);
946d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        StringAppendF(&summary, "\t\tSIZE: Dex Instructions=%zd GC=%zd Mapping=%zd\n",
9473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                      dex_instruction_bytes, gc_map_bytes, pc_mapping_table_bytes);
9483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
9493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t total_size = dex_instruction_bytes + gc_map_bytes + pc_mapping_table_bytes +
950db7bdc1086c44fe628b6743f98d7d85a5c03343aIan Rogers            vmap_table_bytes + invoke_stub_size + oat_code_size + object_bytes;
9513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
9523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        double expansion =
953db7bdc1086c44fe628b6743f98d7d85a5c03343aIan Rogers            static_cast<double>(oat_code_size) / static_cast<double>(dex_instruction_bytes);
9543a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        state->stats_.ComputeOutliers(total_size, expansion, method);
95578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      }
95678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
957a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    state->stats_.Update(ClassHelper(obj_class).GetDescriptor(), object_bytes);
958d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers
95927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    state->os_ << summary << std::flush;
96078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
96127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
9623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  std::set<const void*> already_seen_;
9633a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  // Compute the size of the given data within the oat file and whether this is the first time
9643a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  // this data has been requested
965a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  size_t ComputeOatSize(const void* oat_data, bool* first_occurrence) {
9663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (already_seen_.count(oat_data) == 0) {
967a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      *first_occurrence = true;
9683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      already_seen_.insert(oat_data);
9693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    } else {
970a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      *first_occurrence = false;
9713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
9723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    return oat_dumper_->ComputeSize(oat_data);
97327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  }
974916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
975916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom public:
976916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom  struct Stats {
9773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t oat_file_bytes;
978916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t file_bytes;
979916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
980916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t header_bytes;
981916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t object_bytes;
982916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t alignment_bytes;
983916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
984916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t managed_code_bytes;
9853a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t managed_code_bytes_ignoring_deduplication;
986916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t managed_to_native_code_bytes;
987916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t native_to_managed_code_bytes;
9880d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    size_t class_initializer_code_bytes;
9890d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    size_t large_initializer_code_bytes;
9900d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    size_t large_method_code_bytes;
991916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
9923a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t gc_map_bytes;
993916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t pc_mapping_table_bytes;
9943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t vmap_table_bytes;
995916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
996916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t dex_instruction_bytes;
997916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
99866f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier    std::vector<AbstractMethod*> method_outlier;
9993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    std::vector<size_t> method_outlier_size;
10003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    std::vector<double> method_outlier_expansion;
10013a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
10023a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    explicit Stats()
10033a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        : oat_file_bytes(0),
10043a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          file_bytes(0),
1005916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          header_bytes(0),
1006916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          object_bytes(0),
1007916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          alignment_bytes(0),
1008916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          managed_code_bytes(0),
10093a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          managed_code_bytes_ignoring_deduplication(0),
1010916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          managed_to_native_code_bytes(0),
1011916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          native_to_managed_code_bytes(0),
10120d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers          class_initializer_code_bytes(0),
10130d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers          large_initializer_code_bytes(0),
10140d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers          large_method_code_bytes(0),
10153a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          gc_map_bytes(0),
1016916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          pc_mapping_table_bytes(0),
10173a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          vmap_table_bytes(0),
1018916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          dex_instruction_bytes(0) {}
1019916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1020a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    struct SizeAndCount {
1021a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      SizeAndCount(size_t bytes, size_t count) : bytes(bytes), count(count) {}
1022a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      size_t bytes;
1023a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      size_t count;
1024a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    };
1025a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    typedef SafeMap<std::string, SizeAndCount> SizeAndCountTable;
1026a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    SizeAndCountTable sizes_and_counts;
1027a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
1028a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    void Update(const std::string& descriptor, size_t object_bytes) {
1029a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      SizeAndCountTable::iterator it = sizes_and_counts.find(descriptor);
1030a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      if (it != sizes_and_counts.end()) {
1031a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        it->second.bytes += object_bytes;
1032a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        it->second.count += 1;
1033a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      } else {
1034a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        sizes_and_counts.Put(descriptor, SizeAndCount(object_bytes, 1));
1035a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      }
1036a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    }
1037916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
10383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    double PercentOfOatBytes(size_t size) {
10393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      return (static_cast<double>(size) / static_cast<double>(oat_file_bytes)) * 100;
10403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
10413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1042916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    double PercentOfFileBytes(size_t size) {
1043916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      return (static_cast<double>(size) / static_cast<double>(file_bytes)) * 100;
1044916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    }
1045916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1046916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    double PercentOfObjectBytes(size_t size) {
1047916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      return (static_cast<double>(size) / static_cast<double>(object_bytes)) * 100;
1048916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    }
1049916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
105066f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier    void ComputeOutliers(size_t total_size, double expansion, AbstractMethod* method) {
10513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      method_outlier_size.push_back(total_size);
10523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      method_outlier_expansion.push_back(expansion);
10533a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      method_outlier.push_back(method);
10543a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
10553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
105600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    void DumpOutliers(std::ostream& os)
1057b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
10583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t sum_of_sizes = 0;
10593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t sum_of_sizes_squared = 0;
10603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t sum_of_expansion = 0;
10613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t sum_of_expansion_squared = 0;
10623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t n = method_outlier_size.size();
10633a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      for (size_t i = 0; i < n; i++) {
10643a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t cur_size = method_outlier_size[i];
10653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        sum_of_sizes += cur_size;
10663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        sum_of_sizes_squared += cur_size * cur_size;
10673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        double cur_expansion = method_outlier_expansion[i];
10683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        sum_of_expansion += cur_expansion;
10693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        sum_of_expansion_squared += cur_expansion * cur_expansion;
10703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
10713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t size_mean = sum_of_sizes / n;
10723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t size_variance = (sum_of_sizes_squared - sum_of_sizes * size_mean) / (n - 1);
10733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      double expansion_mean = sum_of_expansion / n;
10743a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      double expansion_variance =
10753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          (sum_of_expansion_squared - sum_of_expansion * expansion_mean) / (n - 1);
10763a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
10773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      // Dump methods whose size is a certain number of standard deviations from the mean
10783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t dumped_values = 0;
10793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t skipped_values = 0;
10803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      for (size_t i = 100; i > 0; i--) {  // i is the current number of standard deviations
10813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t cur_size_variance = i * i * size_variance;
10823a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        bool first = true;
10833a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        for (size_t j = 0; j < n; j++) {
10843a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          size_t cur_size = method_outlier_size[j];
10853a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          if (cur_size > size_mean) {
10863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            size_t cur_var = cur_size - size_mean;
10873a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            cur_var = cur_var * cur_var;
10883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            if (cur_var > cur_size_variance) {
10893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              if (dumped_values > 20) {
10903a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                if (i == 1) {
10913a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  skipped_values++;
10923a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                } else {
10933a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  i = 2;  // jump to counting for 1 standard deviation
10943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  break;
10953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                }
10963a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              } else {
10973a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                if (first) {
1098c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                  os << "\nBig methods (size > " << i << " standard deviations the norm):\n";
10993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  first = false;
11003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                }
11013a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                os << "\t" << PrettyMethod(method_outlier[j]) << " requires storage of "
1102c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                    << PrettySize(cur_size) << "\n";
11033a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                method_outlier_size[j] = 0;  // don't consider this method again
11043a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                dumped_values++;
11053a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              }
11063a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            }
11073a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          }
11083a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
11093a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
11103a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if (skipped_values > 0) {
11113a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        os << "\t... skipped " << skipped_values
1112c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes           << " methods with size > 1 standard deviation from the norm\n";
11133a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
1114c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes      os << std::flush;
11153a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
11163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      // Dump methods whose expansion is a certain number of standard deviations from the mean
11173a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      dumped_values = 0;
11183a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      skipped_values = 0;
11193a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      for (size_t i = 10; i > 0; i--) {  // i is the current number of standard deviations
11203a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        double cur_expansion_variance = i * i * expansion_variance;
11213a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        bool first = true;
11223a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        for (size_t j = 0; j < n; j++) {
11233a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          double cur_expansion = method_outlier_expansion[j];
11243a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          if (cur_expansion > expansion_mean) {
11253a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            size_t cur_var = cur_expansion - expansion_mean;
11263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            cur_var = cur_var * cur_var;
11273a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            if (cur_var > cur_expansion_variance) {
11283a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              if (dumped_values > 20) {
11293a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                if (i == 1) {
11303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  skipped_values++;
11313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                } else {
11323a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  i = 2;  // jump to counting for 1 standard deviation
11333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  break;
11343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                }
11353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              } else {
11363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                if (first) {
11373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  os << "\nLarge expansion methods (size > " << i
1138c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                      << " standard deviations the norm):\n";
11393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  first = false;
11403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                }
11413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                os << "\t" << PrettyMethod(method_outlier[j]) << " expanded code by "
1142c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                   << cur_expansion << "\n";
11433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                method_outlier_expansion[j] = 0.0;  // don't consider this method again
11443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                dumped_values++;
11453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              }
11463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            }
11473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          }
11483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
11493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
11503a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if (skipped_values > 0) {
11513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        os << "\t... skipped " << skipped_values
1152c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes           << " methods with expansion > 1 standard deviation from the norm\n";
11533a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
1154c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes      os << "\n" << std::flush;
11553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
11563a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1157b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers    void Dump(std::ostream& os) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1158c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes      os << "\tart_file_bytes = " << PrettySize(file_bytes) << "\n\n"
1159c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes         << "\tart_file_bytes = header_bytes + object_bytes + alignment_bytes\n"
11603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers         << StringPrintf("\theader_bytes    =  %8zd (%2.0f%% of art file bytes)\n"
11613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         "\tobject_bytes    =  %8zd (%2.0f%% of art file bytes)\n"
1162c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                         "\talignment_bytes =  %8zd (%2.0f%% of art file bytes)\n\n",
11633a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         header_bytes, PercentOfFileBytes(header_bytes),
11643a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         object_bytes, PercentOfFileBytes(object_bytes),
11653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         alignment_bytes, PercentOfFileBytes(alignment_bytes))
1166c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes         << std::flush;
11673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1168916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      CHECK_EQ(file_bytes, header_bytes + object_bytes + alignment_bytes);
1169916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1170a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      os << "\tobject_bytes breakdown:\n";
1171916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      size_t object_bytes_total = 0;
1172a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      typedef SizeAndCountTable::const_iterator It;  // TODO: C++0x auto
1173a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      for (It it = sizes_and_counts.begin(), end = sizes_and_counts.end(); it != end; ++it) {
1174955724179c6c739524f610023287f56b24dc31deElliott Hughes        const std::string& descriptor(it->first);
1175a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        double average = static_cast<double>(it->second.bytes) / static_cast<double>(it->second.count);
1176a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        double percent = PercentOfObjectBytes(it->second.bytes);
1177ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes        os << StringPrintf("\t%32s %8zd bytes %6zd instances "
1178a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes                           "(%4.0f bytes/instance) %2.0f%% of object_bytes\n",
1179a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes                           descriptor.c_str(), it->second.bytes, it->second.count,
1180916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                           average, percent);
1181a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        object_bytes_total += it->second.bytes;
1182916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      }
1183c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes      os << "\n" << std::flush;
1184916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      CHECK_EQ(object_bytes, object_bytes_total);
1185916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
11863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os << StringPrintf("\tmanaged_code_bytes           = %8zd (%2.0f%% of oat file bytes)\n"
11873a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         "\tmanaged_to_native_code_bytes = %8zd (%2.0f%% of oat file bytes)\n"
11880d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers                         "\tnative_to_managed_code_bytes = %8zd (%2.0f%% of oat file bytes)\n\n"
11890d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers                         "\tclass_initializer_code_bytes = %8zd (%2.0f%% of oat file bytes)\n"
11900d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers                         "\tlarge_initializer_code_bytes = %8zd (%2.0f%% of oat file bytes)\n"
1191c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                         "\tlarge_method_code_bytes      = %8zd (%2.0f%% of oat file bytes)\n\n",
11923a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         managed_code_bytes, PercentOfOatBytes(managed_code_bytes),
11933a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         managed_to_native_code_bytes, PercentOfOatBytes(managed_to_native_code_bytes),
11940d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers                         native_to_managed_code_bytes, PercentOfOatBytes(native_to_managed_code_bytes),
11950d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers                         class_initializer_code_bytes, PercentOfOatBytes(class_initializer_code_bytes),
11960d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers                         large_initializer_code_bytes, PercentOfOatBytes(large_initializer_code_bytes),
11970d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers                         large_method_code_bytes, PercentOfOatBytes(large_method_code_bytes))
1198c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes         << std::flush;
11993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
12003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os << StringPrintf("\tgc_map_bytes           = %7zd (%2.0f%% of oat file_bytes)\n"
12013a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         "\tpc_mapping_table_bytes = %7zd (%2.0f%% of oat file_bytes)\n"
1202c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                         "\tvmap_table_bytes       = %7zd (%2.0f%% of oat file_bytes)\n\n",
12033a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         gc_map_bytes, PercentOfOatBytes(gc_map_bytes),
12043a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         pc_mapping_table_bytes, PercentOfOatBytes(pc_mapping_table_bytes),
12053a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         vmap_table_bytes, PercentOfOatBytes(vmap_table_bytes))
1206c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes         << std::flush;
1207916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1208cf44e6f1ec194a906f4760a7c0395fdb0123d7aeElliott Hughes      os << StringPrintf("\tdex_instruction_bytes = %zd\n", dex_instruction_bytes)
1209c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes         << StringPrintf("\tmanaged_code_bytes expansion = %.2f (ignoring deduplication %.2f)\n\n",
1210c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                         static_cast<double>(managed_code_bytes) / static_cast<double>(dex_instruction_bytes),
1211c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                         static_cast<double>(managed_code_bytes_ignoring_deduplication) /
1212cf44e6f1ec194a906f4760a7c0395fdb0123d7aeElliott Hughes                             static_cast<double>(dex_instruction_bytes))
1213c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes         << std::flush;
12143a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
12153a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      DumpOutliers(os);
1216916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    }
1217916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom  } stats_;
1218916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1219916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom private:
12200d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers  enum {
12210d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    // Number of bytes for a constructor to be considered large. Based on the 1000 basic block
12220d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    // threshold, we assume 2 bytes per instruction and 2 instructions per block.
12230d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    kLargeConstructorDexBytes = 4000,
12240d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    // Number of bytes for a method to be considered large. Based on the 4000 basic block
12250d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    // threshold, we assume 2 bytes per instruction and 2 instructions per block.
12260d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    kLargeMethodDexBytes = 16000
12270d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers  };
12283a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  UniquePtr<OatDumper> oat_dumper_;
122927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  std::ostream& os_;
12303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  const std::string image_filename_;
12313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  const std::string host_prefix_;
12323a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  Space& image_space_;
12333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  const ImageHeader& image_header_;
1234d1bb4f6b7c8dda429f61937cd42f3a0b7367c271Elliott Hughes
12353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  DISALLOW_COPY_AND_ASSIGN(ImageDumper);
123678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom};
123778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
123872395bf298b7707ad9d93c3e51b57e1b8e010311Elliott Hughesstatic int oatdump(int argc, char** argv) {
12390d39c12238499ca9ccc34d1532c443335e7c1044Elliott Hughes  InitLogging(argv);
124072395bf298b7707ad9d93c3e51b57e1b8e010311Elliott Hughes
124178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  // Skip over argv[0].
124278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  argv++;
124378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  argc--;
124478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
124578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  if (argc == 0) {
1246aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    fprintf(stderr, "No arguments specified\n");
124778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    usage();
124878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
124978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
1250aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  const char* oat_filename = NULL;
125178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  const char* image_filename = NULL;
125278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  const char* boot_image_filename = NULL;
12530cc6ab6c5104f565a0a3256b5b2b31c6383be189Logan Chien  std::string elf_filename_prefix;
125413c492bce0daf19cbea71670b9e1fe2df2e153e5Brian Carlstrom  UniquePtr<std::string> host_prefix;
125527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  std::ostream* os = &std::cout;
125627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  UniquePtr<std::ofstream> out;
125778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
125878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  for (int i = 0; i < argc; i++) {
125978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    const StringPiece option(argv[i]);
1260a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    if (option.starts_with("--oat-file=")) {
1261a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      oat_filename = option.substr(strlen("--oat-file=")).data();
1262aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    } else if (option.starts_with("--image=")) {
126378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      image_filename = option.substr(strlen("--image=")).data();
1264e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    } else if (option.starts_with("--boot-image=")) {
1265e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom      boot_image_filename = option.substr(strlen("--boot-image=")).data();
126658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    } else if (option.starts_with("--host-prefix=")) {
126713c492bce0daf19cbea71670b9e1fe2df2e153e5Brian Carlstrom      host_prefix.reset(new std::string(option.substr(strlen("--host-prefix=")).data()));
126827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    } else if (option.starts_with("--output=")) {
126927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      const char* filename = option.substr(strlen("--output=")).data();
127027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      out.reset(new std::ofstream(filename));
127127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      if (!out->good()) {
1272aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom        fprintf(stderr, "Failed to open output filename %s\n", filename);
127327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        usage();
127427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      }
127527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      os = out.get();
127678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else {
1277aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      fprintf(stderr, "Unknown argument %s\n", option.data());
127878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      usage();
127978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
128078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
128178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
1282aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (image_filename == NULL && oat_filename == NULL) {
1283362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    fprintf(stderr, "Either --image or --oat must be specified\n");
1284362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    return EXIT_FAILURE;
128578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
128678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
1287aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (image_filename != NULL && oat_filename != NULL) {
1288362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    fprintf(stderr, "Either --image or --oat must be specified but not both\n");
1289362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    return EXIT_FAILURE;
1290aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
1291aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
129213c492bce0daf19cbea71670b9e1fe2df2e153e5Brian Carlstrom  if (host_prefix.get() == NULL) {
129381f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    const char* android_product_out = getenv("ANDROID_PRODUCT_OUT");
129481f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    if (android_product_out != NULL) {
129513c492bce0daf19cbea71670b9e1fe2df2e153e5Brian Carlstrom        host_prefix.reset(new std::string(android_product_out));
129613c492bce0daf19cbea71670b9e1fe2df2e153e5Brian Carlstrom    } else {
129713c492bce0daf19cbea71670b9e1fe2df2e153e5Brian Carlstrom        host_prefix.reset(new std::string(""));
129881f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    }
129981f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom  }
130081f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
1301aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (oat_filename != NULL) {
13020c717dd1c56bd29cf860d0feda8e629dab2cadb3Logan Chien    OatFile* oat_file =
13030c717dd1c56bd29cf860d0feda8e629dab2cadb3Logan Chien        OatFile::Open(oat_filename, oat_filename, NULL, OatFile::kRelocNone);
1304aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    if (oat_file == NULL) {
1305aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      fprintf(stderr, "Failed to open oat file from %s\n", oat_filename);
1306aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      return EXIT_FAILURE;
1307aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
130813c492bce0daf19cbea71670b9e1fe2df2e153e5Brian Carlstrom    OatDumper oat_dumper(*host_prefix.get(), *oat_file);
13093a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    oat_dumper.Dump(*os);
1310aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    return EXIT_SUCCESS;
1311aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
1312aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
131378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  Runtime::Options options;
131478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  std::string image_option;
1315e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  std::string oat_option;
131678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  std::string boot_image_option;
1317e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  std::string boot_oat_option;
131858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  if (boot_image_filename != NULL) {
131958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    boot_image_option += "-Ximage:";
132058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    boot_image_option += boot_image_filename;
132158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL)));
132258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  }
1323aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (image_filename != NULL) {
1324aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    image_option += "-Ximage:";
1325aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    image_option += image_filename;
1326aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    options.push_back(std::make_pair(image_option.c_str(), reinterpret_cast<void*>(NULL)));
1327aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
132858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom
132913c492bce0daf19cbea71670b9e1fe2df2e153e5Brian Carlstrom  if (!host_prefix->empty()) {
133013c492bce0daf19cbea71670b9e1fe2df2e153e5Brian Carlstrom    options.push_back(std::make_pair("host-prefix", host_prefix->c_str()));
133178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
133278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
133300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  if (!Runtime::Create(options, false)) {
1334aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    fprintf(stderr, "Failed to create runtime\n");
133578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    return EXIT_FAILURE;
133678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
133700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  UniquePtr<Runtime> runtime(Runtime::Current());
133800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
133900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // give it away now and then switch to a more managable ScopedObjectAccess.
134000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Thread::Current()->TransitionFromRunnableToSuspended(kNative);
134100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(Thread::Current());
134278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
1343b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  Heap* heap = Runtime::Current()->GetHeap();
1344fddf6f6b4af42c32dd2e92234bab0741118d092eBrian Carlstrom  ImageSpace* image_space = heap->GetImageSpace();
134578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  CHECK(image_space != NULL);
134678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  const ImageHeader& image_header = image_space->GetImageHeader();
134778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  if (!image_header.IsValid()) {
1348aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    fprintf(stderr, "Invalid image header %s\n", image_filename);
134978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    return EXIT_FAILURE;
135078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
135113c492bce0daf19cbea71670b9e1fe2df2e153e5Brian Carlstrom  ImageDumper image_dumper(*os, image_filename, *host_prefix.get(), *image_space, image_header);
13523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  image_dumper.Dump();
135378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  return EXIT_SUCCESS;
135478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom}
135578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
135678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom} // namespace art
135778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
135878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromint main(int argc, char** argv) {
135978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  return art::oatdump(argc, argv);
136078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom}
1361