blob: 57cf71a50b7e1ac945eabb822955c31c75eecfa0 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
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 Carlstrom934486c2011-07-12 23:42:50 -070016
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_RUNTIME_COMMON_TEST_H_
18#define ART_RUNTIME_COMMON_TEST_H_
19
Brian Carlstromb0460ea2011-07-29 10:08:05 -070020#include <dirent.h>
Elliott Hughes0af55432011-08-17 18:37:28 -070021#include <dlfcn.h>
Brian Carlstrom27ec9612011-09-19 20:20:38 -070022#include <sys/mman.h>
Brian Carlstromb0460ea2011-07-29 10:08:05 -070023#include <sys/stat.h>
24#include <sys/types.h>
Dave Allison70202782013-10-22 17:52:19 -070025#include <fstream>
Brian Carlstromb0460ea2011-07-29 10:08:05 -070026
Elliott Hughesf66330a2012-12-12 17:27:00 -080027#include "../../external/icu4c/common/unicode/uvernum.h"
Elliott Hughes76160052012-12-12 16:31:20 -080028#include "base/macros.h"
Elliott Hughes1aa246d2012-12-13 09:29:36 -080029#include "base/stl_util.h"
Elliott Hughese222ee02012-12-13 14:41:43 -080030#include "base/stringprintf.h"
Elliott Hughes76160052012-12-12 16:31:20 -080031#include "base/unix_file/fd_file.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070032#include "class_linker.h"
Ian Rogers1212a022013-03-04 10:48:41 -080033#include "compiler/driver/compiler_driver.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070034#include "dex_file-inl.h"
Ian Rogers7655f292013-07-29 11:07:13 -070035#include "entrypoints/entrypoint_utils.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070036#include "gc/heap.h"
Elliott Hughes90a33692011-08-30 13:27:07 -070037#include "gtest/gtest.h"
Elliott Hughes0f3c5532012-03-30 14:51:51 -070038#include "instruction_set.h"
Ian Rogers0f40ac32013-08-13 22:10:30 -070039#include "interpreter/interpreter.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080040#include "mirror/class_loader.h"
Brian Carlstrom3320cf42011-10-04 14:58:28 -070041#include "oat_file.h"
Ian Rogers6d4d9fc2011-11-30 16:24:48 -080042#include "object_utils.h"
Brian Carlstrom33f741e2011-10-03 11:24:05 -070043#include "os.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070044#include "runtime.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070045#include "scoped_thread_state_change.h"
Elliott Hughese222ee02012-12-13 14:41:43 -080046#include "ScopedLocalRef.h"
Elliott Hughes90a33692011-08-30 13:27:07 -070047#include "thread.h"
Elliott Hughes0f3c5532012-03-30 14:51:51 -070048#include "UniquePtr.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070049#include "well_known_classes.h"
Elliott Hughes0af55432011-08-17 18:37:28 -070050
Brian Carlstrom934486c2011-07-12 23:42:50 -070051namespace art {
52
Brian Carlstromb9cc1ca2012-01-27 00:57:42 -080053static const byte kBase64Map[256] = {
54 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
55 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
56 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
57 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
58 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
59 255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
Brian Carlstrom7934ac22013-07-26 10:54:15 -070060 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // NOLINT
61 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, // NOLINT
Brian Carlstromb9cc1ca2012-01-27 00:57:42 -080062 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
Brian Carlstrom7934ac22013-07-26 10:54:15 -070063 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // NOLINT
64 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, // NOLINT
Brian Carlstromb9cc1ca2012-01-27 00:57:42 -080065 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
66 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
67 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
68 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
69 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
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
76};
77
78byte* DecodeBase64(const char* src, size_t* dst_size) {
79 std::vector<byte> tmp;
Elliott Hughesa21039c2012-06-21 12:09:25 -070080 uint32_t t = 0, y = 0;
Brian Carlstromb9cc1ca2012-01-27 00:57:42 -080081 int g = 3;
82 for (size_t i = 0; src[i] != '\0'; ++i) {
83 byte c = kBase64Map[src[i] & 0xFF];
84 if (c == 255) continue;
85 // the final = symbols are read and used to trim the remaining bytes
86 if (c == 254) {
87 c = 0;
88 // prevent g < 0 which would potentially allow an overflow later
89 if (--g < 0) {
Brian Carlstrom51477332012-03-25 20:20:26 -070090 *dst_size = 0;
Brian Carlstromb9cc1ca2012-01-27 00:57:42 -080091 return NULL;
92 }
93 } else if (g != 3) {
94 // we only allow = to be at the end
Brian Carlstrom51477332012-03-25 20:20:26 -070095 *dst_size = 0;
Brian Carlstromb9cc1ca2012-01-27 00:57:42 -080096 return NULL;
97 }
98 t = (t << 6) | c;
99 if (++y == 4) {
100 tmp.push_back((t >> 16) & 255);
101 if (g > 1) {
102 tmp.push_back((t >> 8) & 255);
103 }
104 if (g > 2) {
105 tmp.push_back(t & 255);
106 }
107 y = t = 0;
108 }
109 }
110 if (y != 0) {
Brian Carlstrom51477332012-03-25 20:20:26 -0700111 *dst_size = 0;
Brian Carlstromb9cc1ca2012-01-27 00:57:42 -0800112 return NULL;
113 }
114 UniquePtr<byte[]> dst(new byte[tmp.size()]);
115 if (dst_size != NULL) {
116 *dst_size = tmp.size();
Brian Carlstrom51477332012-03-25 20:20:26 -0700117 } else {
118 *dst_size = 0;
Brian Carlstromb9cc1ca2012-01-27 00:57:42 -0800119 }
120 std::copy(tmp.begin(), tmp.end(), dst.get());
121 return dst.release();
122}
123
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700124class ScratchFile {
125 public:
126 ScratchFile() {
Elliott Hughes34023802011-08-30 12:06:17 -0700127 filename_ = getenv("ANDROID_DATA");
128 filename_ += "/TmpFile-XXXXXX";
Elliott Hughes76160052012-12-12 16:31:20 -0800129 int fd = mkstemp(&filename_[0]);
130 CHECK_NE(-1, fd);
131 file_.reset(new File(fd, GetFilename()));
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700132 }
133
134 ~ScratchFile() {
Elliott Hughes34023802011-08-30 12:06:17 -0700135 int unlink_result = unlink(filename_.c_str());
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700136 CHECK_EQ(0, unlink_result);
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700137 }
138
Brian Carlstroma004aa92012-02-08 18:05:09 -0800139 const std::string& GetFilename() const {
140 return filename_;
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700141 }
142
Elliott Hughes234da572011-11-03 22:13:06 -0700143 File* GetFile() const {
144 return file_.get();
145 }
146
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700147 int GetFd() const {
Elliott Hughes76160052012-12-12 16:31:20 -0800148 return file_->Fd();
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700149 }
150
151 private:
Elliott Hughes34023802011-08-30 12:06:17 -0700152 std::string filename_;
Elliott Hughes234da572011-11-03 22:13:06 -0700153 UniquePtr<File> file_;
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700154};
155
Dave Allison70202782013-10-22 17:52:19 -0700156#if defined(__arm__)
157
158
159#include <signal.h>
160#include <asm/sigcontext.h>
161#include <asm/ucontext.h>
162
163
164// A signal handler called when have an illegal instruction. We record the fact in
165// a global boolean and then increment the PC in the signal context to return to
166// the next instruction. We know the instruction is an sdiv (4 bytes long).
167static void baddivideinst(int signo, siginfo *si, void *data) {
168 (void)signo;
169 (void)si;
170 struct ucontext *uc = (struct ucontext *)data;
171 struct sigcontext *sc = &uc->uc_mcontext;
172 sc->arm_r0 = 0; // set R0 to #0 to signal error
173 sc->arm_pc += 4; // skip offending instruction
174}
175
176// This is in arch/arm/arm_sdiv.S. It does the following:
177// mov r1,#1
178// sdiv r0,r1,r1
179// bx lr
180//
181// the result will be the value 1 if sdiv is supported. If it is not supported
182// a SIGILL signal will be raised and the signal handler (baddivideinst) called.
183// The signal handler sets r0 to #0 and then increments pc beyond the failed instruction.
184// Thus if the instruction is not supported, the result of this function will be #0
185
186extern "C" bool CheckForARMSDIVInstruction();
187
188static InstructionSetFeatures GuessInstructionFeatures() {
189 InstructionSetFeatures f;
190
191 // Uncomment this for processing of /proc/cpuinfo.
192 if (false) {
193 // Look in /proc/cpuinfo for features we need. Only use this when we can guarantee that
194 // the kernel puts the appropriate feature flags in here. Sometimes it doesn't.
195 std::ifstream in("/proc/cpuinfo");
196 if (in) {
197 while (!in.eof()) {
198 std::string line;
199 std::getline(in, line);
200 if (!in.eof()) {
201 if (line.find("Features") != std::string::npos) {
202 if (line.find("idivt") != std::string::npos) {
203 f.SetHasDivideInstruction(true);
204 }
205 }
206 }
207 in.close();
208 }
209 } else {
210 LOG(INFO) << "Failed to open /proc/cpuinfo";
211 }
212 }
213
214 // See if have a sdiv instruction. Register a signal handler and try to execute
215 // an sdiv instruction. If we get a SIGILL then it's not supported. We can't use
216 // the /proc/cpuinfo method for this because Krait devices don't always put the idivt
217 // feature in the list.
218 struct sigaction sa, osa;
219 sa.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO;
220 sa.sa_sigaction = baddivideinst;
221 sigaction(SIGILL, &sa, &osa);
222
223 if (CheckForARMSDIVInstruction()) {
224 f.SetHasDivideInstruction(true);
225 }
226
227 // Restore the signal handler.
228 sigaction(SIGILL, &osa, NULL);
229
230 // Other feature guesses in here.
231 return f;
232}
233
234#endif
235
236// Given a set of instruction features from the build, parse it. The
237// input 'str' is a comma separated list of feature names. Parse it and
238// return the InstructionSetFeatures object.
239static InstructionSetFeatures ParseFeatureList(std::string str) {
Dave Allison70202782013-10-22 17:52:19 -0700240 InstructionSetFeatures result;
241 typedef std::vector<std::string> FeatureList;
242 FeatureList features;
243 Split(str, ',', features);
244 for (FeatureList::iterator i = features.begin(); i != features.end(); i++) {
245 std::string feature = Trim(*i);
246 if (feature == "default") {
247 // Nothing to do.
248 } else if (feature == "div") {
249 // Supports divide instruction.
250 result.SetHasDivideInstruction(true);
251 } else if (feature == "nodiv") {
252 // Turn off support for divide instruction.
253 result.SetHasDivideInstruction(false);
254 } else {
255 LOG(FATAL) << "Unknown instruction set feature: '" << feature << "'";
256 }
257 }
258 // Others...
259 return result;
260}
261
Brian Carlstromf734cf52011-08-17 16:28:14 -0700262class CommonTest : public testing::Test {
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700263 public:
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800264 static void MakeExecutable(const mirror::ByteArray* code_array) {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700265 CHECK(code_array != NULL);
266 MakeExecutable(code_array->GetData(), code_array->GetLength());
267 }
268
Shih-wei Liao1cb0ae72012-03-16 15:30:19 -0700269 static void MakeExecutable(const std::vector<uint8_t>& code) {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700270 CHECK_NE(code.size(), 0U);
271 MakeExecutable(&code[0], code.size());
272 }
273
Brian Carlstromae826982011-11-09 01:33:42 -0800274 // Create an OatMethod based on pointers (for unit tests)
275 OatFile::OatMethod CreateOatMethod(const void* code,
276 const size_t frame_size_in_bytes,
277 const uint32_t core_spill_mask,
278 const uint32_t fp_spill_mask,
Ian Rogers1809a722013-08-09 22:05:32 -0700279 const uint8_t* mapping_table,
280 const uint8_t* vmap_table,
Jeff Hao74180ca2013-03-27 15:29:11 -0700281 const uint8_t* gc_map) {
Brian Carlstromae826982011-11-09 01:33:42 -0800282 return OatFile::OatMethod(NULL,
283 reinterpret_cast<uint32_t>(code),
284 frame_size_in_bytes,
285 core_spill_mask,
286 fp_spill_mask,
287 reinterpret_cast<uint32_t>(mapping_table),
288 reinterpret_cast<uint32_t>(vmap_table),
Brian Carlstromdf629502013-07-17 22:39:56 -0700289 reinterpret_cast<uint32_t>(gc_map));
Brian Carlstromae826982011-11-09 01:33:42 -0800290 }
291
Brian Carlstromea46f952013-07-30 01:26:50 -0700292 void MakeExecutable(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700293 CHECK(method != NULL);
Jeff Hao74180ca2013-03-27 15:29:11 -0700294 LOG(INFO) << "MakeExecutable " << PrettyMethod(method);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700295
Ian Rogersf3e98552013-03-20 15:49:49 -0700296 const CompiledMethod* compiled_method = NULL;
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700297 if (!method->IsAbstract()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800298 const mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
Ian Rogers4445a7e2012-10-05 17:19:13 -0700299 const DexFile& dex_file = *dex_cache->GetDexFile();
Ian Rogersf3e98552013-03-20 15:49:49 -0700300 compiled_method =
Brian Carlstrom51c24672013-07-11 16:00:56 -0700301 compiler_driver_->GetCompiledMethod(MethodReference(&dex_file,
302 method->GetDexMethodIndex()));
Ian Rogersf3e98552013-03-20 15:49:49 -0700303 }
304 if (compiled_method != NULL) {
Logan Chien971bf3f2012-05-01 15:47:55 +0800305 const std::vector<uint8_t>& code = compiled_method->GetCode();
306 MakeExecutable(code);
307 const void* method_code = CompiledMethod::CodePointer(&code[0],
308 compiled_method->GetInstructionSet());
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700309 LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
Brian Carlstromae826982011-11-09 01:33:42 -0800310 OatFile::OatMethod oat_method = CreateOatMethod(method_code,
311 compiled_method->GetFrameSizeInBytes(),
312 compiled_method->GetCoreSpillMask(),
313 compiled_method->GetFpSpillMask(),
314 &compiled_method->GetMappingTable()[0],
315 &compiled_method->GetVmapTable()[0],
Jeff Hao74180ca2013-03-27 15:29:11 -0700316 NULL);
Brian Carlstrom265091e2013-01-30 14:08:26 -0800317 oat_method.LinkMethod(method);
Ian Rogers0f40ac32013-08-13 22:10:30 -0700318 method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700319 } else {
Ian Rogersf3e98552013-03-20 15:49:49 -0700320 const void* method_code;
Ian Rogers848871b2013-08-05 10:56:33 -0700321 // No code? You must mean to go into the interpreter.
322 method_code = GetCompiledCodeToInterpreterBridge();
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700323 LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
Brian Carlstromae826982011-11-09 01:33:42 -0800324 OatFile::OatMethod oat_method = CreateOatMethod(method_code,
325 kStackAlignment,
326 0,
327 0,
328 NULL,
329 NULL,
Jeff Hao74180ca2013-03-27 15:29:11 -0700330 NULL);
Brian Carlstrom265091e2013-01-30 14:08:26 -0800331 oat_method.LinkMethod(method);
Ian Rogers0f40ac32013-08-13 22:10:30 -0700332 method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700333 }
334 }
335
336 static void MakeExecutable(const void* code_start, size_t code_length) {
337 CHECK(code_start != NULL);
338 CHECK_NE(code_length, 0U);
339 uintptr_t data = reinterpret_cast<uintptr_t>(code_start);
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700340 uintptr_t base = RoundDown(data, kPageSize);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700341 uintptr_t limit = RoundUp(data + code_length, kPageSize);
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700342 uintptr_t len = limit - base;
343 int result = mprotect(reinterpret_cast<void*>(base), len, PROT_READ | PROT_WRITE | PROT_EXEC);
Brian Carlstrom7a00a3c2012-01-25 18:38:03 -0800344 CHECK_EQ(result, 0);
Shih-wei Liao24782c62012-01-08 12:46:11 -0800345
Ian Rogers16341552011-10-10 11:33:06 -0700346 // Flush instruction cache
Shih-wei Liao24782c62012-01-08 12:46:11 -0800347 // Only uses __builtin___clear_cache if GCC >= 4.3.3
348#if GCC_VERSION >= 40303
Ian Rogers16341552011-10-10 11:33:06 -0700349 __builtin___clear_cache(reinterpret_cast<void*>(base), reinterpret_cast<void*>(base + len));
Brian Carlstrom7a00a3c2012-01-25 18:38:03 -0800350#else
Brian Carlstrom6f485c62013-07-18 15:35:35 -0700351 LOG(FATAL) << "UNIMPLEMENTED: cache flush";
Shih-wei Liao24782c62012-01-08 12:46:11 -0800352#endif
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700353 }
354
Elliott Hughes76160052012-12-12 16:31:20 -0800355 static void SetEnvironmentVariables(std::string& android_data) {
356 if (IsHost()) {
Elliott Hughes0af55432011-08-17 18:37:28 -0700357 // $ANDROID_ROOT is set on the device, but not on the host.
358 // We need to set this so that icu4c can find its locale data.
359 std::string root;
360 root += getenv("ANDROID_BUILD_TOP");
Elliott Hughesa0cb1202012-01-23 17:34:32 -0800361#if defined(__linux__)
Elliott Hughes0af55432011-08-17 18:37:28 -0700362 root += "/out/host/linux-x86";
Elliott Hughesa0cb1202012-01-23 17:34:32 -0800363#elif defined(__APPLE__)
364 root += "/out/host/darwin-x86";
365#else
366#error unsupported OS
367#endif
Elliott Hughes0af55432011-08-17 18:37:28 -0700368 setenv("ANDROID_ROOT", root.c_str(), 1);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700369 setenv("LD_LIBRARY_PATH", ":", 0); // Required by java.lang.System.<clinit>.
Elliott Hughes0af55432011-08-17 18:37:28 -0700370 }
371
Brian Carlstrom7675e162013-06-10 16:18:04 -0700372 // On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of dalvik-cache
373 android_data = (IsHost() ? "/tmp/art-data-XXXXXX" : "/data/dalvik-cache/art-data-XXXXXX");
Elliott Hughes76160052012-12-12 16:31:20 -0800374 if (mkdtemp(&android_data[0]) == NULL) {
375 PLOG(FATAL) << "mkdtemp(\"" << &android_data[0] << "\") failed";
Elliott Hughes0f4c41d2011-09-04 14:58:03 -0700376 }
Elliott Hughes76160052012-12-12 16:31:20 -0800377 setenv("ANDROID_DATA", android_data.c_str(), 1);
378 }
379
380 protected:
381 static bool IsHost() {
382 return (getenv("ANDROID_BUILD_TOP") != NULL);
383 }
384
385 virtual void SetUp() {
386 SetEnvironmentVariables(android_data_);
Brian Carlstrom7675e162013-06-10 16:18:04 -0700387 dalvik_cache_.append(android_data_.c_str());
388 dalvik_cache_.append("/dalvik-cache");
389 int mkdir_result = mkdir(dalvik_cache_.c_str(), 0700);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700390 ASSERT_EQ(mkdir_result, 0);
391
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700392 std::string error_msg;
393 java_lang_dex_file_ = DexFile::Open(GetLibCoreDexFileName().c_str(),
394 GetLibCoreDexFileName().c_str(), &error_msg);
Ian Rogers33e95662013-05-20 20:29:14 -0700395 if (java_lang_dex_file_ == NULL) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700396 LOG(FATAL) << "Could not open .dex file '" << GetLibCoreDexFileName() << "': "
397 << error_msg << "\n";
Ian Rogers33e95662013-05-20 20:29:14 -0700398 }
Brian Carlstroma004aa92012-02-08 18:05:09 -0800399 boot_class_path_.push_back(java_lang_dex_file_);
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700400
Ian Rogers1d54e732013-05-02 21:10:01 -0700401 std::string min_heap_string(StringPrintf("-Xms%zdm", gc::Heap::kDefaultInitialSize / MB));
402 std::string max_heap_string(StringPrintf("-Xmx%zdm", gc::Heap::kDefaultMaximumSize / MB));
Ian Rogers30fab402012-01-23 15:43:46 -0800403
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700404 Runtime::Options options;
Brian Carlstroma4a7b482011-10-16 15:29:16 -0700405 options.push_back(std::make_pair("compiler", reinterpret_cast<void*>(NULL)));
Brian Carlstroma004aa92012-02-08 18:05:09 -0800406 options.push_back(std::make_pair("bootclasspath", &boot_class_path_));
Brian Carlstrom69b15fb2011-09-03 12:25:21 -0700407 options.push_back(std::make_pair("-Xcheck:jni", reinterpret_cast<void*>(NULL)));
Ian Rogers30fab402012-01-23 15:43:46 -0800408 options.push_back(std::make_pair(min_heap_string.c_str(), reinterpret_cast<void*>(NULL)));
409 options.push_back(std::make_pair(max_heap_string.c_str(), reinterpret_cast<void*>(NULL)));
Brian Carlstromdf629502013-07-17 22:39:56 -0700410 if (!Runtime::Create(options, false)) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700411 LOG(FATAL) << "Failed to create runtime";
412 return;
413 }
414 runtime_.reset(Runtime::Current());
415 // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
416 // give it away now and then switch to a more managable ScopedObjectAccess.
417 Thread::Current()->TransitionFromRunnableToSuspended(kNative);
Ian Rogers1d54e732013-05-02 21:10:01 -0700418 {
419 ScopedObjectAccess soa(Thread::Current());
420 ASSERT_TRUE(runtime_.get() != NULL);
421 class_linker_ = runtime_->GetClassLinker();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700422
Ian Rogers1d54e732013-05-02 21:10:01 -0700423 InstructionSet instruction_set = kNone;
Dave Allison70202782013-10-22 17:52:19 -0700424
Brian Carlstrom1bd2ceb2013-11-06 00:29:48 -0800425 // Take the default set of instruction features from the build.
Dave Allison70202782013-10-22 17:52:19 -0700426 InstructionSetFeatures instruction_set_features =
Brian Carlstrom1bd2ceb2013-11-06 00:29:48 -0800427 ParseFeatureList(STRINGIFY(ART_DEFAULT_INSTRUCTION_SET_FEATURES));
Dave Allison70202782013-10-22 17:52:19 -0700428
jeffhaoc0228b82012-08-29 18:15:05 -0700429#if defined(__arm__)
Ian Rogers1d54e732013-05-02 21:10:01 -0700430 instruction_set = kThumb2;
Dave Allison70202782013-10-22 17:52:19 -0700431 InstructionSetFeatures runtime_features = GuessInstructionFeatures();
432
433 // for ARM, do a runtime check to make sure that the features we are passed from
434 // the build match the features we actually determine at runtime.
435 ASSERT_EQ(instruction_set_features, runtime_features);
jeffhaoc0228b82012-08-29 18:15:05 -0700436#elif defined(__mips__)
Ian Rogers1d54e732013-05-02 21:10:01 -0700437 instruction_set = kMips;
jeffhaoc0228b82012-08-29 18:15:05 -0700438#elif defined(__i386__)
Ian Rogers1d54e732013-05-02 21:10:01 -0700439 instruction_set = kX86;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700440#endif
buzbeec531cef2012-10-18 07:09:20 -0700441
Ian Rogers1d54e732013-05-02 21:10:01 -0700442 // TODO: make selectable
buzbeec531cef2012-10-18 07:09:20 -0700443#if defined(ART_USE_PORTABLE_COMPILER)
Ian Rogers1d54e732013-05-02 21:10:01 -0700444 CompilerBackend compiler_backend = kPortable;
buzbeec531cef2012-10-18 07:09:20 -0700445#else
Ian Rogers1d54e732013-05-02 21:10:01 -0700446 CompilerBackend compiler_backend = kQuick;
buzbeec531cef2012-10-18 07:09:20 -0700447#endif
448
Ian Rogers1d54e732013-05-02 21:10:01 -0700449 for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
450 Runtime::CalleeSaveType type = Runtime::CalleeSaveType(i);
451 if (!runtime_->HasCalleeSaveMethod(type)) {
452 runtime_->SetCalleeSaveMethod(
453 runtime_->CreateCalleeSaveMethod(instruction_set, type), type);
454 }
455 }
456 class_linker_->FixupDexCaches(runtime_->GetResolutionMethod());
457 compiler_driver_.reset(new CompilerDriver(compiler_backend, instruction_set,
Dave Allison70202782013-10-22 17:52:19 -0700458 instruction_set_features,
Ian Rogers1d54e732013-05-02 21:10:01 -0700459 true, new CompilerDriver::DescriptorSet,
Brian Carlstrom45602482013-07-21 22:07:55 -0700460 2, true));
Ian Rogers4f0d07c2011-10-06 23:38:47 -0700461 }
Brian Carlstrom96391602013-06-13 19:49:50 -0700462 // We typically don't generate an image in unit tests, disable this optimization by default.
463 compiler_driver_->SetSupportBootImageFixup(false);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700464
Ian Rogers1d54e732013-05-02 21:10:01 -0700465 // We're back in native, take the opportunity to initialize well known classes.
Brian Carlstromea46f952013-07-30 01:26:50 -0700466 WellKnownClasses::Init(Thread::Current()->GetJniEnv());
Mathieu Chartier02b6a782012-10-26 13:51:26 -0700467 // Create the heap thread pool so that the GC runs in parallel for tests. Normally, the thread
468 // pool is created by the runtime.
469 runtime_->GetHeap()->CreateThreadPool();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700470 runtime_->GetHeap()->VerifyHeap(); // Check for heap corruption before the test
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700471 }
472
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700473 virtual void TearDown() {
474 const char* android_data = getenv("ANDROID_DATA");
475 ASSERT_TRUE(android_data != NULL);
Brian Carlstrom7675e162013-06-10 16:18:04 -0700476 DIR* dir = opendir(dalvik_cache_.c_str());
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700477 ASSERT_TRUE(dir != NULL);
Elliott Hughes4696b5b2012-10-30 10:35:10 -0700478 dirent* e;
479 while ((e = readdir(dir)) != NULL) {
480 if ((strcmp(e->d_name, ".") == 0) || (strcmp(e->d_name, "..") == 0)) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700481 continue;
482 }
Brian Carlstrom7675e162013-06-10 16:18:04 -0700483 std::string filename(dalvik_cache_);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700484 filename.push_back('/');
Elliott Hughes4696b5b2012-10-30 10:35:10 -0700485 filename.append(e->d_name);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700486 int unlink_result = unlink(filename.c_str());
487 ASSERT_EQ(0, unlink_result);
Jesse Wilsonac5b9e22011-07-27 15:11:13 -0400488 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700489 closedir(dir);
Brian Carlstrom7675e162013-06-10 16:18:04 -0700490 int rmdir_cache_result = rmdir(dalvik_cache_.c_str());
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700491 ASSERT_EQ(0, rmdir_cache_result);
Elliott Hughes34023802011-08-30 12:06:17 -0700492 int rmdir_data_result = rmdir(android_data_.c_str());
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700493 ASSERT_EQ(0, rmdir_data_result);
Elliott Hughes0af55432011-08-17 18:37:28 -0700494
495 // icu4c has a fixed 10-element array "gCommonICUDataArray".
496 // If we run > 10 tests, we fill that array and u_setCommonData fails.
497 // There's a function to clear the array, but it's not public...
498 typedef void (*IcuCleanupFn)();
499 void* sym = dlsym(RTLD_DEFAULT, "u_cleanup_" U_ICU_VERSION_SHORT);
500 CHECK(sym != NULL);
501 IcuCleanupFn icu_cleanup_fn = reinterpret_cast<IcuCleanupFn>(sym);
502 (*icu_cleanup_fn)();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700503
Ian Rogers1212a022013-03-04 10:48:41 -0800504 compiler_driver_.reset();
Elliott Hughes4d6850c2012-01-18 15:55:06 -0800505 STLDeleteElements(&opened_dex_files_);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700506
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800507 Runtime::Current()->GetHeap()->VerifyHeap(); // Check for heap corruption after the test
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700508 }
Jesse Wilsonac5b9e22011-07-27 15:11:13 -0400509
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700510 std::string GetLibCoreDexFileName() {
Brian Carlstrom3b010aa2013-06-25 23:06:36 -0700511 return GetDexFileName("core-libart");
Brian Carlstrom265091e2013-01-30 14:08:26 -0800512 }
513
514 std::string GetDexFileName(const std::string& jar_prefix) {
Elliott Hughes76160052012-12-12 16:31:20 -0800515 if (IsHost()) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700516 const char* host_dir = getenv("ANDROID_HOST_OUT");
517 CHECK(host_dir != NULL);
Brian Carlstrom265091e2013-01-30 14:08:26 -0800518 return StringPrintf("%s/framework/%s-hostdex.jar", host_dir, jar_prefix.c_str());
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700519 }
Brian Carlstrom265091e2013-01-30 14:08:26 -0800520 return StringPrintf("%s/framework/%s.jar", GetAndroidRoot(), jar_prefix.c_str());
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700521 }
522
Brian Carlstrom3f47c122013-03-07 00:02:40 -0800523 std::string GetTestAndroidRoot() {
524 if (IsHost()) {
525 const char* host_dir = getenv("ANDROID_HOST_OUT");
526 CHECK(host_dir != NULL);
527 return host_dir;
528 }
529 return GetAndroidRoot();
530 }
531
Ian Rogers33e95662013-05-20 20:29:14 -0700532 const DexFile* OpenTestDexFile(const char* name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700533 CHECK(name != NULL);
534 std::string filename;
Elliott Hughes76160052012-12-12 16:31:20 -0800535 if (IsHost()) {
Brian Carlstromb2793372012-03-17 18:27:16 -0700536 filename += getenv("ANDROID_HOST_OUT");
537 filename += "/framework/";
538 } else {
539 filename += "/data/nativetest/art/";
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700540 }
Brian Carlstromb2793372012-03-17 18:27:16 -0700541 filename += "art-test-dex-";
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700542 filename += name;
543 filename += ".jar";
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700544 std::string error_msg;
545 const DexFile* dex_file = DexFile::Open(filename.c_str(), filename.c_str(), &error_msg);
546 CHECK(dex_file != NULL) << "Failed to open '" << filename << "': " << error_msg;
Brian Carlstrome0948e12013-08-29 09:36:15 -0700547 CHECK_EQ(PROT_READ, dex_file->GetPermissions());
548 CHECK(dex_file->IsReadOnly());
Elliott Hughes4d6850c2012-01-18 15:55:06 -0800549 opened_dex_files_.push_back(dex_file);
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700550 return dex_file;
551 }
552
Ian Rogers33e95662013-05-20 20:29:14 -0700553 jobject LoadDex(const char* dex_name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700554 const DexFile* dex_file = OpenTestDexFile(dex_name);
555 CHECK(dex_file != NULL);
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700556 class_linker_->RegisterDexFile(*dex_file);
557 std::vector<const DexFile*> class_path;
558 class_path.push_back(dex_file);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700559 ScopedObjectAccessUnchecked soa(Thread::Current());
560 ScopedLocalRef<jobject> class_loader_local(soa.Env(),
561 soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader));
562 jobject class_loader = soa.Env()->NewGlobalRef(class_loader_local.get());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800563 soa.Self()->SetClassLoaderOverride(soa.Decode<mirror::ClassLoader*>(class_loader_local.get()));
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700564 Runtime::Current()->SetCompileTimeClassPath(class_loader, class_path);
565 return class_loader;
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700566 }
567
Ian Rogers33e95662013-05-20 20:29:14 -0700568 void CompileClass(mirror::ClassLoader* class_loader, const char* class_name)
569 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Elliott Hughes95572412011-12-13 18:14:20 -0800570 std::string class_descriptor(DotToDescriptor(class_name));
Mathieu Chartier590fee92013-09-13 13:46:47 -0700571 SirtRef<mirror::ClassLoader> loader(Thread::Current(), class_loader);
572 mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), loader);
Brian Carlstromaded5f72011-10-07 17:15:04 -0700573 CHECK(klass != NULL) << "Class not found " << class_name;
574 for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
575 CompileMethod(klass->GetDirectMethod(i));
576 }
577 for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
578 CompileMethod(klass->GetVirtualMethod(i));
579 }
580 }
581
Brian Carlstromea46f952013-07-30 01:26:50 -0700582 void CompileMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700583 CHECK(method != NULL);
Ian Rogers5fe9af72013-11-14 00:17:20 -0800584 TimingLogger timings("CommonTest::CompileMethod", false, false);
Anwar Ghuloumbe576f42013-07-25 17:32:40 -0700585 timings.StartSplit("CompileOne");
Brian Carlstrom45602482013-07-21 22:07:55 -0700586 compiler_driver_->CompileOne(method, timings);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700587 MakeExecutable(method);
Ian Rogers5fe9af72013-11-14 00:17:20 -0800588 timings.EndSplit();
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700589 }
590
Mathieu Chartier590fee92013-09-13 13:46:47 -0700591 void CompileDirectMethod(SirtRef<mirror::ClassLoader>& class_loader, const char* class_name,
592 const char* method_name, const char* signature)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700593 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Elliott Hughes95572412011-12-13 18:14:20 -0800594 std::string class_descriptor(DotToDescriptor(class_name));
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800595 mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader);
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700596 CHECK(klass != NULL) << "Class not found " << class_name;
Brian Carlstromea46f952013-07-30 01:26:50 -0700597 mirror::ArtMethod* method = klass->FindDirectMethod(method_name, signature);
Elliott Hughes0f4c41d2011-09-04 14:58:03 -0700598 CHECK(method != NULL) << "Direct method not found: "
599 << class_name << "." << method_name << signature;
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700600 CompileMethod(method);
601 }
602
Mathieu Chartier590fee92013-09-13 13:46:47 -0700603 void CompileVirtualMethod(SirtRef<mirror::ClassLoader>& class_loader, const char* class_name,
604 const char* method_name, const char* signature)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700605 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Elliott Hughes95572412011-12-13 18:14:20 -0800606 std::string class_descriptor(DotToDescriptor(class_name));
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800607 mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader);
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700608 CHECK(klass != NULL) << "Class not found " << class_name;
Brian Carlstromea46f952013-07-30 01:26:50 -0700609 mirror::ArtMethod* method = klass->FindVirtualMethod(method_name, signature);
Elliott Hughes0f4c41d2011-09-04 14:58:03 -0700610 CHECK(method != NULL) << "Virtual method not found: "
611 << class_name << "." << method_name << signature;
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700612 CompileMethod(method);
613 }
614
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800615 void ReserveImageSpace() {
616 // Reserve where the image will be loaded up front so that other parts of test set up don't
617 // accidentally end up colliding with the fixed memory address when we need to load the image.
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700618 std::string error_msg;
Brian Carlstrom2d888622013-07-18 17:02:00 -0700619 image_reservation_.reset(MemMap::MapAnonymous("image reservation",
620 reinterpret_cast<byte*>(ART_BASE_ADDRESS),
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800621 (size_t)100 * 1024 * 1024, // 100MB
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700622 PROT_NONE, &error_msg));
623 CHECK(image_reservation_.get() != nullptr) << error_msg;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800624 }
625
626 void UnreserveImageSpace() {
627 image_reservation_.reset();
628 }
629
Elliott Hughes34023802011-08-30 12:06:17 -0700630 std::string android_data_;
Brian Carlstrom7675e162013-06-10 16:18:04 -0700631 std::string dalvik_cache_;
Brian Carlstroma004aa92012-02-08 18:05:09 -0800632 const DexFile* java_lang_dex_file_; // owned by runtime_
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700633 std::vector<const DexFile*> boot_class_path_;
Elliott Hughes90a33692011-08-30 13:27:07 -0700634 UniquePtr<Runtime> runtime_;
Ian Rogers0e073f72011-09-09 10:45:46 -0700635 // Owned by the runtime
Carl Shapiro7a909592011-07-24 19:21:59 -0700636 ClassLinker* class_linker_;
Ian Rogers1212a022013-03-04 10:48:41 -0800637 UniquePtr<CompilerDriver> compiler_driver_;
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700638
639 private:
Elliott Hughes4d6850c2012-01-18 15:55:06 -0800640 std::vector<const DexFile*> opened_dex_files_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800641 UniquePtr<MemMap> image_reservation_;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700642};
643
Elliott Hughesb264f082012-04-06 17:10:10 -0700644// Sets a CheckJni abort hook to catch failures. Note that this will cause CheckJNI to carry on
645// rather than aborting, so be careful!
646class CheckJniAbortCatcher {
647 public:
648 CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) {
649 vm_->check_jni_abort_hook = Hook;
650 vm_->check_jni_abort_hook_data = &actual_;
651 }
652
653 ~CheckJniAbortCatcher() {
654 vm_->check_jni_abort_hook = NULL;
655 vm_->check_jni_abort_hook_data = NULL;
Elliott Hughes56ef0422012-06-19 14:35:04 -0700656 EXPECT_TRUE(actual_.empty()) << actual_;
Elliott Hughesb264f082012-04-06 17:10:10 -0700657 }
658
659 void Check(const char* expected_text) {
660 EXPECT_TRUE(actual_.find(expected_text) != std::string::npos) << "\n"
661 << "Expected to find: " << expected_text << "\n"
662 << "In the output : " << actual_;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700663 actual_.clear();
Elliott Hughesb264f082012-04-06 17:10:10 -0700664 }
665
666 private:
667 static void Hook(void* data, const std::string& reason) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700668 // We use += because when we're hooking the aborts like this, multiple problems can be found.
669 *reinterpret_cast<std::string*>(data) += reason;
Elliott Hughesb264f082012-04-06 17:10:10 -0700670 }
671
672 JavaVMExt* vm_;
673 std::string actual_;
674
675 DISALLOW_COPY_AND_ASSIGN(CheckJniAbortCatcher);
676};
677
Brian Carlstrom265091e2013-01-30 14:08:26 -0800678// TODO: These tests were disabled for portable when we went to having
679// MCLinker link LLVM ELF output because we no longer just have code
680// blobs in memory. We'll need to dlopen to load and relocate
681// temporary output to resurrect these tests.
682#if defined(ART_USE_PORTABLE_COMPILER)
683#define TEST_DISABLED_FOR_PORTABLE() printf("WARNING: TEST DISABLED FOR PORTABLE\n"); return
684#else
685#define TEST_DISABLED_FOR_PORTABLE()
686#endif
Brian Carlstrom934486c2011-07-12 23:42:50 -0700687} // namespace art
Elliott Hughes34023802011-08-30 12:06:17 -0700688
689namespace std {
690
691// TODO: isn't gtest supposed to be able to print STL types for itself?
692template <typename T>
693std::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs) {
Elliott Hughes14134a12011-09-30 16:55:51 -0700694 os << ::art::ToString(rhs);
Elliott Hughes34023802011-08-30 12:06:17 -0700695 return os;
696}
697
698} // namespace std
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700699
700#endif // ART_RUNTIME_COMMON_TEST_H_