| Elliott Hughes | 2faa5f1 | 2012-01-30 14:42:07 -0800 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2011 The Android Open Source Project | 
 | 3 |  * | 
 | 4 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 |  * you may not use this file except in compliance with the License. | 
 | 6 |  * You may obtain a copy of the License at | 
 | 7 |  * | 
 | 8 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 |  * | 
 | 10 |  * Unless required by applicable law or agreed to in writing, software | 
 | 11 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 |  * See the License for the specific language governing permissions and | 
 | 14 |  * limitations under the License. | 
 | 15 |  */ | 
| Brian Carlstrom | 934486c | 2011-07-12 23:42:50 -0700 | [diff] [blame] | 16 |  | 
| Brian Carlstrom | fc0e321 | 2013-07-17 14:40:12 -0700 | [diff] [blame] | 17 | #ifndef ART_RUNTIME_COMMON_TEST_H_ | 
 | 18 | #define ART_RUNTIME_COMMON_TEST_H_ | 
 | 19 |  | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 20 | #include <dirent.h> | 
| Elliott Hughes | 0af5543 | 2011-08-17 18:37:28 -0700 | [diff] [blame] | 21 | #include <dlfcn.h> | 
| Brian Carlstrom | 27ec961 | 2011-09-19 20:20:38 -0700 | [diff] [blame] | 22 | #include <sys/mman.h> | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 23 | #include <sys/stat.h> | 
 | 24 | #include <sys/types.h> | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 25 | #include <fstream> | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 26 |  | 
| Elliott Hughes | f66330a | 2012-12-12 17:27:00 -0800 | [diff] [blame] | 27 | #include "../../external/icu4c/common/unicode/uvernum.h" | 
| Sebastien Hertz | 102a8f2 | 2013-12-18 11:41:30 +0100 | [diff] [blame] | 28 | #include "../compiler/dex/quick/dex_file_to_method_inliner_map.h" | 
 | 29 | #include "../compiler/dex/verified_methods_data.h" | 
 | 30 | #include "../compiler/driver/compiler_driver.h" | 
| Elliott Hughes | 7616005 | 2012-12-12 16:31:20 -0800 | [diff] [blame] | 31 | #include "base/macros.h" | 
| Elliott Hughes | 1aa246d | 2012-12-13 09:29:36 -0800 | [diff] [blame] | 32 | #include "base/stl_util.h" | 
| Elliott Hughes | e222ee0 | 2012-12-13 14:41:43 -0800 | [diff] [blame] | 33 | #include "base/stringprintf.h" | 
| Elliott Hughes | 7616005 | 2012-12-12 16:31:20 -0800 | [diff] [blame] | 34 | #include "base/unix_file/fd_file.h" | 
| Brian Carlstrom | 578bbdc | 2011-07-21 14:07:47 -0700 | [diff] [blame] | 35 | #include "class_linker.h" | 
| Vladimir Marko | 95a4de7 | 2013-12-18 10:29:11 +0000 | [diff] [blame] | 36 | #include "compiler_callbacks.h" | 
| Ian Rogers | 4f6ad8a | 2013-03-18 15:27:28 -0700 | [diff] [blame] | 37 | #include "dex_file-inl.h" | 
| Ian Rogers | 7655f29 | 2013-07-29 11:07:13 -0700 | [diff] [blame] | 38 | #include "entrypoints/entrypoint_utils.h" | 
| Ian Rogers | 1d54e73 | 2013-05-02 21:10:01 -0700 | [diff] [blame] | 39 | #include "gc/heap.h" | 
| Elliott Hughes | 90a3369 | 2011-08-30 13:27:07 -0700 | [diff] [blame] | 40 | #include "gtest/gtest.h" | 
| Elliott Hughes | 0f3c553 | 2012-03-30 14:51:51 -0700 | [diff] [blame] | 41 | #include "instruction_set.h" | 
| Ian Rogers | 0f40ac3 | 2013-08-13 22:10:30 -0700 | [diff] [blame] | 42 | #include "interpreter/interpreter.h" | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 43 | #include "mirror/class_loader.h" | 
| Brian Carlstrom | 3320cf4 | 2011-10-04 14:58:28 -0700 | [diff] [blame] | 44 | #include "oat_file.h" | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 45 | #include "object_utils.h" | 
| Brian Carlstrom | 33f741e | 2011-10-03 11:24:05 -0700 | [diff] [blame] | 46 | #include "os.h" | 
| Brian Carlstrom | 1f87008 | 2011-08-23 16:02:11 -0700 | [diff] [blame] | 47 | #include "runtime.h" | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 48 | #include "scoped_thread_state_change.h" | 
| Elliott Hughes | e222ee0 | 2012-12-13 14:41:43 -0800 | [diff] [blame] | 49 | #include "ScopedLocalRef.h" | 
| Elliott Hughes | 90a3369 | 2011-08-30 13:27:07 -0700 | [diff] [blame] | 50 | #include "thread.h" | 
| Elliott Hughes | 0f3c553 | 2012-03-30 14:51:51 -0700 | [diff] [blame] | 51 | #include "UniquePtr.h" | 
| Vladimir Marko | 95a4de7 | 2013-12-18 10:29:11 +0000 | [diff] [blame] | 52 | #include "verifier/method_verifier.h" | 
 | 53 | #include "verifier/method_verifier-inl.h" | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 54 | #include "well_known_classes.h" | 
