blob: df7fa202265e89348be35f27fb6f70e68ba755e4 [file] [log] [blame]
Andreas Gampea727e372015-08-25 09:22:37 -07001/*
2 * Copyright (C) 2015 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#include "jni.h"
18
19#include "base/logging.h"
20#include "dex_file-inl.h"
Alex Lightce77fc02016-12-15 01:05:52 +000021#include "jni_internal.h"
Andreas Gampea727e372015-08-25 09:22:37 -070022#include "mirror/class-inl.h"
23#include "nth_caller_visitor.h"
Vladimir Marko97d7e1c2016-10-04 14:44:28 +010024#include "oat_file.h"
Andreas Gampea727e372015-08-25 09:22:37 -070025#include "runtime.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070026#include "scoped_thread_state_change-inl.h"
Andreas Gampea727e372015-08-25 09:22:37 -070027#include "stack.h"
28#include "thread-inl.h"
29
30namespace art {
31
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -070032static bool asserts_enabled = true;
Andreas Gampea727e372015-08-25 09:22:37 -070033
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -070034// public static native void disableStackFrameAsserts();
35// Note: to globally disable asserts in unsupported configurations.
36
37extern "C" JNIEXPORT void JNICALL Java_Main_disableStackFrameAsserts(JNIEnv* env ATTRIBUTE_UNUSED,
38 jclass cls ATTRIBUTE_UNUSED) {
39 asserts_enabled = false;
40}
41
Mingyao Yangf711f2c2016-05-23 12:29:39 -070042static jboolean IsInterpreted(JNIEnv* env, jclass, size_t level) {
Andreas Gampea727e372015-08-25 09:22:37 -070043 ScopedObjectAccess soa(env);
Mingyao Yangf711f2c2016-05-23 12:29:39 -070044 NthCallerVisitor caller(soa.Self(), level, false);
Andreas Gampea727e372015-08-25 09:22:37 -070045 caller.WalkStack();
46 CHECK(caller.caller != nullptr);
Andreas Gampe89df7bf2015-09-30 13:13:21 -070047 return caller.GetCurrentShadowFrame() != nullptr ? JNI_TRUE : JNI_FALSE;
Andreas Gampea727e372015-08-25 09:22:37 -070048}
49
Mingyao Yangf711f2c2016-05-23 12:29:39 -070050// public static native boolean isInterpreted();
51
52extern "C" JNIEXPORT jboolean JNICALL Java_Main_isInterpreted(JNIEnv* env, jclass klass) {
53 return IsInterpreted(env, klass, 1);
54}
55
Alex Lightce77fc02016-12-15 01:05:52 +000056// public static native boolean isInterpreted(int depth);
57
58extern "C" JNIEXPORT jboolean JNICALL Java_Main_isInterpretedAt(JNIEnv* env,
59 jclass klass,
60 jint depth) {
61 return IsInterpreted(env, klass, depth);
62}
63
64
65// public static native boolean isInterpretedFunction(String smali);
66
67// TODO Remove 'allow_runtime_frames' option once we have deoptimization through runtime frames.
68struct MethodIsInterpretedVisitor : public StackVisitor {
69 public:
70 MethodIsInterpretedVisitor(Thread* thread, ArtMethod* goal, bool require_deoptable)
71 : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
72 goal_(goal),
73 method_is_interpreted_(true),
74 method_found_(false),
75 prev_was_runtime_(true),
76 require_deoptable_(require_deoptable) {}
77
78 virtual bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
79 if (goal_ == GetMethod()) {
80 method_is_interpreted_ = (require_deoptable_ && prev_was_runtime_) || IsShadowFrame();
81 method_found_ = true;
82 return false;
83 }
84 prev_was_runtime_ = GetMethod()->IsRuntimeMethod();
85 return true;
86 }
87
88 bool IsInterpreted() {
89 return method_is_interpreted_;
90 }
91
92 bool IsFound() {
93 return method_found_;
94 }
95
96 private:
97 const ArtMethod* goal_;
98 bool method_is_interpreted_;
99 bool method_found_;
100 bool prev_was_runtime_;
101 bool require_deoptable_;
102};
103
104// TODO Remove 'require_deoptimizable' option once we have deoptimization through runtime frames.
105extern "C" JNIEXPORT jboolean JNICALL Java_Main_isInterpretedFunction(
106 JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject method, jboolean require_deoptimizable) {
107 // Return false if this seems to not be an ART runtime.
108 if (Runtime::Current() == nullptr) {
109 return JNI_FALSE;
110 }
111 if (method == nullptr) {
112 env->ThrowNew(env->FindClass("java/lang/NullPointerException"), "method is null!");
113 return JNI_FALSE;
114 }
115 jmethodID id = env->FromReflectedMethod(method);
116 if (id == nullptr) {
117 env->ThrowNew(env->FindClass("java/lang/Error"), "Unable to interpret method argument!");
118 return JNI_FALSE;
119 }
120 bool result;
121 bool found;
122 {
123 ScopedObjectAccess soa(env);
124 ArtMethod* goal = jni::DecodeArtMethod(id);
125 MethodIsInterpretedVisitor v(soa.Self(), goal, require_deoptimizable);
126 v.WalkStack();
127 bool enters_interpreter = Runtime::Current()->GetClassLinker()->IsQuickToInterpreterBridge(
128 goal->GetEntryPointFromQuickCompiledCode());
129 result = (v.IsInterpreted() || enters_interpreter);
130 found = v.IsFound();
131 }
132 if (!found) {
133 env->ThrowNew(env->FindClass("java/lang/Error"), "Unable to find given method in stack!");
134 return JNI_FALSE;
135 }
136 return result;
137}
138
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700139// public static native void assertIsInterpreted();
Andreas Gampea727e372015-08-25 09:22:37 -0700140
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700141extern "C" JNIEXPORT void JNICALL Java_Main_assertIsInterpreted(JNIEnv* env, jclass klass) {
142 if (asserts_enabled) {
143 CHECK(Java_Main_isInterpreted(env, klass));
144 }
Andreas Gampe89df7bf2015-09-30 13:13:21 -0700145}
Andreas Gampea727e372015-08-25 09:22:37 -0700146
Mingyao Yangf711f2c2016-05-23 12:29:39 -0700147static jboolean IsManaged(JNIEnv* env, jclass cls, size_t level) {
Andreas Gampea727e372015-08-25 09:22:37 -0700148 ScopedObjectAccess soa(env);
149
Mathieu Chartier0795f232016-09-27 18:43:30 -0700150 ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(cls);
Andreas Gampea727e372015-08-25 09:22:37 -0700151 const DexFile& dex_file = klass->GetDexFile();
152 const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
153 if (oat_dex_file == nullptr) {
154 // No oat file, this must be a test configuration that doesn't compile at all. Ignore that the
155 // result will be that we're running the interpreter.
Andreas Gampe89df7bf2015-09-30 13:13:21 -0700156 return JNI_FALSE;
Andreas Gampea727e372015-08-25 09:22:37 -0700157 }
158
Mingyao Yangf711f2c2016-05-23 12:29:39 -0700159 NthCallerVisitor caller(soa.Self(), level, false);
Andreas Gampea727e372015-08-25 09:22:37 -0700160 caller.WalkStack();
161 CHECK(caller.caller != nullptr);
Andreas Gampea727e372015-08-25 09:22:37 -0700162
Andreas Gampe89df7bf2015-09-30 13:13:21 -0700163 return caller.GetCurrentShadowFrame() != nullptr ? JNI_FALSE : JNI_TRUE;
164}
Andreas Gampea727e372015-08-25 09:22:37 -0700165
Mingyao Yangf711f2c2016-05-23 12:29:39 -0700166// public static native boolean isManaged();
167
168extern "C" JNIEXPORT jboolean JNICALL Java_Main_isManaged(JNIEnv* env, jclass cls) {
169 return IsManaged(env, cls, 1);
170}
171
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700172// public static native void assertIsManaged();
Andreas Gampe89df7bf2015-09-30 13:13:21 -0700173
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700174extern "C" JNIEXPORT void JNICALL Java_Main_assertIsManaged(JNIEnv* env, jclass cls) {
175 if (asserts_enabled) {
176 CHECK(Java_Main_isManaged(env, cls));
177 }
Andreas Gampea727e372015-08-25 09:22:37 -0700178}
179
Mingyao Yangf711f2c2016-05-23 12:29:39 -0700180// public static native boolean isCallerInterpreted();
181
182extern "C" JNIEXPORT jboolean JNICALL Java_Main_isCallerInterpreted(JNIEnv* env, jclass klass) {
183 return IsInterpreted(env, klass, 2);
184}
185
186// public static native void assertCallerIsInterpreted();
187
188extern "C" JNIEXPORT void JNICALL Java_Main_assertCallerIsInterpreted(JNIEnv* env, jclass klass) {
189 if (asserts_enabled) {
190 CHECK(Java_Main_isCallerInterpreted(env, klass));
191 }
192}
193
194// public static native boolean isCallerManaged();
195
196extern "C" JNIEXPORT jboolean JNICALL Java_Main_isCallerManaged(JNIEnv* env, jclass cls) {
197 return IsManaged(env, cls, 2);
198}
199
200// public static native void assertCallerIsManaged();
201
202extern "C" JNIEXPORT void JNICALL Java_Main_assertCallerIsManaged(JNIEnv* env, jclass cls) {
203 if (asserts_enabled) {
204 CHECK(Java_Main_isCallerManaged(env, cls));
205 }
206}
207
Andreas Gampea727e372015-08-25 09:22:37 -0700208} // namespace art