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