| Elliott Hughes | 0af5543 | 2011-08-17 18:37:28 -0700 | [diff] [blame] | 55 |  | 
| Brian Carlstrom | 934486c | 2011-07-12 23:42:50 -0700 | [diff] [blame] | 56 | namespace art { | 
 | 57 |  | 
| Brian Carlstrom | b9cc1ca | 2012-01-27 00:57:42 -0800 | [diff] [blame] | 58 | static const byte kBase64Map[256] = { | 
 | 59 |   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | 
 | 60 |   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | 
 | 61 |   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | 
 | 62 |   255, 255, 255, 255, 255, 255, 255,  62, 255, 255, 255,  63, | 
 | 63 |   52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255, | 
 | 64 |   255, 254, 255, 255, 255,   0,   1,   2,   3,   4,   5,   6, | 
| Brian Carlstrom | 7934ac2 | 2013-07-26 10:54:15 -0700 | [diff] [blame] | 65 |     7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,  // NOLINT | 
 | 66 |    19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255, 255,  // NOLINT | 
| Brian Carlstrom | b9cc1ca | 2012-01-27 00:57:42 -0800 | [diff] [blame] | 67 |   255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36, | 
| Brian Carlstrom | 7934ac2 | 2013-07-26 10:54:15 -0700 | [diff] [blame] | 68 |    37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  // NOLINT | 
 | 69 |    49,  50,  51, 255, 255, 255, 255, 255, 255, 255, 255, 255,  // NOLINT | 
| Brian Carlstrom | b9cc1ca | 2012-01-27 00:57:42 -0800 | [diff] [blame] | 70 |   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | 
 | 71 |   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | 
 | 72 |   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | 
 | 73 |   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | 
 | 74 |   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | 
 | 75 |   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | 
 | 76 |   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | 
 | 77 |   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | 
 | 78 |   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | 
 | 79 |   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | 
 | 80 |   255, 255, 255, 255 | 
 | 81 | }; | 
 | 82 |  | 
 | 83 | byte* DecodeBase64(const char* src, size_t* dst_size) { | 
 | 84 |   std::vector<byte> tmp; | 
| Elliott Hughes | a21039c | 2012-06-21 12:09:25 -0700 | [diff] [blame] | 85 |   uint32_t t = 0, y = 0; | 
| Brian Carlstrom | b9cc1ca | 2012-01-27 00:57:42 -0800 | [diff] [blame] | 86 |   int g = 3; | 
 | 87 |   for (size_t i = 0; src[i] != '\0'; ++i) { | 
 | 88 |     byte c = kBase64Map[src[i] & 0xFF]; | 
 | 89 |     if (c == 255) continue; | 
 | 90 |     // the final = symbols are read and used to trim the remaining bytes | 
 | 91 |     if (c == 254) { | 
 | 92 |       c = 0; | 
 | 93 |       // prevent g < 0 which would potentially allow an overflow later | 
 | 94 |       if (--g < 0) { | 
| Brian Carlstrom | 5147733 | 2012-03-25 20:20:26 -0700 | [diff] [blame] | 95 |         *dst_size = 0; | 
| Brian Carlstrom | b9cc1ca | 2012-01-27 00:57:42 -0800 | [diff] [blame] | 96 |         return NULL; | 
 | 97 |       } | 
 | 98 |     } else if (g != 3) { | 
 | 99 |       // we only allow = to be at the end | 
| Brian Carlstrom | 5147733 | 2012-03-25 20:20:26 -0700 | [diff] [blame] | 100 |       *dst_size = 0; | 
| Brian Carlstrom | b9cc1ca | 2012-01-27 00:57:42 -0800 | [diff] [blame] | 101 |       return NULL; | 
 | 102 |     } | 
 | 103 |     t = (t << 6) | c; | 
 | 104 |     if (++y == 4) { | 
 | 105 |       tmp.push_back((t >> 16) & 255); | 
 | 106 |       if (g > 1) { | 
 | 107 |         tmp.push_back((t >> 8) & 255); | 
 | 108 |       } | 
 | 109 |       if (g > 2) { | 
 | 110 |         tmp.push_back(t & 255); | 
 | 111 |       } | 
 | 112 |       y = t = 0; | 
 | 113 |     } | 
 | 114 |   } | 
 | 115 |   if (y != 0) { | 
| Brian Carlstrom | 5147733 | 2012-03-25 20:20:26 -0700 | [diff] [blame] | 116 |     *dst_size = 0; | 
| Brian Carlstrom | b9cc1ca | 2012-01-27 00:57:42 -0800 | [diff] [blame] | 117 |     return NULL; | 
 | 118 |   } | 
 | 119 |   UniquePtr<byte[]> dst(new byte[tmp.size()]); | 
 | 120 |   if (dst_size != NULL) { | 
 | 121 |     *dst_size = tmp.size(); | 
| Brian Carlstrom | 5147733 | 2012-03-25 20:20:26 -0700 | [diff] [blame] | 122 |   } else { | 
 | 123 |     *dst_size = 0; | 
| Brian Carlstrom | b9cc1ca | 2012-01-27 00:57:42 -0800 | [diff] [blame] | 124 |   } | 
 | 125 |   std::copy(tmp.begin(), tmp.end(), dst.get()); | 
 | 126 |   return dst.release(); | 
 | 127 | } | 
 | 128 |  | 
| Brian Carlstrom | db4d540 | 2011-08-09 12:18:28 -0700 | [diff] [blame] | 129 | class ScratchFile { | 
 | 130 |  public: | 
 | 131 |   ScratchFile() { | 
| Elliott Hughes | 3402380 | 2011-08-30 12:06:17 -0700 | [diff] [blame] | 132 |     filename_ = getenv("ANDROID_DATA"); | 
 | 133 |     filename_ += "/TmpFile-XXXXXX"; | 
| Elliott Hughes | 7616005 | 2012-12-12 16:31:20 -0800 | [diff] [blame] | 134 |     int fd = mkstemp(&filename_[0]); | 
 | 135 |     CHECK_NE(-1, fd); | 
 | 136 |     file_.reset(new File(fd, GetFilename())); | 
| Brian Carlstrom | db4d540 | 2011-08-09 12:18:28 -0700 | [diff] [blame] | 137 |   } | 
 | 138 |  | 
 | 139 |   ~ScratchFile() { | 
| Elliott Hughes | 3402380 | 2011-08-30 12:06:17 -0700 | [diff] [blame] | 140 |     int unlink_result = unlink(filename_.c_str()); | 
| Brian Carlstrom | db4d540 | 2011-08-09 12:18:28 -0700 | [diff] [blame] | 141 |     CHECK_EQ(0, unlink_result); | 
| Brian Carlstrom | db4d540 | 2011-08-09 12:18:28 -0700 | [diff] [blame] | 142 |   } | 
 | 143 |  | 
| Brian Carlstrom | a004aa9 | 2012-02-08 18:05:09 -0800 | [diff] [blame] | 144 |   const std::string& GetFilename() const { | 
 | 145 |     return filename_; | 
| Brian Carlstrom | db4d540 | 2011-08-09 12:18:28 -0700 | [diff] [blame] | 146 |   } | 
 | 147 |  | 
| Elliott Hughes | 234da57 | 2011-11-03 22:13:06 -0700 | [diff] [blame] | 148 |   File* GetFile() const { | 
 | 149 |     return file_.get(); | 
 | 150 |   } | 
 | 151 |  | 
| Brian Carlstrom | db4d540 | 2011-08-09 12:18:28 -0700 | [diff] [blame] | 152 |   int GetFd() const { | 
| Elliott Hughes | 7616005 | 2012-12-12 16:31:20 -0800 | [diff] [blame] | 153 |     return file_->Fd(); | 
| Brian Carlstrom | db4d540 | 2011-08-09 12:18:28 -0700 | [diff] [blame] | 154 |   } | 
 | 155 |  | 
 | 156 |  private: | 
| Elliott Hughes | 3402380 | 2011-08-30 12:06:17 -0700 | [diff] [blame] | 157 |   std::string filename_; | 
| Elliott Hughes | 234da57 | 2011-11-03 22:13:06 -0700 | [diff] [blame] | 158 |   UniquePtr<File> file_; | 
| Brian Carlstrom | db4d540 | 2011-08-09 12:18:28 -0700 | [diff] [blame] | 159 | }; | 
 | 160 |  | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 161 | #if defined(__arm__) | 
 | 162 |  | 
 | 163 |  | 
 | 164 | #include <signal.h> | 
 | 165 | #include <asm/sigcontext.h> | 
| Christopher Ferris | f0d5f55 | 2013-12-16 15:05:39 -0800 | [diff] [blame] | 166 | #include <asm-generic/ucontext.h> | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 167 |  | 
 | 168 |  | 
 | 169 | // A signal handler called when have an illegal instruction.  We record the fact in | 
 | 170 | // a global boolean and then increment the PC in the signal context to return to | 
 | 171 | // the next instruction.  We know the instruction is an sdiv (4 bytes long). | 
 | 172 | static void baddivideinst(int signo, siginfo *si, void *data) { | 
 | 173 |   (void)signo; | 
 | 174 |   (void)si; | 
 | 175 |   struct ucontext *uc = (struct ucontext *)data; | 
 | 176 |   struct sigcontext *sc = &uc->uc_mcontext; | 
 | 177 |   sc->arm_r0 = 0;     // set R0 to #0 to signal error | 
 | 178 |   sc->arm_pc += 4;    // skip offending instruction | 
 | 179 | } | 
 | 180 |  | 
 | 181 | // This is in arch/arm/arm_sdiv.S.  It does the following: | 
 | 182 | // mov r1,#1 | 
 | 183 | // sdiv r0,r1,r1 | 
 | 184 | // bx lr | 
 | 185 | // | 
 | 186 | // the result will be the value 1 if sdiv is supported.  If it is not supported | 
 | 187 | // a SIGILL signal will be raised and the signal handler (baddivideinst) called. | 
 | 188 | // The signal handler sets r0 to #0 and then increments pc beyond the failed instruction. | 
 | 189 | // Thus if the instruction is not supported, the result of this function will be #0 | 
 | 190 |  | 
 | 191 | extern "C" bool CheckForARMSDIVInstruction(); | 
 | 192 |  | 
 | 193 | static InstructionSetFeatures GuessInstructionFeatures() { | 
 | 194 |   InstructionSetFeatures f; | 
 | 195 |  | 
 | 196 |   // Uncomment this for processing of /proc/cpuinfo. | 
 | 197 |   if (false) { | 
 | 198 |     // Look in /proc/cpuinfo for features we need.  Only use this when we can guarantee that | 
 | 199 |     // the kernel puts the appropriate feature flags in here.  Sometimes it doesn't. | 
 | 200 |     std::ifstream in("/proc/cpuinfo"); | 
 | 201 |     if (in) { | 
 | 202 |       while (!in.eof()) { | 
 | 203 |         std::string line; | 
 | 204 |         std::getline(in, line); | 
 | 205 |         if (!in.eof()) { | 
 | 206 |           if (line.find("Features") != std::string::npos) { | 
 | 207 |             if (line.find("idivt") != std::string::npos) { | 
 | 208 |               f.SetHasDivideInstruction(true); | 
 | 209 |             } | 
 | 210 |           } | 
 | 211 |         } | 
 | 212 |         in.close(); | 
 | 213 |       } | 
 | 214 |     } else { | 
 | 215 |       LOG(INFO) << "Failed to open /proc/cpuinfo"; | 
 | 216 |     } | 
 | 217 |   } | 
 | 218 |  | 
 | 219 |   // See if have a sdiv instruction.  Register a signal handler and try to execute | 
 | 220 |   // an sdiv instruction.  If we get a SIGILL then it's not supported.  We can't use | 
 | 221 |   // the /proc/cpuinfo method for this because Krait devices don't always put the idivt | 
 | 222 |   // feature in the list. | 
 | 223 |   struct sigaction sa, osa; | 
 | 224 |   sa.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO; | 
 | 225 |   sa.sa_sigaction = baddivideinst; | 
 | 226 |   sigaction(SIGILL, &sa, &osa); | 
 | 227 |  | 
 | 228 |   if (CheckForARMSDIVInstruction()) { | 
 | 229 |     f.SetHasDivideInstruction(true); | 
 | 230 |   } | 
 | 231 |  | 
 | 232 |   // Restore the signal handler. | 
 | 233 |   sigaction(SIGILL, &osa, NULL); | 
 | 234 |  | 
 | 235 |   // Other feature guesses in here. | 
 | 236 |   return f; | 
 | 237 | } | 
 | 238 |  | 
 | 239 | #endif | 
 | 240 |  | 
 | 241 | // Given a set of instruction features from the build, parse it.  The | 
 | 242 | // input 'str' is a comma separated list of feature names.  Parse it and | 
 | 243 | // return the InstructionSetFeatures object. | 
 | 244 | static InstructionSetFeatures ParseFeatureList(std::string str) { | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 245 |   InstructionSetFeatures result; | 
 | 246 |   typedef std::vector<std::string> FeatureList; | 
 | 247 |   FeatureList features; | 
 | 248 |   Split(str, ',', features); | 
 | 249 |   for (FeatureList::iterator i = features.begin(); i != features.end(); i++) { | 
 | 250 |     std::string feature = Trim(*i); | 
 | 251 |     if (feature == "default") { | 
 | 252 |       // Nothing to do. | 
 | 253 |     } else if (feature == "div") { | 
 | 254 |       // Supports divide instruction. | 
 | 255 |       result.SetHasDivideInstruction(true); | 
 | 256 |     } else if (feature == "nodiv") { | 
 | 257 |       // Turn off support for divide instruction. | 
 | 258 |       result.SetHasDivideInstruction(false); | 
 | 259 |     } else { | 
 | 260 |       LOG(FATAL) << "Unknown instruction set feature: '" << feature << "'"; | 
 | 261 |     } | 
 | 262 |   } | 
 | 263 |   // Others... | 
 | 264 |   return result; | 
 | 265 | } | 
 | 266 |  | 
| Brian Carlstrom | f734cf5 | 2011-08-17 16:28:14 -0700 | [diff] [blame] | 267 | class CommonTest : public testing::Test { | 
| Brian Carlstrom | 9baa4ae | 2011-09-01 21:14:14 -0700 | [diff] [blame] | 268 |  public: | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 269 |   static void MakeExecutable(const mirror::ByteArray* code_array) { | 
| Brian Carlstrom | 3320cf4 | 2011-10-04 14:58:28 -0700 | [diff] [blame] | 270 |     CHECK(code_array != NULL); | 
 | 271 |     MakeExecutable(code_array->GetData(), code_array->GetLength()); | 
 | 272 |   } | 
 | 273 |  | 
| Shih-wei Liao | 1cb0ae7 | 2012-03-16 15:30:19 -0700 | [diff] [blame] | 274 |   static void MakeExecutable(const std::vector<uint8_t>& code) { | 
| Brian Carlstrom | 3320cf4 | 2011-10-04 14:58:28 -0700 | [diff] [blame] | 275 |     CHECK_NE(code.size(), 0U); | 
 | 276 |     MakeExecutable(&code[0], code.size()); | 
 | 277 |   } | 
 | 278 |  | 
| Brian Carlstrom | ae82698 | 2011-11-09 01:33:42 -0800 | [diff] [blame] | 279 |   // Create an OatMethod based on pointers (for unit tests) | 
 | 280 |   OatFile::OatMethod CreateOatMethod(const void* code, | 
 | 281 |                                      const size_t frame_size_in_bytes, | 
 | 282 |                                      const uint32_t core_spill_mask, | 
 | 283 |                                      const uint32_t fp_spill_mask, | 
| Ian Rogers | 1809a72 | 2013-08-09 22:05:32 -0700 | [diff] [blame] | 284 |                                      const uint8_t* mapping_table, | 
 | 285 |                                      const uint8_t* vmap_table, | 
| Jeff Hao | 74180ca | 2013-03-27 15:29:11 -0700 | [diff] [blame] | 286 |                                      const uint8_t* gc_map) { | 
| Brian Carlstrom | ae82698 | 2011-11-09 01:33:42 -0800 | [diff] [blame] | 287 |       return OatFile::OatMethod(NULL, | 
 | 288 |                                 reinterpret_cast<uint32_t>(code), | 
 | 289 |                                 frame_size_in_bytes, | 
 | 290 |                                 core_spill_mask, | 
 | 291 |                                 fp_spill_mask, | 
 | 292 |                                 reinterpret_cast<uint32_t>(mapping_table), | 
 | 293 |                                 reinterpret_cast<uint32_t>(vmap_table), | 
| Brian Carlstrom | df62950 | 2013-07-17 22:39:56 -0700 | [diff] [blame] | 294 |                                 reinterpret_cast<uint32_t>(gc_map)); | 
| Brian Carlstrom | ae82698 | 2011-11-09 01:33:42 -0800 | [diff] [blame] | 295 |   } | 
 | 296 |  | 
| Brian Carlstrom | ea46f95 | 2013-07-30 01:26:50 -0700 | [diff] [blame] | 297 |   void MakeExecutable(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
| Brian Carlstrom | 3320cf4 | 2011-10-04 14:58:28 -0700 | [diff] [blame] | 298 |     CHECK(method != NULL); | 
| Brian Carlstrom | 3320cf4 | 2011-10-04 14:58:28 -0700 | [diff] [blame] | 299 |  | 
| Ian Rogers | f3e9855 | 2013-03-20 15:49:49 -0700 | [diff] [blame] | 300 |     const CompiledMethod* compiled_method = NULL; | 
| Brian Carlstrom | 3320cf4 | 2011-10-04 14:58:28 -0700 | [diff] [blame] | 301 |     if (!method->IsAbstract()) { | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 302 |       const mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache(); | 
| Ian Rogers | 4445a7e | 2012-10-05 17:19:13 -0700 | [diff] [blame] | 303 |       const DexFile& dex_file = *dex_cache->GetDexFile(); | 
| Ian Rogers | f3e9855 | 2013-03-20 15:49:49 -0700 | [diff] [blame] | 304 |       compiled_method = | 
| Brian Carlstrom | 51c2467 | 2013-07-11 16:00:56 -0700 | [diff] [blame] | 305 |           compiler_driver_->GetCompiledMethod(MethodReference(&dex_file, | 
 | 306 |                                                               method->GetDexMethodIndex())); | 
| Ian Rogers | f3e9855 | 2013-03-20 15:49:49 -0700 | [diff] [blame] | 307 |     } | 
 | 308 |     if (compiled_method != NULL) { | 
| Logan Chien | 971bf3f | 2012-05-01 15:47:55 +0800 | [diff] [blame] | 309 |       const std::vector<uint8_t>& code = compiled_method->GetCode(); | 
 | 310 |       MakeExecutable(code); | 
 | 311 |       const void* method_code = CompiledMethod::CodePointer(&code[0], | 
 | 312 |                                                             compiled_method->GetInstructionSet()); | 
| Brian Carlstrom | 3320cf4 | 2011-10-04 14:58:28 -0700 | [diff] [blame] | 313 |       LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code; | 
| Brian Carlstrom | ae82698 | 2011-11-09 01:33:42 -0800 | [diff] [blame] | 314 |       OatFile::OatMethod oat_method = CreateOatMethod(method_code, | 
 | 315 |                                                       compiled_method->GetFrameSizeInBytes(), | 
 | 316 |                                                       compiled_method->GetCoreSpillMask(), | 
 | 317 |                                                       compiled_method->GetFpSpillMask(), | 
 | 318 |                                                       &compiled_method->GetMappingTable()[0], | 
 | 319 |                                                       &compiled_method->GetVmapTable()[0], | 
| Jeff Hao | 74180ca | 2013-03-27 15:29:11 -0700 | [diff] [blame] | 320 |                                                       NULL); | 
| Brian Carlstrom | 265091e | 2013-01-30 14:08:26 -0800 | [diff] [blame] | 321 |       oat_method.LinkMethod(method); | 
| Ian Rogers | 0f40ac3 | 2013-08-13 22:10:30 -0700 | [diff] [blame] | 322 |       method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge); | 
| Brian Carlstrom | 3320cf4 | 2011-10-04 14:58:28 -0700 | [diff] [blame] | 323 |     } else { | 
| Ian Rogers | f3e9855 | 2013-03-20 15:49:49 -0700 | [diff] [blame] | 324 |       const void* method_code; | 
| Ian Rogers | 848871b | 2013-08-05 10:56:33 -0700 | [diff] [blame] | 325 |       // No code? You must mean to go into the interpreter. | 
 | 326 |       method_code = GetCompiledCodeToInterpreterBridge(); | 
| Brian Carlstrom | ae82698 | 2011-11-09 01:33:42 -0800 | [diff] [blame] | 327 |       OatFile::OatMethod oat_method = CreateOatMethod(method_code, | 
 | 328 |                                                       kStackAlignment, | 
 | 329 |                                                       0, | 
 | 330 |                                                       0, | 
 | 331 |                                                       NULL, | 
 | 332 |                                                       NULL, | 
| Jeff Hao | 74180ca | 2013-03-27 15:29:11 -0700 | [diff] [blame] | 333 |                                                       NULL); | 
| Brian Carlstrom | 265091e | 2013-01-30 14:08:26 -0800 | [diff] [blame] | 334 |       oat_method.LinkMethod(method); | 
| Ian Rogers | 0f40ac3 | 2013-08-13 22:10:30 -0700 | [diff] [blame] | 335 |       method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge); | 
| Brian Carlstrom | 3320cf4 | 2011-10-04 14:58:28 -0700 | [diff] [blame] | 336 |     } | 
 | 337 |   } | 
 | 338 |  | 
 | 339 |   static void MakeExecutable(const void* code_start, size_t code_length) { | 
 | 340 |     CHECK(code_start != NULL); | 
 | 341 |     CHECK_NE(code_length, 0U); | 
 | 342 |     uintptr_t data = reinterpret_cast<uintptr_t>(code_start); | 
| Brian Carlstrom | 9baa4ae | 2011-09-01 21:14:14 -0700 | [diff] [blame] | 343 |     uintptr_t base = RoundDown(data, kPageSize); | 
| Brian Carlstrom | 3320cf4 | 2011-10-04 14:58:28 -0700 | [diff] [blame] | 344 |     uintptr_t limit = RoundUp(data + code_length, kPageSize); | 
| Brian Carlstrom | 9baa4ae | 2011-09-01 21:14:14 -0700 | [diff] [blame] | 345 |     uintptr_t len = limit - base; | 
 | 346 |     int result = mprotect(reinterpret_cast<void*>(base), len, PROT_READ | PROT_WRITE | PROT_EXEC); | 
| Brian Carlstrom | 7a00a3c | 2012-01-25 18:38:03 -0800 | [diff] [blame] | 347 |     CHECK_EQ(result, 0); | 
| Shih-wei Liao | 24782c6 | 2012-01-08 12:46:11 -0800 | [diff] [blame] | 348 |  | 
| Ian Rogers | 1634155 | 2011-10-10 11:33:06 -0700 | [diff] [blame] | 349 |     // Flush instruction cache | 
| Shih-wei Liao | 24782c6 | 2012-01-08 12:46:11 -0800 | [diff] [blame] | 350 |     // Only uses __builtin___clear_cache if GCC >= 4.3.3 | 
 | 351 | #if GCC_VERSION >= 40303 | 
| Ian Rogers | 1634155 | 2011-10-10 11:33:06 -0700 | [diff] [blame] | 352 |     __builtin___clear_cache(reinterpret_cast<void*>(base), reinterpret_cast<void*>(base + len)); | 
| Brian Carlstrom | 7a00a3c | 2012-01-25 18:38:03 -0800 | [diff] [blame] | 353 | #else | 
| Brian Carlstrom | 6f485c6 | 2013-07-18 15:35:35 -0700 | [diff] [blame] | 354 |     LOG(FATAL) << "UNIMPLEMENTED: cache flush"; | 
| Shih-wei Liao | 24782c6 | 2012-01-08 12:46:11 -0800 | [diff] [blame] | 355 | #endif | 
| Brian Carlstrom | 9baa4ae | 2011-09-01 21:14:14 -0700 | [diff] [blame] | 356 |   } | 
 | 357 |  | 
