common_test.h revision 2dd0e2cea360bc9206eb88ecc40d259e796c239d
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 */ 16934486cf07c578b6494417ca5dcbae89cf04b019Brian Carlstrom 17b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#include <dirent.h> 180af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes#include <dlfcn.h> 1927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom#include <sys/mman.h> 20b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#include <sys/stat.h> 21b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#include <sys/types.h> 22b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 23f66330a747eff155eb571b634fc9d901c55a78a7Elliott Hughes#include "../../external/icu4c/common/unicode/uvernum.h" 24761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/macros.h" 251aa246dec5abe212f699de1413a0c4a191ca364aElliott Hughes#include "base/stl_util.h" 26e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes#include "base/stringprintf.h" 27761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/unix_file/fd_file.h" 28578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "class_linker.h" 299baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom#include "compiler.h" 30578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "dex_file.h" 3190a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes#include "gtest/gtest.h" 321f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom#include "heap.h" 330f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes#include "instruction_set.h" 342dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class_loader.h" 353320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom#include "oat_file.h" 366d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h" 3733f741eefef8f8012f6c190b39355f2e0430d535Brian Carlstrom#include "os.h" 381f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom#include "runtime.h" 3900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h" 40e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes#include "ScopedLocalRef.h" 4190a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes#include "thread.h" 420f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes#include "UniquePtr.h" 4300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "well_known_classes.h" 440af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes 45934486cf07c578b6494417ca5dcbae89cf04b019Brian Carlstromnamespace art { 46934486cf07c578b6494417ca5dcbae89cf04b019Brian Carlstrom 47b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstromstatic const byte kBase64Map[256] = { 48b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 49b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 50b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 51b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, 52b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 53b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 54a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // NOLINT 55a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, // NOLINT 56b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 57a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // NOLINT 58a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, // NOLINT 59b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 60b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 61b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 64b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 65b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 66b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 67b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 68b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 69b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 255, 255, 255, 255 70b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom}; 71b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 72b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrombyte* DecodeBase64(const char* src, size_t* dst_size) { 73b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom std::vector<byte> tmp; 74a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes uint32_t t = 0, y = 0; 75b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom int g = 3; 76b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom for (size_t i = 0; src[i] != '\0'; ++i) { 77b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom byte c = kBase64Map[src[i] & 0xFF]; 78b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom if (c == 255) continue; 79b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom // the final = symbols are read and used to trim the remaining bytes 80b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom if (c == 254) { 81b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom c = 0; 82b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom // prevent g < 0 which would potentially allow an overflow later 83b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom if (--g < 0) { 845147733292cd0b80ca7da3099e43cc549d67526bBrian Carlstrom *dst_size = 0; 85b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom return NULL; 86b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom } 87b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom } else if (g != 3) { 88b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom // we only allow = to be at the end 895147733292cd0b80ca7da3099e43cc549d67526bBrian Carlstrom *dst_size = 0; 90b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom return NULL; 91b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom } 92b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom t = (t << 6) | c; 93b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom if (++y == 4) { 94b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom tmp.push_back((t >> 16) & 255); 95b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom if (g > 1) { 96b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom tmp.push_back((t >> 8) & 255); 97b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom } 98b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom if (g > 2) { 99b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom tmp.push_back(t & 255); 100b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom } 101b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom y = t = 0; 102b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom } 103b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom } 104b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom if (y != 0) { 1055147733292cd0b80ca7da3099e43cc549d67526bBrian Carlstrom *dst_size = 0; 106b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom return NULL; 107b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom } 108b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom UniquePtr<byte[]> dst(new byte[tmp.size()]); 109b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom if (dst_size != NULL) { 110b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom *dst_size = tmp.size(); 1115147733292cd0b80ca7da3099e43cc549d67526bBrian Carlstrom } else { 1125147733292cd0b80ca7da3099e43cc549d67526bBrian Carlstrom *dst_size = 0; 113b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom } 114b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom std::copy(tmp.begin(), tmp.end(), dst.get()); 115b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom return dst.release(); 116b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom} 117b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom 1189f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstromstatic inline const DexFile* OpenDexFileBase64(const char* base64, 1199f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstrom const std::string& location) { 12033f741eefef8f8012f6c190b39355f2e0430d535Brian Carlstrom // decode base64 121578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom CHECK(base64 != NULL); 122578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom size_t length; 1234d6850c47515fe2a4f9de923befb6287bb863c8cElliott Hughes UniquePtr<byte[]> dex_bytes(DecodeBase64(base64, &length)); 1244d6850c47515fe2a4f9de923befb6287bb863c8cElliott Hughes CHECK(dex_bytes.get() != NULL); 12533f741eefef8f8012f6c190b39355f2e0430d535Brian Carlstrom 12633f741eefef8f8012f6c190b39355f2e0430d535Brian Carlstrom // write to provided file 12733f741eefef8f8012f6c190b39355f2e0430d535Brian Carlstrom UniquePtr<File> file(OS::OpenFile(location.c_str(), true)); 12833f741eefef8f8012f6c190b39355f2e0430d535Brian Carlstrom CHECK(file.get() != NULL); 1294d6850c47515fe2a4f9de923befb6287bb863c8cElliott Hughes if (!file->WriteFully(dex_bytes.get(), length)) { 13033f741eefef8f8012f6c190b39355f2e0430d535Brian Carlstrom PLOG(FATAL) << "Failed to write base64 as dex file"; 13133f741eefef8f8012f6c190b39355f2e0430d535Brian Carlstrom } 13233f741eefef8f8012f6c190b39355f2e0430d535Brian Carlstrom file.reset(); 13333f741eefef8f8012f6c190b39355f2e0430d535Brian Carlstrom 13433f741eefef8f8012f6c190b39355f2e0430d535Brian Carlstrom // read dex file 135a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom const DexFile* dex_file = DexFile::Open(location, location); 136578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom CHECK(dex_file != NULL); 137f615a61aef972cfc1dc23931ac2ed0da14c3fedbBrian Carlstrom return dex_file; 138578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom} 139578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom 140db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstromclass ScratchFile { 141db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom public: 142db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom ScratchFile() { 14334023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes filename_ = getenv("ANDROID_DATA"); 14434023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes filename_ += "/TmpFile-XXXXXX"; 145761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes int fd = mkstemp(&filename_[0]); 146761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes CHECK_NE(-1, fd); 147761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes file_.reset(new File(fd, GetFilename())); 148db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } 149db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 150db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom ~ScratchFile() { 15134023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes int unlink_result = unlink(filename_.c_str()); 152db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom CHECK_EQ(0, unlink_result); 153db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } 154db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 155a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom const std::string& GetFilename() const { 156a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom return filename_; 157db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } 158db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 159234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes File* GetFile() const { 160234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes return file_.get(); 161234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes } 162234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes 163db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom int GetFd() const { 164761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes return file_->Fd(); 165db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } 166db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 167db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom private: 16834023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes std::string filename_; 169234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes UniquePtr<File> file_; 170db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom}; 171db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 172f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstromclass CommonTest : public testing::Test { 1739baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom public: 1742dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers static void MakeExecutable(const mirror::ByteArray* code_array) { 1753320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom CHECK(code_array != NULL); 1763320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom MakeExecutable(code_array->GetData(), code_array->GetLength()); 1773320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 1783320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 1791cb0ae742072b5ea2c7f677e6ad220ba01255daeShih-wei Liao static void MakeExecutable(const std::vector<uint8_t>& code) { 1803320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom CHECK_NE(code.size(), 0U); 1813320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom MakeExecutable(&code[0], code.size()); 1823320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 1833320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 184ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom // Create an OatMethod based on pointers (for unit tests) 185ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom OatFile::OatMethod CreateOatMethod(const void* code, 186ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom const size_t frame_size_in_bytes, 187ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom const uint32_t core_spill_mask, 188ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom const uint32_t fp_spill_mask, 189ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom const uint32_t* mapping_table, 190ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom const uint16_t* vmap_table, 191e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom const uint8_t* gc_map, 1922dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers const mirror::AbstractMethod::InvokeStub* invoke_stub) { 193ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom return OatFile::OatMethod(NULL, 194ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom reinterpret_cast<uint32_t>(code), 195ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom frame_size_in_bytes, 196ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom core_spill_mask, 197ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom fp_spill_mask, 198ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom reinterpret_cast<uint32_t>(mapping_table), 199ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom reinterpret_cast<uint32_t>(vmap_table), 200e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom reinterpret_cast<uint32_t>(gc_map), 2010c717dd1c56bd29cf860d0feda8e629dab2cadb3Logan Chien reinterpret_cast<uint32_t>(invoke_stub) 2020c717dd1c56bd29cf860d0feda8e629dab2cadb3Logan Chien#if defined(ART_USE_LLVM_COMPILER) 203971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien , 0 2040c717dd1c56bd29cf860d0feda8e629dab2cadb3Logan Chien#endif 2050c717dd1c56bd29cf860d0feda8e629dab2cadb3Logan Chien ); 206ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 207ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 2082dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers void MakeExecutable(mirror::AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 2093320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom CHECK(method != NULL); 2103320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2116d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers MethodHelper mh(method); 2120571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const CompiledInvokeStub* compiled_invoke_stub = 2136d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers compiler_->FindInvokeStub(mh.IsStatic(), mh.GetShorty()); 2143320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom CHECK(compiled_invoke_stub != NULL) << PrettyMethod(method); 215f7015fd55a8dc969ac2440ffc829a6b4d942fb5aLogan Chien 216971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode(); 217971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien MakeExecutable(invoke_stub); 2182dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers const mirror::AbstractMethod::InvokeStub* method_invoke_stub = 2192dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers reinterpret_cast<const mirror::AbstractMethod::InvokeStub*>( 2204284bb9e8b79add46e61da897fa02df3625888f7Logan Chien CompiledCode::CodePointer(&invoke_stub[0], 2214284bb9e8b79add46e61da897fa02df3625888f7Logan Chien compiled_invoke_stub->GetInstructionSet())); 222f7015fd55a8dc969ac2440ffc829a6b4d942fb5aLogan Chien 2233320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom LOG(INFO) << "MakeExecutable " << PrettyMethod(method) 2243320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom << " invoke_stub=" << reinterpret_cast<void*>(method_invoke_stub); 2253320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2263320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (!method->IsAbstract()) { 2272dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers const mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache(); 2284445a7e3398a6143939168097a3aa275b734504dIan Rogers const DexFile& dex_file = *dex_cache->GetDexFile(); 2290571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const CompiledMethod* compiled_method = 2300571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers compiler_->GetCompiledMethod(Compiler::MethodReference(&dex_file, 2310571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers method->GetDexMethodIndex())); 2323320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom CHECK(compiled_method != NULL) << PrettyMethod(method); 233f7015fd55a8dc969ac2440ffc829a6b4d942fb5aLogan Chien 234971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien const std::vector<uint8_t>& code = compiled_method->GetCode(); 235971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien MakeExecutable(code); 236971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien const void* method_code = CompiledMethod::CodePointer(&code[0], 237971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien compiled_method->GetInstructionSet()); 238f7015fd55a8dc969ac2440ffc829a6b4d942fb5aLogan Chien 2393320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code; 240f7015fd55a8dc969ac2440ffc829a6b4d942fb5aLogan Chien 241ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom OatFile::OatMethod oat_method = CreateOatMethod(method_code, 242ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom compiled_method->GetFrameSizeInBytes(), 243ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom compiled_method->GetCoreSpillMask(), 244ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom compiled_method->GetFpSpillMask(), 245ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom &compiled_method->GetMappingTable()[0], 246ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom &compiled_method->GetVmapTable()[0], 247e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom NULL, 248ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom method_invoke_stub); 249ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom oat_method.LinkMethodPointers(method); 2503320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } else { 2513320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom MakeExecutable(runtime_->GetAbstractMethodErrorStubArray()); 2523320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const void* method_code = runtime_->GetAbstractMethodErrorStubArray()->GetData(); 2533320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code; 254ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom OatFile::OatMethod oat_method = CreateOatMethod(method_code, 255ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom kStackAlignment, 256ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 0, 257ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 0, 258ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom NULL, 259ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom NULL, 260e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom NULL, 261ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom method_invoke_stub); 262ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom oat_method.LinkMethodPointers(method); 2633320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 2643320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 2653320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2663320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom static void MakeExecutable(const void* code_start, size_t code_length) { 2673320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom CHECK(code_start != NULL); 2683320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom CHECK_NE(code_length, 0U); 2693320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uintptr_t data = reinterpret_cast<uintptr_t>(code_start); 2709baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom uintptr_t base = RoundDown(data, kPageSize); 2713320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uintptr_t limit = RoundUp(data + code_length, kPageSize); 2729baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom uintptr_t len = limit - base; 2739baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom int result = mprotect(reinterpret_cast<void*>(base), len, PROT_READ | PROT_WRITE | PROT_EXEC); 2747a00a3c6c9a3425ba8331ee8e479040731db651bBrian Carlstrom CHECK_EQ(result, 0); 27524782c6aa7abf396de057d7eb15035b4c594a3b4Shih-wei Liao 2761634155a231665f16867cbecab9332a8b1cf3b1eIan Rogers // Flush instruction cache 27724782c6aa7abf396de057d7eb15035b4c594a3b4Shih-wei Liao // Only uses __builtin___clear_cache if GCC >= 4.3.3 27824782c6aa7abf396de057d7eb15035b4c594a3b4Shih-wei Liao#if GCC_VERSION >= 40303 2791634155a231665f16867cbecab9332a8b1cf3b1eIan Rogers __builtin___clear_cache(reinterpret_cast<void*>(base), reinterpret_cast<void*>(base + len)); 2807a00a3c6c9a3425ba8331ee8e479040731db651bBrian Carlstrom#elif defined(__APPLE__) 28124782c6aa7abf396de057d7eb15035b4c594a3b4Shih-wei Liao // Currently, only Mac OS builds use GCC 4.2.*. Those host builds do not 28224782c6aa7abf396de057d7eb15035b4c594a3b4Shih-wei Liao // need to generate clear_cache on x86. 2837a00a3c6c9a3425ba8331ee8e479040731db651bBrian Carlstrom#else 2847a00a3c6c9a3425ba8331ee8e479040731db651bBrian Carlstrom#error unsupported 28524782c6aa7abf396de057d7eb15035b4c594a3b4Shih-wei Liao#endif 2869baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom } 2879baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom 288761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes static void SetEnvironmentVariables(std::string& android_data) { 289761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes if (IsHost()) { 2900af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes // $ANDROID_ROOT is set on the device, but not on the host. 2910af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes // We need to set this so that icu4c can find its locale data. 2920af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes std::string root; 2930af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes root += getenv("ANDROID_BUILD_TOP"); 294a0cb1204543934b1f4975025cd6047eb71dc6429Elliott Hughes#if defined(__linux__) 2950af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes root += "/out/host/linux-x86"; 296a0cb1204543934b1f4975025cd6047eb71dc6429Elliott Hughes#elif defined(__APPLE__) 297a0cb1204543934b1f4975025cd6047eb71dc6429Elliott Hughes root += "/out/host/darwin-x86"; 298a0cb1204543934b1f4975025cd6047eb71dc6429Elliott Hughes#else 299a0cb1204543934b1f4975025cd6047eb71dc6429Elliott Hughes#error unsupported OS 300a0cb1204543934b1f4975025cd6047eb71dc6429Elliott Hughes#endif 3010af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes setenv("ANDROID_ROOT", root.c_str(), 1); 3022fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers setenv("LD_LIBRARY_PATH", ":", 0); // Required by java.lang.System.<clinit>. 3030af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes } 3040af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes 30569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom // On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of art-cache 306761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes android_data = (IsHost() ? "/tmp/art-data-XXXXXX" : "/data/art-cache/art-data-XXXXXX"); 307761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes if (mkdtemp(&android_data[0]) == NULL) { 308761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes PLOG(FATAL) << "mkdtemp(\"" << &android_data[0] << "\") failed"; 3090f4c41d75c821162184501cd4b510a93f6eb580fElliott Hughes } 310761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes setenv("ANDROID_DATA", android_data.c_str(), 1); 311761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes } 312761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes 313761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes protected: 314761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes static bool IsHost() { 315761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes return (getenv("ANDROID_BUILD_TOP") != NULL); 316761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes } 317761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes 318761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes virtual void SetUp() { 319761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes SetEnvironmentVariables(android_data_); 32034023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes art_cache_.append(android_data_.c_str()); 321b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom art_cache_.append("/art-cache"); 322b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom int mkdir_result = mkdir(art_cache_.c_str(), 0700); 323b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom ASSERT_EQ(mkdir_result, 0); 324b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 325a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom java_lang_dex_file_ = DexFile::Open(GetLibCoreDexFileName(), GetLibCoreDexFileName()); 326a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom boot_class_path_.push_back(java_lang_dex_file_); 327578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom 3280051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier std::string min_heap_string(StringPrintf("-Xms%zdm", Heap::kDefaultInitialSize / MB)); 3290051be6d118c511308ed7764ef41e0d594292c49Mathieu Chartier std::string max_heap_string(StringPrintf("-Xmx%zdm", Heap::kDefaultMaximumSize / MB)); 33030fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers 33169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom Runtime::Options options; 332a4a7b48c813ad73ac795d0b405de69755b36dd6bBrian Carlstrom options.push_back(std::make_pair("compiler", reinterpret_cast<void*>(NULL))); 333a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom options.push_back(std::make_pair("bootclasspath", &boot_class_path_)); 33469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom options.push_back(std::make_pair("-Xcheck:jni", reinterpret_cast<void*>(NULL))); 33530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers options.push_back(std::make_pair(min_heap_string.c_str(), reinterpret_cast<void*>(NULL))); 33630fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers options.push_back(std::make_pair(max_heap_string.c_str(), reinterpret_cast<void*>(NULL))); 33700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if(!Runtime::Create(options, false)) { 33800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers LOG(FATAL) << "Failed to create runtime"; 33900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return; 34000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 34100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers runtime_.reset(Runtime::Current()); 34200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start, 34300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // give it away now and then switch to a more managable ScopedObjectAccess. 34400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers Thread::Current()->TransitionFromRunnableToSuspended(kNative); 34500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Whilst we're in native take the opportunity to initialize well known classes. 34600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers WellKnownClasses::InitClasses(Thread::Current()->GetJniEnv()); 34700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 34890a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes ASSERT_TRUE(runtime_.get() != NULL); 3497a90959d4ef7a69f3bcb7b8763f646e12d9267d3Carl Shapiro class_linker_ = runtime_->GetClassLinker(); 3500cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers 3514f0d07c783afef89703dce32c94440fc8621a29bIan Rogers InstructionSet instruction_set = kNone; 352c0228b8f02c05ed58bea58490e0d8bdcaf8c5bb8jeffhao#if defined(__arm__) 3534f0d07c783afef89703dce32c94440fc8621a29bIan Rogers instruction_set = kThumb2; 354c0228b8f02c05ed58bea58490e0d8bdcaf8c5bb8jeffhao#elif defined(__mips__) 355c0228b8f02c05ed58bea58490e0d8bdcaf8c5bb8jeffhao instruction_set = kMips; 356c0228b8f02c05ed58bea58490e0d8bdcaf8c5bb8jeffhao#elif defined(__i386__) 357c0228b8f02c05ed58bea58490e0d8bdcaf8c5bb8jeffhao instruction_set = kX86; 3582c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers#endif 359c531cefbfb5394413122e9f57d211ba436cff012buzbee 360c531cefbfb5394413122e9f57d211ba436cff012buzbee // TODO: make selectable 361c531cefbfb5394413122e9f57d211ba436cff012buzbee#if defined(ART_USE_PORTABLE_COMPILER) 362c531cefbfb5394413122e9f57d211ba436cff012buzbee CompilerBackend compiler_backend = kPortable; 363c531cefbfb5394413122e9f57d211ba436cff012buzbee#elif defined(ART_USE_LLVM_COMPILER) 364c531cefbfb5394413122e9f57d211ba436cff012buzbee CompilerBackend compiler_backend = kIceland; // TODO: remove 365c531cefbfb5394413122e9f57d211ba436cff012buzbee#else 366c531cefbfb5394413122e9f57d211ba436cff012buzbee CompilerBackend compiler_backend = kQuick; 367c531cefbfb5394413122e9f57d211ba436cff012buzbee#endif 368c531cefbfb5394413122e9f57d211ba436cff012buzbee 3698add92dcf59568c72c17e9a979948b1a7a0b1264Elliott Hughes runtime_->SetJniDlsymLookupStub(Compiler::CreateJniDlsymLookupStub(instruction_set)); 3704f0d07c783afef89703dce32c94440fc8621a29bIan Rogers runtime_->SetAbstractMethodErrorStubArray(Compiler::CreateAbstractMethodErrorStub(instruction_set)); 371362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) { 3721cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers Runtime::TrampolineType type = Runtime::TrampolineType(i); 3731cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers if (!runtime_->HasResolutionStubArray(type)) { 3744f0d07c783afef89703dce32c94440fc8621a29bIan Rogers runtime_->SetResolutionStubArray( 3754f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Compiler::CreateResolutionStub(instruction_set, type), type); 3761cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers } 3771cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers } 3781984651929744dd603fd082e23eacd877b9bc177Ian Rogers if (!runtime_->HasResolutionMethod()) { 3791984651929744dd603fd082e23eacd877b9bc177Ian Rogers runtime_->SetResolutionMethod(runtime_->CreateResolutionMethod()); 3801984651929744dd603fd082e23eacd877b9bc177Ian Rogers } 381362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { 3824f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Runtime::CalleeSaveType type = Runtime::CalleeSaveType(i); 3834f0d07c783afef89703dce32c94440fc8621a29bIan Rogers if (!runtime_->HasCalleeSaveMethod(type)) { 3844f0d07c783afef89703dce32c94440fc8621a29bIan Rogers runtime_->SetCalleeSaveMethod( 3854f0d07c783afef89703dce32c94440fc8621a29bIan Rogers runtime_->CreateCalleeSaveMethod(instruction_set, type), type); 3864f0d07c783afef89703dce32c94440fc8621a29bIan Rogers } 3874f0d07c783afef89703dce32c94440fc8621a29bIan Rogers } 3881984651929744dd603fd082e23eacd877b9bc177Ian Rogers class_linker_->FixupDexCaches(runtime_->GetResolutionMethod()); 389e52e49b32f5cf862a414da63e5dbd2eb04ad758eElliott Hughes image_classes_.reset(new std::set<std::string>); 390c531cefbfb5394413122e9f57d211ba436cff012buzbee compiler_.reset(new Compiler(compiler_backend, instruction_set, true, 2, false, image_classes_.get(), 391ba0668ecd2a6459ed7c77012995ad08d27f88725Brian Carlstrom true, true)); 3922c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 39302b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier // Create the heap thread pool so that the GC runs in parallel for tests. Normally, the thread 39402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier // pool is created by the runtime. 39502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier runtime_->GetHeap()->CreateThreadPool(); 39602b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 39700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers runtime_->GetHeap()->VerifyHeap(); // Check for heap corruption before the test 398578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom } 399578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom 400b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom virtual void TearDown() { 401b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom const char* android_data = getenv("ANDROID_DATA"); 402b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom ASSERT_TRUE(android_data != NULL); 403b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom DIR* dir = opendir(art_cache_.c_str()); 404b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom ASSERT_TRUE(dir != NULL); 4054696b5b20be2f51f4ada5f3771a205d90bff351dElliott Hughes dirent* e; 4064696b5b20be2f51f4ada5f3771a205d90bff351dElliott Hughes while ((e = readdir(dir)) != NULL) { 4074696b5b20be2f51f4ada5f3771a205d90bff351dElliott Hughes if ((strcmp(e->d_name, ".") == 0) || (strcmp(e->d_name, "..") == 0)) { 408b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom continue; 409b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom } 410b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom std::string filename(art_cache_); 411b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom filename.push_back('/'); 4124696b5b20be2f51f4ada5f3771a205d90bff351dElliott Hughes filename.append(e->d_name); 413b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom int unlink_result = unlink(filename.c_str()); 414b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom ASSERT_EQ(0, unlink_result); 415b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom } 416b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom closedir(dir); 417b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom int rmdir_cache_result = rmdir(art_cache_.c_str()); 418b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom ASSERT_EQ(0, rmdir_cache_result); 41934023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes int rmdir_data_result = rmdir(android_data_.c_str()); 420b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom ASSERT_EQ(0, rmdir_data_result); 4210af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes 4220af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes // icu4c has a fixed 10-element array "gCommonICUDataArray". 4230af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes // If we run > 10 tests, we fill that array and u_setCommonData fails. 4240af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes // There's a function to clear the array, but it's not public... 4250af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes typedef void (*IcuCleanupFn)(); 4260af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes void* sym = dlsym(RTLD_DEFAULT, "u_cleanup_" U_ICU_VERSION_SHORT); 4270af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes CHECK(sym != NULL); 4280af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes IcuCleanupFn icu_cleanup_fn = reinterpret_cast<IcuCleanupFn>(sym); 4290af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes (*icu_cleanup_fn)(); 4300cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers 4310e073f7b9386a461b470d30415a96480ab1b76afIan Rogers compiler_.reset(); 432e52e49b32f5cf862a414da63e5dbd2eb04ad758eElliott Hughes image_classes_.reset(); 4334d6850c47515fe2a4f9de923befb6287bb863c8cElliott Hughes STLDeleteElements(&opened_dex_files_); 4342c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 435b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes Runtime::Current()->GetHeap()->VerifyHeap(); // Check for heap corruption after the test 436b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom } 437b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom 438b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom std::string GetLibCoreDexFileName() { 439761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes if (IsHost()) { 440b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom const char* host_dir = getenv("ANDROID_HOST_OUT"); 441b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom CHECK(host_dir != NULL); 442b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom return StringPrintf("%s/framework/core-hostdex.jar", host_dir); 443ac5b9e22d32c4f986783a2207b08ade769619f6fJesse Wilson } 444a56fcd60596ae8694da21fccde5c56832e437c56Brian Carlstrom return StringPrintf("%s/framework/core.jar", GetAndroidRoot()); 445b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom } 446ac5b9e22d32c4f986783a2207b08ade769619f6fJesse Wilson 4479f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstrom const DexFile* OpenTestDexFile(const char* name) { 4489f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstrom CHECK(name != NULL); 4499f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstrom std::string filename; 450761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes if (IsHost()) { 451b2793375d42b5d90d9a0111581c4314abe11ca4cBrian Carlstrom filename += getenv("ANDROID_HOST_OUT"); 452b2793375d42b5d90d9a0111581c4314abe11ca4cBrian Carlstrom filename += "/framework/"; 453b2793375d42b5d90d9a0111581c4314abe11ca4cBrian Carlstrom } else { 454b2793375d42b5d90d9a0111581c4314abe11ca4cBrian Carlstrom filename += "/data/nativetest/art/"; 4559f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstrom } 456b2793375d42b5d90d9a0111581c4314abe11ca4cBrian Carlstrom filename += "art-test-dex-"; 4579f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstrom filename += name; 4589f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstrom filename += ".jar"; 459a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom const DexFile* dex_file = DexFile::Open(filename, filename); 46069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom CHECK(dex_file != NULL) << "Failed to open " << filename; 4614d6850c47515fe2a4f9de923befb6287bb863c8cElliott Hughes opened_dex_files_.push_back(dex_file); 4629f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstrom return dex_file; 4639f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstrom } 4649f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstrom 46500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers jobject LoadDex(const char* dex_name) 466b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 4679baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom const DexFile* dex_file = OpenTestDexFile(dex_name); 4689baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom CHECK(dex_file != NULL); 4699baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom class_linker_->RegisterDexFile(*dex_file); 4709baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom std::vector<const DexFile*> class_path; 4719baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom class_path.push_back(dex_file); 47200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 47300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedLocalRef<jobject> class_loader_local(soa.Env(), 47400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader)); 47500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers jobject class_loader = soa.Env()->NewGlobalRef(class_loader_local.get()); 4762dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers soa.Self()->SetClassLoaderOverride(soa.Decode<mirror::ClassLoader*>(class_loader_local.get())); 47700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers Runtime::Current()->SetCompileTimeClassPath(class_loader, class_path); 47800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return class_loader; 4799baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom } 4809baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom 4812dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers void CompileClass(mirror::ClassLoader* class_loader, const char* class_name) { 482955724179c6c739524f610023287f56b24dc31deElliott Hughes std::string class_descriptor(DotToDescriptor(class_name)); 4832dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader); 484aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom CHECK(klass != NULL) << "Class not found " << class_name; 485aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom for (size_t i = 0; i < klass->NumDirectMethods(); i++) { 486aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom CompileMethod(klass->GetDirectMethod(i)); 487aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 488aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom for (size_t i = 0; i < klass->NumVirtualMethods(); i++) { 489aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom CompileMethod(klass->GetVirtualMethod(i)); 490aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 491aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 492aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 4932dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers void CompileMethod(mirror::AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 4949baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom CHECK(method != NULL); 4952c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers compiler_->CompileOne(method); 4963320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom MakeExecutable(method); 4973320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 498169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers MakeExecutable(runtime_->GetJniDlsymLookupStub()); 4999baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom } 5009baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom 5012dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers void CompileDirectMethod(mirror::ClassLoader* class_loader, 5029baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom const char* class_name, 5039baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom const char* method_name, 50400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers const char* signature) 505b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 506955724179c6c739524f610023287f56b24dc31deElliott Hughes std::string class_descriptor(DotToDescriptor(class_name)); 5072dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader); 5089baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom CHECK(klass != NULL) << "Class not found " << class_name; 5092dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::AbstractMethod* method = klass->FindDirectMethod(method_name, signature); 5100f4c41d75c821162184501cd4b510a93f6eb580fElliott Hughes CHECK(method != NULL) << "Direct method not found: " 5110f4c41d75c821162184501cd4b510a93f6eb580fElliott Hughes << class_name << "." << method_name << signature; 5129baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom CompileMethod(method); 5139baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom } 5149baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom 5152dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers void CompileVirtualMethod(mirror::ClassLoader* class_loader, 5169baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom const char* class_name, 5179baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom const char* method_name, 51800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers const char* signature) 519b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 520955724179c6c739524f610023287f56b24dc31deElliott Hughes std::string class_descriptor(DotToDescriptor(class_name)); 5212dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader); 5229baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom CHECK(klass != NULL) << "Class not found " << class_name; 5232dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::AbstractMethod* method = klass->FindVirtualMethod(method_name, signature); 5240f4c41d75c821162184501cd4b510a93f6eb580fElliott Hughes CHECK(method != NULL) << "Virtual method not found: " 5250f4c41d75c821162184501cd4b510a93f6eb580fElliott Hughes << class_name << "." << method_name << signature; 5269baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom CompileMethod(method); 5279baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom } 5289baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom 529700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom void ReserveImageSpace() { 530700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom // Reserve where the image will be loaded up front so that other parts of test set up don't 531700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom // accidentally end up colliding with the fixed memory address when we need to load the image. 532700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom image_reservation_.reset(MemMap::MapAnonymous("Image reservation", (byte*)ART_BASE_ADDRESS, 533700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom (size_t)100 * 1024 * 1024, // 100MB 534700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom PROT_NONE)); 535700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom } 536700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom 537700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom void UnreserveImageSpace() { 538700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom image_reservation_.reset(); 539700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom } 540700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom 54134023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes std::string android_data_; 542b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom std::string art_cache_; 543a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom const DexFile* java_lang_dex_file_; // owned by runtime_ 5449ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom std::vector<const DexFile*> boot_class_path_; 54590a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes UniquePtr<Runtime> runtime_; 5460e073f7b9386a461b470d30415a96480ab1b76afIan Rogers // Owned by the runtime 5477a90959d4ef7a69f3bcb7b8763f646e12d9267d3Carl Shapiro ClassLinker* class_linker_; 5480e073f7b9386a461b470d30415a96480ab1b76afIan Rogers UniquePtr<Compiler> compiler_; 549e52e49b32f5cf862a414da63e5dbd2eb04ad758eElliott Hughes UniquePtr<std::set<std::string> > image_classes_; 5509baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom 5519baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom private: 5524d6850c47515fe2a4f9de923befb6287bb863c8cElliott Hughes std::vector<const DexFile*> opened_dex_files_; 553700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom UniquePtr<MemMap> image_reservation_; 554578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom}; 555578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom 556b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes// Sets a CheckJni abort hook to catch failures. Note that this will cause CheckJNI to carry on 557b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes// rather than aborting, so be careful! 558b264f081424642b06b0bbe7102781895d41faa9dElliott Hughesclass CheckJniAbortCatcher { 559b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes public: 560b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) { 561b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes vm_->check_jni_abort_hook = Hook; 562b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes vm_->check_jni_abort_hook_data = &actual_; 563b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes } 564b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes 565b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes ~CheckJniAbortCatcher() { 566b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes vm_->check_jni_abort_hook = NULL; 567b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes vm_->check_jni_abort_hook_data = NULL; 56856ef042065ce282f8f01a0f31f5cce868a60ede8Elliott Hughes EXPECT_TRUE(actual_.empty()) << actual_; 569b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes } 570b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes 571b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes void Check(const char* expected_text) { 572b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes EXPECT_TRUE(actual_.find(expected_text) != std::string::npos) << "\n" 573b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes << "Expected to find: " << expected_text << "\n" 574b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes << "In the output : " << actual_; 5753f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes actual_.clear(); 576b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes } 577b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes 578b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes private: 579b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes static void Hook(void* data, const std::string& reason) { 5803f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // We use += because when we're hooking the aborts like this, multiple problems can be found. 5813f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes *reinterpret_cast<std::string*>(data) += reason; 582b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes } 583b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes 584b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes JavaVMExt* vm_; 585b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes std::string actual_; 586b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes 587b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes DISALLOW_COPY_AND_ASSIGN(CheckJniAbortCatcher); 588b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes}; 589b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes 590934486cf07c578b6494417ca5dcbae89cf04b019Brian Carlstrom} // namespace art 59134023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes 59234023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughesnamespace std { 59334023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes 59434023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes// TODO: isn't gtest supposed to be able to print STL types for itself? 59534023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughestemplate <typename T> 59634023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughesstd::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs) { 59714134a10e9bbaff0faf314dc00c1a1aeef8ef86bElliott Hughes os << ::art::ToString(rhs); 59834023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes return os; 59934023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes} 60034023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes 60134023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes} // namespace std 602