blob: e44e1c94e7829e5504f59678cffb34f5f4fdba36 [file] [log] [blame]
Mathieu Chartiere5f13e52015-02-24 09:37:21 -08001/*
2 * Copyright 2014 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 */
16
17#ifndef ART_RUNTIME_JIT_JIT_H_
18#define ART_RUNTIME_JIT_JIT_H_
19
Nicolas Geoffraya4f81542016-03-08 16:57:48 +000020#include "base/histogram-inl.h"
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080021#include "base/macros.h"
22#include "base/mutex.h"
Mathieu Chartiera4885cb2015-03-09 15:38:54 -070023#include "base/timing_logger.h"
Nicolas Geoffray9ac09ee2019-05-08 23:38:27 +010024#include "handle.h"
Mathieu Chartieref41db72016-10-25 15:08:01 -070025#include "jit/profile_saver_options.h"
26#include "obj_ptr.h"
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080027#include "thread_pool.h"
28
29namespace art {
30
Mathieu Chartiere401d142015-04-22 13:56:20 -070031class ArtMethod;
David Sehr9323e6e2016-09-13 08:58:35 -070032class ClassLinker;
Nicolas Geoffray9ac09ee2019-05-08 23:38:27 +010033class DexFile;
Nicolas Geoffraydc2fbb62019-04-11 22:55:50 +010034class OatDexFile;
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080035struct RuntimeArgumentMap;
Vladimir Marko3a21e382016-09-02 12:38:38 +010036union JValue;
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080037
David Sehr709b0702016-10-13 09:12:37 -070038namespace mirror {
39class Object;
40class Class;
Nicolas Geoffray9ac09ee2019-05-08 23:38:27 +010041class ClassLoader;
Nicolas Geoffraya48c3df2019-06-27 13:11:12 +000042class String;
David Sehr709b0702016-10-13 09:12:37 -070043} // namespace mirror
44
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080045namespace jit {
46
47class JitCodeCache;
Nicolas Geoffray7f7539b2019-06-06 16:20:54 +010048class JitMemoryRegion;
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080049class JitOptions;
50
Nicolas Geoffray274fe4a2016-04-12 16:33:24 +010051static constexpr int16_t kJitCheckForOSR = -1;
52static constexpr int16_t kJitHotnessDisabled = -2;
Nicolas Geoffray47b95802018-05-16 15:42:17 +010053// At what priority to schedule jit threads. 9 is the lowest foreground priority on device.
54// See android/os/Process.java.
55static constexpr int kJitPoolThreadPthreadDefaultPriority = 9;
David Srbeckye3fc2d12018-11-30 13:41:14 +000056static constexpr uint32_t kJitSamplesBatchSize = 32; // Must be power of 2.
Nicolas Geoffray47b95802018-05-16 15:42:17 +010057
58class JitOptions {
59 public:
60 static JitOptions* CreateFromRuntimeArguments(const RuntimeArgumentMap& options);
61
62 uint16_t GetCompileThreshold() const {
63 return compile_threshold_;
64 }
65
66 uint16_t GetWarmupThreshold() const {
67 return warmup_threshold_;
68 }
69
70 uint16_t GetOsrThreshold() const {
71 return osr_threshold_;
72 }
73
74 uint16_t GetPriorityThreadWeight() const {
75 return priority_thread_weight_;
76 }
77
78 uint16_t GetInvokeTransitionWeight() const {
79 return invoke_transition_weight_;
80 }
81
82 size_t GetCodeCacheInitialCapacity() const {
83 return code_cache_initial_capacity_;
84 }
85
86 size_t GetCodeCacheMaxCapacity() const {
87 return code_cache_max_capacity_;
88 }
89
90 bool DumpJitInfoOnShutdown() const {
91 return dump_info_on_shutdown_;
92 }
93
94 const ProfileSaverOptions& GetProfileSaverOptions() const {
95 return profile_saver_options_;
96 }
97
98 bool GetSaveProfilingInfo() const {
99 return profile_saver_options_.IsEnabled();
100 }
101
102 int GetThreadPoolPthreadPriority() const {
103 return thread_pool_pthread_priority_;
104 }
105
106 bool UseJitCompilation() const {
107 return use_jit_compilation_;
108 }
109
110 void SetUseJitCompilation(bool b) {
111 use_jit_compilation_ = b;
112 }
113
114 void SetSaveProfilingInfo(bool save_profiling_info) {
115 profile_saver_options_.SetEnabled(save_profiling_info);
116 }
117
118 void SetWaitForJitNotificationsToSaveProfile(bool value) {
119 profile_saver_options_.SetWaitForJitNotificationsToSave(value);
120 }
121
122 void SetProfileAOTCode(bool value) {
123 profile_saver_options_.SetProfileAOTCode(value);
124 }
125
126 void SetJitAtFirstUse() {
127 use_jit_compilation_ = true;
128 compile_threshold_ = 0;
129 }
130
131 private:
David Srbeckye3fc2d12018-11-30 13:41:14 +0000132 // We add the sample in batches of size kJitSamplesBatchSize.
133 // This method rounds the threshold so that it is multiple of the batch size.
134 static uint32_t RoundUpThreshold(uint32_t threshold);
135
Nicolas Geoffray47b95802018-05-16 15:42:17 +0100136 bool use_jit_compilation_;
137 size_t code_cache_initial_capacity_;
138 size_t code_cache_max_capacity_;
David Srbeckye3fc2d12018-11-30 13:41:14 +0000139 uint32_t compile_threshold_;
140 uint32_t warmup_threshold_;
141 uint32_t osr_threshold_;
Nicolas Geoffray47b95802018-05-16 15:42:17 +0100142 uint16_t priority_thread_weight_;
143 uint16_t invoke_transition_weight_;
144 bool dump_info_on_shutdown_;
145 int thread_pool_pthread_priority_;
146 ProfileSaverOptions profile_saver_options_;
147
148 JitOptions()
149 : use_jit_compilation_(false),
150 code_cache_initial_capacity_(0),
151 code_cache_max_capacity_(0),
152 compile_threshold_(0),
153 warmup_threshold_(0),
154 osr_threshold_(0),
155 priority_thread_weight_(0),
156 invoke_transition_weight_(0),
157 dump_info_on_shutdown_(false),
Nicolas Geoffrayc9de61c2018-11-27 17:34:31 +0000158 thread_pool_pthread_priority_(kJitPoolThreadPthreadDefaultPriority) {}
Nicolas Geoffray47b95802018-05-16 15:42:17 +0100159
160 DISALLOW_COPY_AND_ASSIGN(JitOptions);
161};
Nicolas Geoffray274fe4a2016-04-12 16:33:24 +0100162
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800163class Jit {
164 public:
Nicolas Geoffray71cd50f2016-04-14 15:00:33 +0100165 static constexpr size_t kDefaultPriorityThreadWeightRatio = 1000;
Nicolas Geoffraybd553eb2016-04-28 13:56:04 +0100166 static constexpr size_t kDefaultInvokeTransitionWeightRatio = 500;
buzbee42a09cb02017-02-01 09:08:31 -0800167 // How frequently should the interpreter check to see if OSR compilation is ready.
David Srbeckye3fc2d12018-11-30 13:41:14 +0000168 static constexpr int16_t kJitRecheckOSRThreshold = 101; // Prime number to avoid patterns.
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800169
170 virtual ~Jit();
Orion Hodsonad28f5e2018-10-17 09:08:17 +0100171
172 // Create JIT itself.
173 static Jit* Create(JitCodeCache* code_cache, JitOptions* options);
174
Nicolas Geoffrayd2f13ba2019-06-04 16:48:58 +0100175 bool CompileMethod(ArtMethod* method, Thread* self, bool baseline, bool osr, bool prejit)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700176 REQUIRES_SHARED(Locks::mutator_lock_);
Nicolas Geoffray274fe4a2016-04-12 16:33:24 +0100177
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800178 const JitCodeCache* GetCodeCache() const {
Orion Hodsonad28f5e2018-10-17 09:08:17 +0100179 return code_cache_;
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800180 }
Nicolas Geoffray274fe4a2016-04-12 16:33:24 +0100181
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800182 JitCodeCache* GetCodeCache() {
Orion Hodsonad28f5e2018-10-17 09:08:17 +0100183 return code_cache_;
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800184 }
Nicolas Geoffray274fe4a2016-04-12 16:33:24 +0100185
Orion Hodsonad28f5e2018-10-17 09:08:17 +0100186 void CreateThreadPool();
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800187 void DeleteThreadPool();
Mathieu Chartier93c21ba2018-12-10 13:08:30 -0800188 void WaitForWorkersToBeCreated();
Orion Hodsonad28f5e2018-10-17 09:08:17 +0100189
Mathieu Chartiera4885cb2015-03-09 15:38:54 -0700190 // Dump interesting info: #methods compiled, code vs data size, compile / verify cumulative
191 // loggers.
Nicolas Geoffraya4f81542016-03-08 16:57:48 +0000192 void DumpInfo(std::ostream& os) REQUIRES(!lock_);
Mathieu Chartiera4885cb2015-03-09 15:38:54 -0700193 // Add a timing logger to cumulative_timings_.
194 void AddTimingLogger(const TimingLogger& logger);
Nicolas Geoffraya4f81542016-03-08 16:57:48 +0000195
196 void AddMemoryUsage(ArtMethod* method, size_t bytes)
197 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700198 REQUIRES_SHARED(Locks::mutator_lock_);
Nicolas Geoffraya4f81542016-03-08 16:57:48 +0000199
Nicolas Geoffray47b95802018-05-16 15:42:17 +0100200 uint16_t OSRMethodThreshold() const {
201 return options_->GetOsrThreshold();
Mathieu Chartiera50f9cf2015-09-25 11:34:45 -0700202 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800203
Nicolas Geoffray47b95802018-05-16 15:42:17 +0100204 uint16_t HotMethodThreshold() const {
205 return options_->GetCompileThreshold();
Nicolas Geoffray274fe4a2016-04-12 16:33:24 +0100206 }
207
Nicolas Geoffray47b95802018-05-16 15:42:17 +0100208 uint16_t WarmMethodThreshold() const {
209 return options_->GetWarmupThreshold();
Nicolas Geoffray274fe4a2016-04-12 16:33:24 +0100210 }
211
212 uint16_t PriorityThreadWeight() const {
Nicolas Geoffray47b95802018-05-16 15:42:17 +0100213 return options_->GetPriorityThreadWeight();
Nicolas Geoffray274fe4a2016-04-12 16:33:24 +0100214 }
215
Nicolas Geoffraya48c3df2019-06-27 13:11:12 +0000216 // Return whether we should do JIT compilation. Note this will returns false
217 // if we only need to save profile information and not compile methods.
Nicolas Geoffray2fef66b2019-06-26 22:00:02 +0000218 bool UseJitCompilation() const {
219 return options_->UseJitCompilation();
220 }
Calin Juravleffc87072016-04-20 14:22:09 +0100221
Calin Juravle138dbff2016-06-28 19:36:58 +0100222 bool GetSaveProfilingInfo() const {
Nicolas Geoffray47b95802018-05-16 15:42:17 +0100223 return options_->GetSaveProfilingInfo();
Calin Juravleffc87072016-04-20 14:22:09 +0100224 }
225
Nicolas Geoffray274fe4a2016-04-12 16:33:24 +0100226 // Wait until there is no more pending compilation tasks.
227 void WaitForCompilationToFinish(Thread* self);
228
229 // Profiling methods.
230 void MethodEntered(Thread* thread, ArtMethod* method)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700231 REQUIRES_SHARED(Locks::mutator_lock_);
Nicolas Geoffray274fe4a2016-04-12 16:33:24 +0100232
David Srbeckye3fc2d12018-11-30 13:41:14 +0000233 ALWAYS_INLINE void AddSamples(Thread* self,
234 ArtMethod* method,
235 uint16_t samples,
236 bool with_backedges)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700237 REQUIRES_SHARED(Locks::mutator_lock_);
Nicolas Geoffray274fe4a2016-04-12 16:33:24 +0100238
Mathieu Chartieref41db72016-10-25 15:08:01 -0700239 void InvokeVirtualOrInterface(ObjPtr<mirror::Object> this_object,
Nicolas Geoffray274fe4a2016-04-12 16:33:24 +0100240 ArtMethod* caller,
241 uint32_t dex_pc,
242 ArtMethod* callee)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700243 REQUIRES_SHARED(Locks::mutator_lock_);
Nicolas Geoffray274fe4a2016-04-12 16:33:24 +0100244
Nicolas Geoffray71cd50f2016-04-14 15:00:33 +0100245 void NotifyInterpreterToCompiledCodeTransition(Thread* self, ArtMethod* caller)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700246 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray47b95802018-05-16 15:42:17 +0100247 AddSamples(self, caller, options_->GetInvokeTransitionWeight(), false);
Nicolas Geoffray71cd50f2016-04-14 15:00:33 +0100248 }
249
250 void NotifyCompiledCodeToInterpreterTransition(Thread* self, ArtMethod* callee)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700251 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray47b95802018-05-16 15:42:17 +0100252 AddSamples(self, callee, options_->GetInvokeTransitionWeight(), false);
Nicolas Geoffray71cd50f2016-04-14 15:00:33 +0100253 }
254
Calin Juravlec90bc922016-02-24 10:13:09 +0000255 // Starts the profile saver if the config options allow profile recording.
256 // The profile will be stored in the specified `filename` and will contain
257 // information collected from the given `code_paths` (a set of dex locations).
Calin Juravlec90bc922016-02-24 10:13:09 +0000258 void StartProfileSaver(const std::string& filename,
Calin Juravle77651c42017-03-03 18:04:02 -0800259 const std::vector<std::string>& code_paths);
Calin Juravle4d77b6a2015-12-01 18:38:09 +0000260 void StopProfileSaver();
Calin Juravle31f2c152015-10-23 17:56:15 +0100261
Calin Juravleb8e69992016-03-09 15:37:48 +0000262 void DumpForSigQuit(std::ostream& os) REQUIRES(!lock_);
Nicolas Geoffrayaee21562015-12-15 16:39:44 +0000263
Tamas Berghammer160e6df2016-01-05 14:29:02 +0000264 static void NewTypeLoadedIfUsingJit(mirror::Class* type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700265 REQUIRES_SHARED(Locks::mutator_lock_);
Tamas Berghammer160e6df2016-01-05 14:29:02 +0000266
Tamas Berghammerfffbee42016-01-15 13:09:34 +0000267 // If debug info generation is turned on then write the type information for types already loaded
268 // into the specified class linker to the jit debug interface,
269 void DumpTypeInfoForLoadedTypes(ClassLinker* linker);
270
Nicolas Geoffray35122442016-03-02 12:05:30 +0000271 // Return whether we should try to JIT compiled code as soon as an ArtMethod is invoked.
Siva Chandra05d24152016-01-05 17:43:17 -0800272 bool JitAtFirstUse();
273
Nicolas Geoffray35122442016-03-02 12:05:30 +0000274 // Return whether we can invoke JIT code for `method`.
275 bool CanInvokeCompiledCode(ArtMethod* method);
276
Calin Juravleb2771b42016-04-07 17:09:25 +0100277 // Return whether the runtime should use a priority thread weight when sampling.
Vladimir Markoa710d912017-09-12 14:56:07 +0100278 static bool ShouldUsePriorityThreadWeight(Thread* self);
Calin Juravleb2771b42016-04-07 17:09:25 +0100279
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000280 // If an OSR compiled version is available for `method`,
281 // and `dex_pc + dex_pc_offset` is an entry point of that compiled
282 // version, this method will jump to the compiled code, let it run,
283 // and return true afterwards. Return false otherwise.
284 static bool MaybeDoOnStackReplacement(Thread* thread,
285 ArtMethod* method,
286 uint32_t dex_pc,
287 int32_t dex_pc_offset,
288 JValue* result)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700289 REQUIRES_SHARED(Locks::mutator_lock_);
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000290
Nicolas Geoffraya7edd0d2018-11-07 03:18:16 +0000291 // Load the compiler library.
292 static bool LoadCompilerLibrary(std::string* error_msg);
Mathieu Chartier72918ea2016-03-24 11:07:06 -0700293
Andreas Gampef149b3f2016-11-16 14:58:24 -0800294 ThreadPool* GetThreadPool() const {
295 return thread_pool_.get();
296 }
297
Nicolas Geoffray021c5f22016-12-16 11:22:05 +0000298 // Stop the JIT by waiting for all current compilations and enqueued compilations to finish.
299 void Stop();
300
301 // Start JIT threads.
302 void Start();
303
Nicolas Geoffrayce9ed362018-11-29 03:19:28 +0000304 // Transition to a child state.
Nicolas Geoffray0d54cfb2019-05-03 09:13:52 +0100305 void PostForkChildAction(bool is_system_server, bool is_zygote);
Nicolas Geoffrayce9ed362018-11-29 03:19:28 +0000306
307 // Prepare for forking.
308 void PreZygoteFork();
309
310 // Adjust state after forking.
311 void PostZygoteFork();
Nicolas Geoffrayc9de61c2018-11-27 17:34:31 +0000312
Nicolas Geoffray9ac09ee2019-05-08 23:38:27 +0100313 // Compile methods from the given profile. If `add_to_queue` is true, methods
314 // in the profile are added to the JIT queue. Otherwise they are compiled
315 // directly.
316 void CompileMethodsFromProfile(Thread* self,
317 const std::vector<const DexFile*>& dex_files,
318 const std::string& profile_path,
319 Handle<mirror::ClassLoader> class_loader,
320 bool add_to_queue);
321
322 // Register the dex files to the JIT. This is to perform any compilation/optimization
323 // at the point of loading the dex files.
324 void RegisterDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files,
Nicolas Geoffray741a0702019-06-10 11:18:11 +0100325 jobject class_loader);
Nicolas Geoffrayde1b2a22019-02-27 09:10:57 +0000326
Nicolas Geoffraya48c3df2019-06-27 13:11:12 +0000327 // Called by the compiler to know whether it can directly encode the
328 // method/class/string.
329 bool CanEncodeMethod(ArtMethod* method, bool is_for_shared_region) const;
330 bool CanEncodeClass(ObjPtr<mirror::Class> cls, bool is_for_shared_region) const
331 REQUIRES_SHARED(Locks::mutator_lock_);
332 bool CanEncodeString(ObjPtr<mirror::String> string, bool is_for_shared_region) const
333 REQUIRES_SHARED(Locks::mutator_lock_);
334 bool CanAssumeInitialized(ObjPtr<mirror::Class> cls, bool is_for_shared_region) const
335 REQUIRES_SHARED(Locks::mutator_lock_);
336
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800337 private:
Orion Hodsonad28f5e2018-10-17 09:08:17 +0100338 Jit(JitCodeCache* code_cache, JitOptions* options);
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800339
David Srbeckye3fc2d12018-11-30 13:41:14 +0000340 // Compile the method if the number of samples passes a threshold.
341 // Returns false if we can not compile now - don't increment the counter and retry later.
342 bool MaybeCompileMethod(Thread* self,
343 ArtMethod* method,
344 uint32_t old_count,
345 uint32_t new_count,
346 bool with_backedges)
347 REQUIRES_SHARED(Locks::mutator_lock_);
348
Orion Hodsonad28f5e2018-10-17 09:08:17 +0100349 static bool BindCompilerMethods(std::string* error_msg);
Mathieu Chartierc1bc4152016-03-24 17:22:52 -0700350
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800351 // JIT compiler
Mathieu Chartier72918ea2016-03-24 11:07:06 -0700352 static void* jit_library_handle_;
353 static void* jit_compiler_handle_;
Nicolas Geoffrayc9de61c2018-11-27 17:34:31 +0000354 static void* (*jit_load_)(void);
Mathieu Chartier72918ea2016-03-24 11:07:06 -0700355 static void (*jit_unload_)(void*);
Nicolas Geoffray7f7539b2019-06-06 16:20:54 +0100356 static bool (*jit_compile_method_)(void*, JitMemoryRegion*, ArtMethod*, Thread*, bool, bool);
Mathieu Chartier72918ea2016-03-24 11:07:06 -0700357 static void (*jit_types_loaded_)(void*, mirror::Class**, size_t count);
Nicolas Geoffrayc9de61c2018-11-27 17:34:31 +0000358 static void (*jit_update_options_)(void*);
359 static bool (*jit_generate_debug_info_)(void*);
360 template <typename T> static bool LoadSymbol(T*, const char* symbol, std::string* error_msg);
Nicolas Geoffray47b95802018-05-16 15:42:17 +0100361
Orion Hodsonad28f5e2018-10-17 09:08:17 +0100362 // JIT resources owned by runtime.
363 jit::JitCodeCache* const code_cache_;
Nicolas Geoffray47b95802018-05-16 15:42:17 +0100364 const JitOptions* const options_;
365
Nicolas Geoffray47b95802018-05-16 15:42:17 +0100366 std::unique_ptr<ThreadPool> thread_pool_;
Nicolas Geoffraydc2fbb62019-04-11 22:55:50 +0100367 std::vector<std::unique_ptr<OatDexFile>> type_lookup_tables_;
Nicolas Geoffray47b95802018-05-16 15:42:17 +0100368
Mathieu Chartiera4885cb2015-03-09 15:38:54 -0700369 // Performance monitoring.
Mathieu Chartiera4885cb2015-03-09 15:38:54 -0700370 CumulativeLogger cumulative_timings_;
Nicolas Geoffraya4f81542016-03-08 16:57:48 +0000371 Histogram<uint64_t> memory_use_ GUARDED_BY(lock_);
372 Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
Mathieu Chartiera4885cb2015-03-09 15:38:54 -0700373
Mathieu Chartier3130cdf2015-05-03 15:20:23 -0700374 DISALLOW_COPY_AND_ASSIGN(Jit);
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800375};
376
Andreas Gampef149b3f2016-11-16 14:58:24 -0800377// Helper class to stop the JIT for a given scope. This will wait for the JIT to quiesce.
378class ScopedJitSuspend {
379 public:
380 ScopedJitSuspend();
381 ~ScopedJitSuspend();
382
383 private:
384 bool was_on_;
385};
386
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800387} // namespace jit
388} // namespace art
389
390#endif // ART_RUNTIME_JIT_JIT_H_