| Elliott Hughes | 7616005 | 2012-12-12 16:31:20 -0800 | [diff] [blame] | 358 |   static void SetEnvironmentVariables(std::string& android_data) { | 
 | 359 |     if (IsHost()) { | 
| Elliott Hughes | 0af5543 | 2011-08-17 18:37:28 -0700 | [diff] [blame] | 360 |       // $ANDROID_ROOT is set on the device, but not on the host. | 
 | 361 |       // We need to set this so that icu4c can find its locale data. | 
 | 362 |       std::string root; | 
 | 363 |       root += getenv("ANDROID_BUILD_TOP"); | 
| Elliott Hughes | a0cb120 | 2012-01-23 17:34:32 -0800 | [diff] [blame] | 364 | #if defined(__linux__) | 
| Elliott Hughes | 0af5543 | 2011-08-17 18:37:28 -0700 | [diff] [blame] | 365 |       root += "/out/host/linux-x86"; | 
| Elliott Hughes | a0cb120 | 2012-01-23 17:34:32 -0800 | [diff] [blame] | 366 | #elif defined(__APPLE__) | 
 | 367 |       root += "/out/host/darwin-x86"; | 
 | 368 | #else | 
 | 369 | #error unsupported OS | 
 | 370 | #endif | 
| Elliott Hughes | 0af5543 | 2011-08-17 18:37:28 -0700 | [diff] [blame] | 371 |       setenv("ANDROID_ROOT", root.c_str(), 1); | 
| Ian Rogers | 2fa6b2e | 2012-10-17 00:10:17 -0700 | [diff] [blame] | 372 |       setenv("LD_LIBRARY_PATH", ":", 0);  // Required by java.lang.System.<clinit>. | 
| Elliott Hughes | 0af5543 | 2011-08-17 18:37:28 -0700 | [diff] [blame] | 373 |     } | 
 | 374 |  | 
| Brian Carlstrom | 7675e16 | 2013-06-10 16:18:04 -0700 | [diff] [blame] | 375 |     // On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of dalvik-cache | 
 | 376 |     android_data = (IsHost() ? "/tmp/art-data-XXXXXX" : "/data/dalvik-cache/art-data-XXXXXX"); | 
| Elliott Hughes | 7616005 | 2012-12-12 16:31:20 -0800 | [diff] [blame] | 377 |     if (mkdtemp(&android_data[0]) == NULL) { | 
 | 378 |       PLOG(FATAL) << "mkdtemp(\"" << &android_data[0] << "\") failed"; | 
| Elliott Hughes | 0f4c41d | 2011-09-04 14:58:03 -0700 | [diff] [blame] | 379 |     } | 
| Elliott Hughes | 7616005 | 2012-12-12 16:31:20 -0800 | [diff] [blame] | 380 |     setenv("ANDROID_DATA", android_data.c_str(), 1); | 
 | 381 |   } | 
 | 382 |  | 
| Ian Rogers | 1d99e45 | 2014-01-02 17:36:41 -0800 | [diff] [blame] | 383 |   void MakeExecutable(mirror::ClassLoader* class_loader, const char* class_name) | 
 | 384 |       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
 | 385 |     std::string class_descriptor(DotToDescriptor(class_name)); | 
 | 386 |     SirtRef<mirror::ClassLoader> loader(Thread::Current(), class_loader); | 
 | 387 |     mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), loader); | 
 | 388 |     CHECK(klass != NULL) << "Class not found " << class_name; | 
 | 389 |     for (size_t i = 0; i < klass->NumDirectMethods(); i++) { | 
 | 390 |       MakeExecutable(klass->GetDirectMethod(i)); | 
 | 391 |     } | 
 | 392 |     for (size_t i = 0; i < klass->NumVirtualMethods(); i++) { | 
 | 393 |       MakeExecutable(klass->GetVirtualMethod(i)); | 
 | 394 |     } | 
 | 395 |   } | 
 | 396 |  | 
| Elliott Hughes | 7616005 | 2012-12-12 16:31:20 -0800 | [diff] [blame] | 397 |  protected: | 
 | 398 |   static bool IsHost() { | 
 | 399 |     return (getenv("ANDROID_BUILD_TOP") != NULL); | 
 | 400 |   } | 
 | 401 |  | 
 | 402 |   virtual void SetUp() { | 
 | 403 |     SetEnvironmentVariables(android_data_); | 
| Brian Carlstrom | 7675e16 | 2013-06-10 16:18:04 -0700 | [diff] [blame] | 404 |     dalvik_cache_.append(android_data_.c_str()); | 
 | 405 |     dalvik_cache_.append("/dalvik-cache"); | 
 | 406 |     int mkdir_result = mkdir(dalvik_cache_.c_str(), 0700); | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 407 |     ASSERT_EQ(mkdir_result, 0); | 
 | 408 |  | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 409 |     std::string error_msg; | 
 | 410 |     java_lang_dex_file_ = DexFile::Open(GetLibCoreDexFileName().c_str(), | 
 | 411 |                                         GetLibCoreDexFileName().c_str(), &error_msg); | 
| Ian Rogers | 33e9566 | 2013-05-20 20:29:14 -0700 | [diff] [blame] | 412 |     if (java_lang_dex_file_ == NULL) { | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 413 |       LOG(FATAL) << "Could not open .dex file '" << GetLibCoreDexFileName() << "': " | 
 | 414 |           << error_msg << "\n"; | 
| Ian Rogers | 33e9566 | 2013-05-20 20:29:14 -0700 | [diff] [blame] | 415 |     } | 
| Brian Carlstrom | a004aa9 | 2012-02-08 18:05:09 -0800 | [diff] [blame] | 416 |     boot_class_path_.push_back(java_lang_dex_file_); | 
| Brian Carlstrom | 578bbdc | 2011-07-21 14:07:47 -0700 | [diff] [blame] | 417 |  | 
| Ian Rogers | 1d54e73 | 2013-05-02 21:10:01 -0700 | [diff] [blame] | 418 |     std::string min_heap_string(StringPrintf("-Xms%zdm", gc::Heap::kDefaultInitialSize / MB)); | 
 | 419 |     std::string max_heap_string(StringPrintf("-Xmx%zdm", gc::Heap::kDefaultMaximumSize / MB)); | 
| Ian Rogers | 30fab40 | 2012-01-23 15:43:46 -0800 | [diff] [blame] | 420 |  | 
| Vladimir Marko | 95a4de7 | 2013-12-18 10:29:11 +0000 | [diff] [blame] | 421 |     // TODO: make selectable | 
 | 422 | #if defined(ART_USE_PORTABLE_COMPILER) | 
 | 423 |     CompilerBackend compiler_backend = kPortable; | 
 | 424 | #else | 
 | 425 |     CompilerBackend compiler_backend = kQuick; | 
 | 426 | #endif | 
 | 427 |  | 
 | 428 |     verified_methods_data_.reset(new VerifiedMethodsData); | 
 | 429 |     method_inliner_map_.reset(compiler_backend == kQuick ? new DexFileToMethodInlinerMap : nullptr); | 
 | 430 |     callbacks_.Reset(verified_methods_data_.get(), method_inliner_map_.get()); | 
| Brian Carlstrom | 69b15fb | 2011-09-03 12:25:21 -0700 | [diff] [blame] | 431 |     Runtime::Options options; | 
| Vladimir Marko | 95a4de7 | 2013-12-18 10:29:11 +0000 | [diff] [blame] | 432 |     options.push_back(std::make_pair("compilercallbacks", static_cast<CompilerCallbacks*>(&callbacks_))); | 
| Brian Carlstrom | a004aa9 | 2012-02-08 18:05:09 -0800 | [diff] [blame] | 433 |     options.push_back(std::make_pair("bootclasspath", &boot_class_path_)); | 
| Brian Carlstrom | 69b15fb | 2011-09-03 12:25:21 -0700 | [diff] [blame] | 434 |     options.push_back(std::make_pair("-Xcheck:jni", reinterpret_cast<void*>(NULL))); | 
| Ian Rogers | 30fab40 | 2012-01-23 15:43:46 -0800 | [diff] [blame] | 435 |     options.push_back(std::make_pair(min_heap_string.c_str(), reinterpret_cast<void*>(NULL))); | 
 | 436 |     options.push_back(std::make_pair(max_heap_string.c_str(), reinterpret_cast<void*>(NULL))); | 
| Brian Carlstrom | df62950 | 2013-07-17 22:39:56 -0700 | [diff] [blame] | 437 |     if (!Runtime::Create(options, false)) { | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 438 |       LOG(FATAL) << "Failed to create runtime"; | 
 | 439 |       return; | 
 | 440 |     } | 
 | 441 |     runtime_.reset(Runtime::Current()); | 
 | 442 |     // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start, | 
 | 443 |     // give it away now and then switch to a more managable ScopedObjectAccess. | 
 | 444 |     Thread::Current()->TransitionFromRunnableToSuspended(kNative); | 
| Ian Rogers | 1d54e73 | 2013-05-02 21:10:01 -0700 | [diff] [blame] | 445 |     { | 
 | 446 |       ScopedObjectAccess soa(Thread::Current()); | 
 | 447 |       ASSERT_TRUE(runtime_.get() != NULL); | 
 | 448 |       class_linker_ = runtime_->GetClassLinker(); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 449 |  | 
| Ian Rogers | 1d54e73 | 2013-05-02 21:10:01 -0700 | [diff] [blame] | 450 |       InstructionSet instruction_set = kNone; | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 451 |  | 
| Brian Carlstrom | 1bd2ceb | 2013-11-06 00:29:48 -0800 | [diff] [blame] | 452 |       // Take the default set of instruction features from the build. | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 453 |       InstructionSetFeatures instruction_set_features = | 
| Brian Carlstrom | 1bd2ceb | 2013-11-06 00:29:48 -0800 | [diff] [blame] | 454 |           ParseFeatureList(STRINGIFY(ART_DEFAULT_INSTRUCTION_SET_FEATURES)); | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 455 |  | 
| jeffhao | c0228b8 | 2012-08-29 18:15:05 -0700 | [diff] [blame] | 456 | #if defined(__arm__) | 
| Ian Rogers | 1d54e73 | 2013-05-02 21:10:01 -0700 | [diff] [blame] | 457 |       instruction_set = kThumb2; | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 458 |       InstructionSetFeatures runtime_features = GuessInstructionFeatures(); | 
 | 459 |  | 
 | 460 |       // for ARM, do a runtime check to make sure that the features we are passed from | 
 | 461 |       // the build match the features we actually determine at runtime. | 
 | 462 |       ASSERT_EQ(instruction_set_features, runtime_features); | 
| jeffhao | c0228b8 | 2012-08-29 18:15:05 -0700 | [diff] [blame] | 463 | #elif defined(__mips__) | 
| Ian Rogers | 1d54e73 | 2013-05-02 21:10:01 -0700 | [diff] [blame] | 464 |       instruction_set = kMips; | 
| jeffhao | c0228b8 | 2012-08-29 18:15:05 -0700 | [diff] [blame] | 465 | #elif defined(__i386__) | 
| Ian Rogers | 1d54e73 | 2013-05-02 21:10:01 -0700 | [diff] [blame] | 466 |       instruction_set = kX86; | 
| Ian Rogers | 2c8f653 | 2011-09-02 17:16:34 -0700 | [diff] [blame] | 467 | #endif | 
| buzbee | c531cef | 2012-10-18 07:09:20 -0700 | [diff] [blame] | 468 |  | 
| Ian Rogers | 1d54e73 | 2013-05-02 21:10:01 -0700 | [diff] [blame] | 469 |       for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { | 
 | 470 |         Runtime::CalleeSaveType type = Runtime::CalleeSaveType(i); | 
 | 471 |         if (!runtime_->HasCalleeSaveMethod(type)) { | 
 | 472 |           runtime_->SetCalleeSaveMethod( | 
 | 473 |               runtime_->CreateCalleeSaveMethod(instruction_set, type), type); | 
 | 474 |         } | 
 | 475 |       } | 
 | 476 |       class_linker_->FixupDexCaches(runtime_->GetResolutionMethod()); | 
| Sebastien Hertz | 102a8f2 | 2013-12-18 11:41:30 +0100 | [diff] [blame] | 477 |       compiler_driver_.reset(new CompilerDriver(verified_methods_data_.get(), | 
 | 478 |                                                 method_inliner_map_.get(), | 
 | 479 |                                                 compiler_backend, instruction_set, | 
| Dave Allison | 7020278 | 2013-10-22 17:52:19 -0700 | [diff] [blame] | 480 |                                                 instruction_set_features, | 
| Ian Rogers | 1d54e73 | 2013-05-02 21:10:01 -0700 | [diff] [blame] | 481 |                                                 true, new CompilerDriver::DescriptorSet, | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 482 |                                                 2, true)); | 
| Ian Rogers | 4f0d07c | 2011-10-06 23:38:47 -0700 | [diff] [blame] | 483 |     } | 
| Brian Carlstrom | 9639160 | 2013-06-13 19:49:50 -0700 | [diff] [blame] | 484 |     // We typically don't generate an image in unit tests, disable this optimization by default. | 
 | 485 |     compiler_driver_->SetSupportBootImageFixup(false); | 
| Ian Rogers | 2c8f653 | 2011-09-02 17:16:34 -0700 | [diff] [blame] | 486 |  | 
| Ian Rogers | 1d54e73 | 2013-05-02 21:10:01 -0700 | [diff] [blame] | 487 |     // We're back in native, take the opportunity to initialize well known classes. | 
| Brian Carlstrom | ea46f95 | 2013-07-30 01:26:50 -0700 | [diff] [blame] | 488 |     WellKnownClasses::Init(Thread::Current()->GetJniEnv()); | 
| Mathieu Chartier | 02b6a78 | 2012-10-26 13:51:26 -0700 | [diff] [blame] | 489 |     // Create the heap thread pool so that the GC runs in parallel for tests. Normally, the thread | 
 | 490 |     // pool is created by the runtime. | 
 | 491 |     runtime_->GetHeap()->CreateThreadPool(); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 492 |     runtime_->GetHeap()->VerifyHeap();  // Check for heap corruption before the test | 
| Brian Carlstrom | 578bbdc | 2011-07-21 14:07:47 -0700 | [diff] [blame] | 493 |   } | 
 | 494 |  | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 495 |   virtual void TearDown() { | 
 | 496 |     const char* android_data = getenv("ANDROID_DATA"); | 
 | 497 |     ASSERT_TRUE(android_data != NULL); | 
| Brian Carlstrom | 7675e16 | 2013-06-10 16:18:04 -0700 | [diff] [blame] | 498 |     DIR* dir = opendir(dalvik_cache_.c_str()); | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 499 |     ASSERT_TRUE(dir != NULL); | 
| Elliott Hughes | 4696b5b | 2012-10-30 10:35:10 -0700 | [diff] [blame] | 500 |     dirent* e; | 
 | 501 |     while ((e = readdir(dir)) != NULL) { | 
 | 502 |       if ((strcmp(e->d_name, ".") == 0) || (strcmp(e->d_name, "..") == 0)) { | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 503 |         continue; | 
 | 504 |       } | 
| Brian Carlstrom | 7675e16 | 2013-06-10 16:18:04 -0700 | [diff] [blame] | 505 |       std::string filename(dalvik_cache_); | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 506 |       filename.push_back('/'); | 
| Elliott Hughes | 4696b5b | 2012-10-30 10:35:10 -0700 | [diff] [blame] | 507 |       filename.append(e->d_name); | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 508 |       int unlink_result = unlink(filename.c_str()); | 
 | 509 |       ASSERT_EQ(0, unlink_result); | 
| Jesse Wilson | ac5b9e2 | 2011-07-27 15:11:13 -0400 | [diff] [blame] | 510 |     } | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 511 |     closedir(dir); | 
| Brian Carlstrom | 7675e16 | 2013-06-10 16:18:04 -0700 | [diff] [blame] | 512 |     int rmdir_cache_result = rmdir(dalvik_cache_.c_str()); | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 513 |     ASSERT_EQ(0, rmdir_cache_result); | 
| Elliott Hughes | 3402380 | 2011-08-30 12:06:17 -0700 | [diff] [blame] | 514 |     int rmdir_data_result = rmdir(android_data_.c_str()); | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 515 |     ASSERT_EQ(0, rmdir_data_result); | 
| Elliott Hughes | 0af5543 | 2011-08-17 18:37:28 -0700 | [diff] [blame] | 516 |  | 
 | 517 |     // icu4c has a fixed 10-element array "gCommonICUDataArray". | 
 | 518 |     // If we run > 10 tests, we fill that array and u_setCommonData fails. | 
 | 519 |     // There's a function to clear the array, but it's not public... | 
 | 520 |     typedef void (*IcuCleanupFn)(); | 
 | 521 |     void* sym = dlsym(RTLD_DEFAULT, "u_cleanup_" U_ICU_VERSION_SHORT); | 
 | 522 |     CHECK(sym != NULL); | 
 | 523 |     IcuCleanupFn icu_cleanup_fn = reinterpret_cast<IcuCleanupFn>(sym); | 
 | 524 |     (*icu_cleanup_fn)(); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 525 |  | 
| Ian Rogers | 1212a02 | 2013-03-04 10:48:41 -0800 | [diff] [blame] | 526 |     compiler_driver_.reset(); | 
| Vladimir Marko | 95a4de7 | 2013-12-18 10:29:11 +0000 | [diff] [blame] | 527 |     callbacks_.Reset(nullptr, nullptr); | 
 | 528 |     method_inliner_map_.reset(); | 
 | 529 |     verified_methods_data_.reset(); | 
| Elliott Hughes | 4d6850c | 2012-01-18 15:55:06 -0800 | [diff] [blame] | 530 |     STLDeleteElements(&opened_dex_files_); | 
| Ian Rogers | 2c8f653 | 2011-09-02 17:16:34 -0700 | [diff] [blame] | 531 |  | 
| Elliott Hughes | b3bd5f0 | 2012-03-08 21:05:27 -0800 | [diff] [blame] | 532 |     Runtime::Current()->GetHeap()->VerifyHeap();  // Check for heap corruption after the test | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 533 |   } | 
| Jesse Wilson | ac5b9e2 | 2011-07-27 15:11:13 -0400 | [diff] [blame] | 534 |  | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 535 |   std::string GetLibCoreDexFileName() { | 
| Brian Carlstrom | 3b010aa | 2013-06-25 23:06:36 -0700 | [diff] [blame] | 536 |     return GetDexFileName("core-libart"); | 
| Brian Carlstrom | 265091e | 2013-01-30 14:08:26 -0800 | [diff] [blame] | 537 |   } | 
 | 538 |  | 
 | 539 |   std::string GetDexFileName(const std::string& jar_prefix) { | 
| Elliott Hughes | 7616005 | 2012-12-12 16:31:20 -0800 | [diff] [blame] | 540 |     if (IsHost()) { | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 541 |       const char* host_dir = getenv("ANDROID_HOST_OUT"); | 
 | 542 |       CHECK(host_dir != NULL); | 
| Brian Carlstrom | 265091e | 2013-01-30 14:08:26 -0800 | [diff] [blame] | 543 |       return StringPrintf("%s/framework/%s-hostdex.jar", host_dir, jar_prefix.c_str()); | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 544 |     } | 
| Brian Carlstrom | 265091e | 2013-01-30 14:08:26 -0800 | [diff] [blame] | 545 |     return StringPrintf("%s/framework/%s.jar", GetAndroidRoot(), jar_prefix.c_str()); | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 546 |   } | 
 | 547 |  | 
| Brian Carlstrom | 3f47c12 | 2013-03-07 00:02:40 -0800 | [diff] [blame] | 548 |   std::string GetTestAndroidRoot() { | 
 | 549 |     if (IsHost()) { | 
 | 550 |       const char* host_dir = getenv("ANDROID_HOST_OUT"); | 
 | 551 |       CHECK(host_dir != NULL); | 
 | 552 |       return host_dir; | 
 | 553 |     } | 
 | 554 |     return GetAndroidRoot(); | 
 | 555 |   } | 
 | 556 |  | 
| Ian Rogers | 33e9566 | 2013-05-20 20:29:14 -0700 | [diff] [blame] | 557 |   const DexFile* OpenTestDexFile(const char* name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
| Brian Carlstrom | 9f30b38 | 2011-08-28 22:41:38 -0700 | [diff] [blame] | 558 |     CHECK(name != NULL); | 
 | 559 |     std::string filename; | 
| Elliott Hughes | 7616005 | 2012-12-12 16:31:20 -0800 | [diff] [blame] | 560 |     if (IsHost()) { | 
| Brian Carlstrom | b279337 | 2012-03-17 18:27:16 -0700 | [diff] [blame] | 561 |       filename += getenv("ANDROID_HOST_OUT"); | 
 | 562 |       filename += "/framework/"; | 
 | 563 |     } else { | 
 | 564 |       filename += "/data/nativetest/art/"; | 
| Brian Carlstrom | 9f30b38 | 2011-08-28 22:41:38 -0700 | [diff] [blame] | 565 |     } | 
| Brian Carlstrom | b279337 | 2012-03-17 18:27:16 -0700 | [diff] [blame] | 566 |     filename += "art-test-dex-"; | 
| Brian Carlstrom | 9f30b38 | 2011-08-28 22:41:38 -0700 | [diff] [blame] | 567 |     filename += name; | 
 | 568 |     filename += ".jar"; | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 569 |     std::string error_msg; | 
 | 570 |     const DexFile* dex_file = DexFile::Open(filename.c_str(), filename.c_str(), &error_msg); | 
 | 571 |     CHECK(dex_file != NULL) << "Failed to open '" << filename << "': " << error_msg; | 
| Brian Carlstrom | e0948e1 | 2013-08-29 09:36:15 -0700 | [diff] [blame] | 572 |     CHECK_EQ(PROT_READ, dex_file->GetPermissions()); | 
 | 573 |     CHECK(dex_file->IsReadOnly()); | 
| Elliott Hughes | 4d6850c | 2012-01-18 15:55:06 -0800 | [diff] [blame] | 574 |     opened_dex_files_.push_back(dex_file); | 
| Brian Carlstrom | 9f30b38 | 2011-08-28 22:41:38 -0700 | [diff] [blame] | 575 |     return dex_file; | 
 | 576 |   } | 
 | 577 |  | 
| Ian Rogers | 33e9566 | 2013-05-20 20:29:14 -0700 | [diff] [blame] | 578 |   jobject LoadDex(const char* dex_name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
| Brian Carlstrom | 9baa4ae | 2011-09-01 21:14:14 -0700 | [diff] [blame] | 579 |     const DexFile* dex_file = OpenTestDexFile(dex_name); | 
 | 580 |     CHECK(dex_file != NULL); | 
| Brian Carlstrom | 9baa4ae | 2011-09-01 21:14:14 -0700 | [diff] [blame] | 581 |     class_linker_->RegisterDexFile(*dex_file); | 
 | 582 |     std::vector<const DexFile*> class_path; | 
 | 583 |     class_path.push_back(dex_file); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 584 |     ScopedObjectAccessUnchecked soa(Thread::Current()); | 
 | 585 |     ScopedLocalRef<jobject> class_loader_local(soa.Env(), | 
 | 586 |         soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader)); | 
 | 587 |     jobject class_loader = soa.Env()->NewGlobalRef(class_loader_local.get()); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 588 |     soa.Self()->SetClassLoaderOverride(soa.Decode<mirror::ClassLoader*>(class_loader_local.get())); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 589 |     Runtime::Current()->SetCompileTimeClassPath(class_loader, class_path); | 
 | 590 |     return class_loader; | 
| Brian Carlstrom | 9baa4ae | 2011-09-01 21:14:14 -0700 | [diff] [blame] | 591 |   } | 
 | 592 |  | 
| Ian Rogers | 33e9566 | 2013-05-20 20:29:14 -0700 | [diff] [blame] | 593 |   void CompileClass(mirror::ClassLoader* class_loader, const char* class_name) | 
 | 594 |       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
| Elliott Hughes | 9557241 | 2011-12-13 18:14:20 -0800 | [diff] [blame] | 595 |     std::string class_descriptor(DotToDescriptor(class_name)); | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 596 |     SirtRef<mirror::ClassLoader> loader(Thread::Current(), class_loader); | 
 | 597 |     mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), loader); | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 598 |     CHECK(klass != NULL) << "Class not found " << class_name; | 
 | 599 |     for (size_t i = 0; i < klass->NumDirectMethods(); i++) { | 
 | 600 |       CompileMethod(klass->GetDirectMethod(i)); | 
 | 601 |     } | 
 | 602 |     for (size_t i = 0; i < klass->NumVirtualMethods(); i++) { | 
 | 603 |       CompileMethod(klass->GetVirtualMethod(i)); | 
 | 604 |     } | 
 | 605 |   } | 
 | 606 |  | 
| Brian Carlstrom | ea46f95 | 2013-07-30 01:26:50 -0700 | [diff] [blame] | 607 |   void CompileMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
| Brian Carlstrom | 9baa4ae | 2011-09-01 21:14:14 -0700 | [diff] [blame] | 608 |     CHECK(method != NULL); | 
| Ian Rogers | 5fe9af7 | 2013-11-14 00:17:20 -0800 | [diff] [blame] | 609 |     TimingLogger timings("CommonTest::CompileMethod", false, false); | 
| Anwar Ghuloum | be576f4 | 2013-07-25 17:32:40 -0700 | [diff] [blame] | 610 |     timings.StartSplit("CompileOne"); | 
| Brian Carlstrom | 4560248 | 2013-07-21 22:07:55 -0700 | [diff] [blame] | 611 |     compiler_driver_->CompileOne(method, timings); | 
| Brian Carlstrom | 3320cf4 | 2011-10-04 14:58:28 -0700 | [diff] [blame] | 612 |     MakeExecutable(method); | 
| Ian Rogers | 5fe9af7 | 2013-11-14 00:17:20 -0800 | [diff] [blame] | 613 |     timings.EndSplit(); | 
| Brian Carlstrom | 9baa4ae | 2011-09-01 21:14:14 -0700 | [diff] [blame] | 614 |   } | 
 | 615 |  | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 616 |   void CompileDirectMethod(SirtRef<mirror::ClassLoader>& class_loader, const char* class_name, | 
 | 617 |                            const char* method_name, const char* signature) | 
| Ian Rogers | b726dcb | 2012-09-05 08:57:23 -0700 | [diff] [blame] | 618 |       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
| Elliott Hughes | 9557241 | 2011-12-13 18:14:20 -0800 | [diff] [blame] | 619 |     std::string class_descriptor(DotToDescriptor(class_name)); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 620 |     mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader); | 
| Brian Carlstrom | 9baa4ae | 2011-09-01 21:14:14 -0700 | [diff] [blame] | 621 |     CHECK(klass != NULL) << "Class not found " << class_name; | 
| Brian Carlstrom | ea46f95 | 2013-07-30 01:26:50 -0700 | [diff] [blame] | 622 |     mirror::ArtMethod* method = klass->FindDirectMethod(method_name, signature); | 
| Elliott Hughes | 0f4c41d | 2011-09-04 14:58:03 -0700 | [diff] [blame] | 623 |     CHECK(method != NULL) << "Direct method not found: " | 
 | 624 |                           << class_name << "." << method_name << signature; | 
| Brian Carlstrom | 9baa4ae | 2011-09-01 21:14:14 -0700 | [diff] [blame] | 625 |     CompileMethod(method); | 
 | 626 |   } | 
 | 627 |  | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 628 |   void CompileVirtualMethod(SirtRef<mirror::ClassLoader>& class_loader, const char* class_name, | 
 | 629 |                             const char* method_name, const char* signature) | 
| Ian Rogers | b726dcb | 2012-09-05 08:57:23 -0700 | [diff] [blame] | 630 |       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
| Elliott Hughes | 9557241 | 2011-12-13 18:14:20 -0800 | [diff] [blame] | 631 |     std::string class_descriptor(DotToDescriptor(class_name)); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 632 |     mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader); | 
| Brian Carlstrom | 9baa4ae | 2011-09-01 21:14:14 -0700 | [diff] [blame] | 633 |     CHECK(klass != NULL) << "Class not found " << class_name; | 
| Brian Carlstrom | ea46f95 | 2013-07-30 01:26:50 -0700 | [diff] [blame] | 634 |     mirror::ArtMethod* method = klass->FindVirtualMethod(method_name, signature); | 
| Elliott Hughes | 0f4c41d | 2011-09-04 14:58:03 -0700 | [diff] [blame] | 635 |     CHECK(method != NULL) << "Virtual method not found: " | 
 | 636 |                           << class_name << "." << method_name << signature; | 
| Brian Carlstrom | 9baa4ae | 2011-09-01 21:14:14 -0700 | [diff] [blame] | 637 |     CompileMethod(method); | 
 | 638 |   } | 
 | 639 |  | 
| Brian Carlstrom | 700c8d3 | 2012-11-05 10:42:02 -0800 | [diff] [blame] | 640 |   void ReserveImageSpace() { | 
 | 641 |     // Reserve where the image will be loaded up front so that other parts of test set up don't | 
 | 642 |     // accidentally end up colliding with the fixed memory address when we need to load the image. | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 643 |     std::string error_msg; | 
| Brian Carlstrom | 2d88862 | 2013-07-18 17:02:00 -0700 | [diff] [blame] | 644 |     image_reservation_.reset(MemMap::MapAnonymous("image reservation", | 
 | 645 |                                                   reinterpret_cast<byte*>(ART_BASE_ADDRESS), | 
| Brian Carlstrom | 700c8d3 | 2012-11-05 10:42:02 -0800 | [diff] [blame] | 646 |                                                   (size_t)100 * 1024 * 1024,  // 100MB | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 647 |                                                   PROT_NONE, &error_msg)); | 
 | 648 |     CHECK(image_reservation_.get() != nullptr) << error_msg; | 
| Brian Carlstrom | 700c8d3 | 2012-11-05 10:42:02 -0800 | [diff] [blame] | 649 |   } | 
 | 650 |  | 
 | 651 |   void UnreserveImageSpace() { | 
 | 652 |     image_reservation_.reset(); | 
 | 653 |   } | 
 | 654 |  | 
| Vladimir Marko | 95a4de7 | 2013-12-18 10:29:11 +0000 | [diff] [blame] | 655 |   class TestCompilerCallbacks : public CompilerCallbacks { | 
 | 656 |    public: | 
 | 657 |     TestCompilerCallbacks() : verified_methods_data_(nullptr), method_inliner_map_(nullptr) { } | 
 | 658 |  | 
 | 659 |     void Reset(VerifiedMethodsData* verified_methods_data, | 
 | 660 |                DexFileToMethodInlinerMap* method_inliner_map) { | 
 | 661 |         verified_methods_data_ = verified_methods_data; | 
 | 662 |         method_inliner_map_ = method_inliner_map; | 
 | 663 |     } | 
 | 664 |  | 
 | 665 |     virtual bool MethodVerified(verifier::MethodVerifier* verifier) | 
 | 666 |         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
 | 667 |       CHECK(verified_methods_data_); | 
 | 668 |       bool result = verified_methods_data_->ProcessVerifiedMethod(verifier); | 
 | 669 |       if (result && method_inliner_map_ != nullptr) { | 
 | 670 |         MethodReference ref = verifier->GetMethodReference(); | 
 | 671 |         method_inliner_map_->GetMethodInliner(ref.dex_file) | 
 | 672 |             ->AnalyseMethodCode(ref.dex_method_index, verifier->CodeItem()); | 
 | 673 |       } | 
 | 674 |       return result; | 
 | 675 |     } | 
 | 676 |     virtual void ClassRejected(ClassReference ref) { | 
 | 677 |       verified_methods_data_->AddRejectedClass(ref); | 
 | 678 |     } | 
 | 679 |  | 
 | 680 |    private: | 
 | 681 |     VerifiedMethodsData* verified_methods_data_; | 
 | 682 |     DexFileToMethodInlinerMap* method_inliner_map_; | 
 | 683 |   }; | 
 | 684 |  | 
| Elliott Hughes | 3402380 | 2011-08-30 12:06:17 -0700 | [diff] [blame] | 685 |   std::string android_data_; | 
| Brian Carlstrom | 7675e16 | 2013-06-10 16:18:04 -0700 | [diff] [blame] | 686 |   std::string dalvik_cache_; | 
| Brian Carlstrom | a004aa9 | 2012-02-08 18:05:09 -0800 | [diff] [blame] | 687 |   const DexFile* java_lang_dex_file_;  // owned by runtime_ | 
| Brian Carlstrom | 9ea1cb1 | 2011-08-24 23:18:18 -0700 | [diff] [blame] | 688 |   std::vector<const DexFile*> boot_class_path_; | 
| Elliott Hughes | 90a3369 | 2011-08-30 13:27:07 -0700 | [diff] [blame] | 689 |   UniquePtr<Runtime> runtime_; | 
| Ian Rogers | 0e073f7 | 2011-09-09 10:45:46 -0700 | [diff] [blame] | 690 |   // Owned by the runtime | 
| Carl Shapiro | 7a90959 | 2011-07-24 19:21:59 -0700 | [diff] [blame] | 691 |   ClassLinker* class_linker_; | 
| Sebastien Hertz | 102a8f2 | 2013-12-18 11:41:30 +0100 | [diff] [blame] | 692 |   UniquePtr<VerifiedMethodsData> verified_methods_data_; | 
 | 693 |   UniquePtr<DexFileToMethodInlinerMap> method_inliner_map_; | 
| Vladimir Marko | 95a4de7 | 2013-12-18 10:29:11 +0000 | [diff] [blame] | 694 |   TestCompilerCallbacks callbacks_; | 
| Ian Rogers | 1212a02 | 2013-03-04 10:48:41 -0800 | [diff] [blame] | 695 |   UniquePtr<CompilerDriver> compiler_driver_; | 
| Brian Carlstrom | 9baa4ae | 2011-09-01 21:14:14 -0700 | [diff] [blame] | 696 |  | 
 | 697 |  private: | 
| Elliott Hughes | 4d6850c | 2012-01-18 15:55:06 -0800 | [diff] [blame] | 698 |   std::vector<const DexFile*> opened_dex_files_; | 
| Brian Carlstrom | 700c8d3 | 2012-11-05 10:42:02 -0800 | [diff] [blame] | 699 |   UniquePtr<MemMap> image_reservation_; | 
| Brian Carlstrom | 578bbdc | 2011-07-21 14:07:47 -0700 | [diff] [blame] | 700 | }; | 
 | 701 |  | 
| Elliott Hughes | b264f08 | 2012-04-06 17:10:10 -0700 | [diff] [blame] | 702 | // Sets a CheckJni abort hook to catch failures. Note that this will cause CheckJNI to carry on | 
 | 703 | // rather than aborting, so be careful! | 
 | 704 | class CheckJniAbortCatcher { | 
 | 705 |  public: | 
 | 706 |   CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) { | 
 | 707 |     vm_->check_jni_abort_hook = Hook; | 
 | 708 |     vm_->check_jni_abort_hook_data = &actual_; | 
 | 709 |   } | 
 | 710 |  | 
 | 711 |   ~CheckJniAbortCatcher() { | 
 | 712 |     vm_->check_jni_abort_hook = NULL; | 
 | 713 |     vm_->check_jni_abort_hook_data = NULL; | 
| Elliott Hughes | 56ef042 | 2012-06-19 14:35:04 -0700 | [diff] [blame] | 714 |     EXPECT_TRUE(actual_.empty()) << actual_; | 
| Elliott Hughes | b264f08 | 2012-04-06 17:10:10 -0700 | [diff] [blame] | 715 |   } | 
 | 716 |  | 
 | 717 |   void Check(const char* expected_text) { | 
 | 718 |     EXPECT_TRUE(actual_.find(expected_text) != std::string::npos) << "\n" | 
 | 719 |         << "Expected to find: " << expected_text << "\n" | 
 | 720 |         << "In the output   : " << actual_; | 
| Elliott Hughes | 3f6635a | 2012-06-19 13:37:49 -0700 | [diff] [blame] | 721 |     actual_.clear(); | 
| Elliott Hughes | b264f08 | 2012-04-06 17:10:10 -0700 | [diff] [blame] | 722 |   } | 
 | 723 |  | 
 | 724 |  private: | 
 | 725 |   static void Hook(void* data, const std::string& reason) { | 
| Elliott Hughes | 3f6635a | 2012-06-19 13:37:49 -0700 | [diff] [blame] | 726 |     // We use += because when we're hooking the aborts like this, multiple problems can be found. | 
 | 727 |     *reinterpret_cast<std::string*>(data) += reason; | 
| Elliott Hughes | b264f08 | 2012-04-06 17:10:10 -0700 | [diff] [blame] | 728 |   } | 
 | 729 |  | 
 | 730 |   JavaVMExt* vm_; | 
 | 731 |   std::string actual_; | 
 | 732 |  | 
 | 733 |   DISALLOW_COPY_AND_ASSIGN(CheckJniAbortCatcher); | 
 | 734 | }; | 
 | 735 |  | 
| Brian Carlstrom | 265091e | 2013-01-30 14:08:26 -0800 | [diff] [blame] | 736 | // TODO: These tests were disabled for portable when we went to having | 
 | 737 | // MCLinker link LLVM ELF output because we no longer just have code | 
 | 738 | // blobs in memory. We'll need to dlopen to load and relocate | 
 | 739 | // temporary output to resurrect these tests. | 
 | 740 | #if defined(ART_USE_PORTABLE_COMPILER) | 
 | 741 | #define TEST_DISABLED_FOR_PORTABLE() printf("WARNING: TEST DISABLED FOR PORTABLE\n"); return | 
 | 742 | #else | 
 | 743 | #define TEST_DISABLED_FOR_PORTABLE() | 
 | 744 | #endif | 
| Brian Carlstrom | 934486c | 2011-07-12 23:42:50 -0700 | [diff] [blame] | 745 | }  // namespace art | 
| Elliott Hughes | 3402380 | 2011-08-30 12:06:17 -0700 | [diff] [blame] | 746 |  | 
 | 747 | namespace std { | 
 | 748 |  | 
 | 749 | // TODO: isn't gtest supposed to be able to print STL types for itself? | 
 | 750 | template <typename T> | 
 | 751 | std::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs) { | 
| Elliott Hughes | 14134a1 | 2011-09-30 16:55:51 -0700 | [diff] [blame] | 752 |   os << ::art::ToString(rhs); | 
| Elliott Hughes | 3402380 | 2011-08-30 12:06:17 -0700 | [diff] [blame] | 753 |   return os; | 
 | 754 | } | 
 | 755 |  | 
 | 756 | }  // namespace std | 
| Brian Carlstrom | fc0e321 | 2013-07-17 14:40:12 -0700 | [diff] [blame] | 757 |  | 
 | 758 | #endif  // ART_RUNTIME_COMMON_TEST_H_ |