1a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/*
2a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Copyright (C) 2008 The Android Open Source Project
3a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *
4a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * you may not use this file except in compliance with the License.
6a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * You may obtain a copy of the License at
7a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *
8a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *
10a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Unless required by applicable law or agreed to in writing, software
11a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * See the License for the specific language governing permissions and
14a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * limitations under the License.
15a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */
16a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
17a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include "jni_internal.h"
18a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
19a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include <sys/mman.h>
20a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include <zlib.h>
21a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2207ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
23a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include "class_linker.h"
242dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "class_linker-inl.h"
254f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h"
2622d5e735f403c57525fe868304c7123f0ce66399Ian Rogers#include "field_helper.h"
271d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/space.h"
28ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_field-inl.h"
29ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h"
302dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h"
312dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h"
322dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h"
33b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers#include "mirror/string-inl.h"
342dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/throwable.h"
3558df32711162823647356afe25ae2cde04133563Jeff Hao#include "runtime.h"
3600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h"
37a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include "thread.h"
38a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
39a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesnamespace art {
40a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
413f6635a2c84d645002f651c312d53f8348646c1fElliott Hughesstatic void JniAbort(const char* jni_function_name, const char* msg) {
42a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  Thread* self = Thread::Current();
4300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(self);
44ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  mirror::ArtMethod* current_method = self->GetCurrentMethod(nullptr);
45a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
463b6baaa203fa63f1522b2172a1645f90412afdaeElliott Hughes  std::ostringstream os;
473f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes  os << "JNI DETECTED ERROR IN APPLICATION: " << msg;
48a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
49ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  if (jni_function_name != nullptr) {
503f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    os << "\n    in call to " << jni_function_name;
51a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
52a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  // TODO: is this useful given that we're about to dump the calling thread's stack?
53ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  if (current_method != nullptr) {
543f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    os << "\n    from " << PrettyMethod(current_method);
55a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  }
56a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  os << "\n";
57a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  self->Dump(os);
58a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
59a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  JavaVMExt* vm = Runtime::Current()->GetJavaVM();
60ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  if (vm->check_jni_abort_hook != nullptr) {
61b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes    vm->check_jni_abort_hook(vm->check_jni_abort_hook_data, os.str());
62a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  } else {
639da7f59c9059397182b9a97e898a42ec06d4d646Ian Rogers    // Ensure that we get a native stack trace for this thread.
649da7f59c9059397182b9a97e898a42ec06d4d646Ian Rogers    self->TransitionFromRunnableToSuspended(kNative);
65a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    LOG(FATAL) << os.str();
669da7f59c9059397182b9a97e898a42ec06d4d646Ian Rogers    self->TransitionFromSuspendedToRunnable();  // Unreachable, keep annotalysis happy.
67a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
68a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}
69a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
703f6635a2c84d645002f651c312d53f8348646c1fElliott Hughesstatic void JniAbortV(const char* jni_function_name, const char* fmt, va_list ap) {
713f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes  std::string msg;
723f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes  StringAppendV(&msg, fmt, ap);
733f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes  JniAbort(jni_function_name, msg.c_str());
743f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes}
753f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes
763f6635a2c84d645002f651c312d53f8348646c1fElliott Hughesvoid JniAbortF(const char* jni_function_name, const char* fmt, ...) {
773f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes  va_list args;
783f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes  va_start(args, fmt);
793f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes  JniAbortV(jni_function_name, fmt, args);
803f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes  va_end(args);
813f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes}
823f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes
83a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/*
84a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
85a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *      JNI function helpers
86a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
87a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */
88a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
89eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartierstatic bool IsHandleScopeLocalRef(JNIEnv* env, jobject localRef) {
90eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  return GetIndirectRefKind(localRef) == kHandleScopeOrInvalid &&
91eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier      reinterpret_cast<JNIEnvExt*>(env)->self->HandleScopeContains(localRef);
92959f8ed11ef9493a89b90a1f9a82a811dbc7ae0eIan Rogers}
93959f8ed11ef9493a89b90a1f9a82a811dbc7ae0eIan Rogers
943f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes// Flags passed into ScopedCheck.
95a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define kFlag_Default       0x0000
96a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
973f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritBad       0x0000      // Calling while in critical is not allowed.
983f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritOkay      0x0001      // Calling while in critical is allowed.
993f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritGet       0x0002      // This is a critical "get".
1003f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritRelease   0x0003      // This is a critical "release".
1013f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritMask      0x0003      // Bit mask to get "crit" value.
102a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1033f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_ExcepBad      0x0000      // Raised exceptions are not allowed.
1043f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_ExcepOkay     0x0004      // Raised exceptions are allowed.
105a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1063f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_Release       0x0010      // Are we in a non-critical release function?
1073f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_NullableUtf   0x0020      // Are our UTF parameters nullable?
108a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1093f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_Invocation    0x8000      // Part of the invocation interface (JavaVM*).
110a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
111485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes#define kFlag_ForceTrace    0x80000000  // Add this to a JNI function's flags if you want to trace every call.
112485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes
113a09576416788b916095739e43a16917e7948f3a4Elliott Hughesstatic const char* gBuiltInPrefixes[] = {
114a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  "Landroid/",
115a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  "Lcom/android/",
116a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  "Lcom/google/android/",
117a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  "Ldalvik/",
118a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  "Ljava/",
119a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  "Ljavax/",
120a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  "Llibcore/",
121a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  "Lorg/apache/harmony/",
122ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr
123a09576416788b916095739e43a16917e7948f3a4Elliott Hughes};
124a09576416788b916095739e43a16917e7948f3a4Elliott Hughes
125ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersstatic bool ShouldTrace(JavaVMExt* vm, mirror::ArtMethod* method)
126b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
127a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  // If both "-Xcheck:jni" and "-Xjnitrace:" are enabled, we print trace messages
128a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  // when a native method that matches the -Xjnitrace argument calls a JNI function
129a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  // such as NewByteArray.
130a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  // If -verbose:third-party-jni is on, we want to log any JNI function calls
131a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  // made by a third-party native method.
132bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier  std::string class_name(method->GetDeclaringClassDescriptor());
13381ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  if (!vm->trace.empty() && class_name.find(vm->trace) != std::string::npos) {
134a09576416788b916095739e43a16917e7948f3a4Elliott Hughes    return true;
135a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  }
1364dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  if (VLOG_IS_ON(third_party_jni)) {
137a09576416788b916095739e43a16917e7948f3a4Elliott Hughes    // Return true if we're trying to log all third-party JNI activity and 'method' doesn't look
138a09576416788b916095739e43a16917e7948f3a4Elliott Hughes    // like part of Android.
139ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    for (size_t i = 0; gBuiltInPrefixes[i] != nullptr; ++i) {
14081ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes      if (StartsWith(class_name, gBuiltInPrefixes[i])) {
141a09576416788b916095739e43a16917e7948f3a4Elliott Hughes        return false;
142a09576416788b916095739e43a16917e7948f3a4Elliott Hughes      }
143a09576416788b916095739e43a16917e7948f3a4Elliott Hughes    }
144a09576416788b916095739e43a16917e7948f3a4Elliott Hughes    return true;
145a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  }
146a09576416788b916095739e43a16917e7948f3a4Elliott Hughes  return false;
147a09576416788b916095739e43a16917e7948f3a4Elliott Hughes}
148a09576416788b916095739e43a16917e7948f3a4Elliott Hughes
149a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesclass ScopedCheck {
150ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes public:
151a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  // For JNIEnv* functions.
15200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  explicit ScopedCheck(JNIEnv* env, int flags, const char* functionName)
153b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
15400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      : soa_(env) {
155365c10235438607541fa2259a5fec48061b90bd8Ian Rogers    Init(flags, functionName, true);
15632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    CheckThread(flags);
157a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
158a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
159a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  // For JavaVM* functions.
16000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // TODO: it's not correct that this is a lock function, but making it so aids annotalysis.
16100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  explicit ScopedCheck(JavaVM* vm, bool has_method, const char* functionName)
162b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
16300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      : soa_(vm) {
164365c10235438607541fa2259a5fec48061b90bd8Ian Rogers    Init(kFlag_Invocation, functionName, has_method);
165a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
166a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
167b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers  ~ScopedCheck() UNLOCK_FUNCTION(Locks::mutator_lock_) {}
16800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
16900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  const ScopedObjectAccess& soa() {
17000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return soa_;
17100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
17200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
17332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  bool ForceCopy() {
174a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return Runtime::Current()->GetJavaVM()->force_copy;
175a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
176a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
17781ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
17881ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
17981ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
18081ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // circumstances, but this is incorrect.
18181ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  void CheckClassName(const char* class_name) {
1822d10b206f9d0b97396b7dadb9a6415cd39efd341Ian Rogers    if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
1833f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_,
1843f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                "illegal class name '%s'\n"
1853f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                "    (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
1863f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                class_name);
187a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
188a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
189a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
190a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
191a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that the field is of the appropriate type.  If the field has an
192a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * object type, "java_object" is the object we're trying to assign into it.
193a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
194a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Works for both static and instance fields.
195a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
196ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  void CheckFieldType(jvalue value, jfieldID fid, char prim, bool isStatic)
197b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
19861c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier    StackHandleScope<1> hs(Thread::Current());
19961c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier    Handle<mirror::ArtField> f(hs.NewHandle(CheckFieldID(fid)));
20061c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier    if (f.Get() == nullptr) {
201a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      return;
202a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
2032dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Class* field_type = FieldHelper(f).GetType();
2040cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    if (!field_type->IsPrimitive()) {
205ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      jobject java_object = value.l;
206ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      if (java_object != nullptr) {
2072dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers        mirror::Object* obj = soa_.Decode<mirror::Object*>(java_object);
2083f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes        // If java_object is a weak global ref whose referent has been cleared,
2093f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes        // obj will be NULL.  Otherwise, obj should always be non-NULL
2103f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes        // and valid.
211590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier        if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) {
212b76cac637691c29daa9c44e493b5bc26346ed116Mathieu Chartier          Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
2133f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes          JniAbortF(function_name_, "field operation on invalid %s: %p",
2143f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                    ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
215a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          return;
2160cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers        } else {
217161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom          if (!obj->InstanceOf(field_type)) {
2183f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes            JniAbortF(function_name_, "attempt to set field %s with value of wrong type: %s",
21961c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier                      PrettyField(f.Get()).c_str(), PrettyTypeOf(obj).c_str());
2200cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers            return;
2210cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers          }
2220cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers        }
223a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
2240cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    } else if (field_type != Runtime::Current()->GetClassLinker()->FindPrimitiveClass(prim)) {
2253f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "attempt to set field %s with value of wrong type: %c",
22661c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier                PrettyField(f.Get()).c_str(), prim);
227a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      return;
2280cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    }
2290cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers
23061c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier    if (isStatic != f.Get()->IsStatic()) {
231a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      if (isStatic) {
23261c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier        JniAbortF(function_name_, "accessing non-static field %s as static",
23361c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier                  PrettyField(f.Get()).c_str());
234a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      } else {
23561c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier        JniAbortF(function_name_, "accessing static field %s as non-static",
23661c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier                  PrettyField(f.Get()).c_str());
237a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
238a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      return;
239a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
240a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
241a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
242a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
243a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that this instance field ID is valid for this object.
244a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
245a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Assumes "jobj" has already been validated.
246a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
24700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void CheckInstanceFieldID(jobject java_object, jfieldID fid)
248b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2492dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
250ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (o == nullptr || !Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
251b76cac637691c29daa9c44e493b5bc26346ed116Mathieu Chartier      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
2523f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "field operation on invalid %s: %p",
2533f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
254a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      return;
255a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
256a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
257ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    mirror::ArtField* f = CheckFieldID(fid);
258ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (f == nullptr) {
25932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes      return;
26032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
2612dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Class* c = o->GetClass();
26261c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier    if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
2633f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "jfieldID %s not valid for an object of class %s",
2643f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                PrettyField(f).c_str(), PrettyTypeOf(o).c_str());
265a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
266a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
267a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
268a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
269a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that the pointer value is non-NULL.
270a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
27132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  void CheckNonNull(const void* ptr) {
272ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (ptr == nullptr) {
2733f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "non-nullable argument was NULL");
274a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
275a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
276a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
277a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
278a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that the method's return type matches the type of call.
279a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * 'expectedType' will be "L" for all objects, including arrays.
280a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
28100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void CheckSig(jmethodID mid, const char* expectedType, bool isStatic)
282b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
283ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    mirror::ArtMethod* m = CheckMethodID(mid);
284ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (m == nullptr) {
28532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes      return;
28632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
287bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier    if (*expectedType != m->GetShorty()[0]) {
2883f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "the return type of %s does not match %s",
2893f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                function_name_, PrettyMethod(m).c_str());
2903f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    }
2913f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    if (isStatic != m->IsStatic()) {
292a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      if (isStatic) {
2933f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes        JniAbortF(function_name_, "calling non-static method %s with %s",
2943f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                  PrettyMethod(m).c_str(), function_name_);
295a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      } else {
2963f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes        JniAbortF(function_name_, "calling static method %s with %s",
2973f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                  PrettyMethod(m).c_str(), function_name_);
298a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
299a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
300a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
301a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
302a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
303a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that this static field ID is valid for this class.
304a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
305a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Assumes "java_class" has already been validated.
306a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
30700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void CheckStaticFieldID(jclass java_class, jfieldID fid)
308b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
3092dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Class* c = soa_.Decode<mirror::Class*>(java_class);
310ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    mirror::ArtField* f = CheckFieldID(fid);
311ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (f == nullptr) {
31232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes      return;
31332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
314a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    if (f->GetDeclaringClass() != c) {
3153f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "static jfieldID %p not valid for class %s",
3163f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                fid, PrettyClass(c).c_str());
317a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
318a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
319a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
320a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
321e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes   * Verify that "mid" is appropriate for "java_class".
322a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
323a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * A mismatch isn't dangerous, because the jmethodID defines the class.  In
324e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes   * fact, java_class is unused in the implementation.  It's best if we don't
325a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * allow bad code in the system though.
326a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
327e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes   * Instances of "java_class" must be instances of the method's declaring class.
328a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
32900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void CheckStaticMethod(jclass java_class, jmethodID mid)
330b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
331ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    mirror::ArtMethod* m = CheckMethodID(mid);
332ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (m == nullptr) {
33332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes      return;
33432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
3352dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Class* c = soa_.Decode<mirror::Class*>(java_class);
33667fe2b41a6afccf6ab1a58879eae3e0e8f3d6c7aBrian Carlstrom    if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
3373f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "can't call static %s on class %s",
3383f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                PrettyMethod(m).c_str(), PrettyClass(c).c_str());
339a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
340a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
341a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
342a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
343a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that "mid" is appropriate for "jobj".
344a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
345a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Make sure the object is an instance of the method's declaring class.
346a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * (Note the mid might point to a declaration in an interface; this
347a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * will be handled automatically by the instanceof check.)
348a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
34900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void CheckVirtualMethod(jobject java_object, jmethodID mid)
350b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
351ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    mirror::ArtMethod* m = CheckMethodID(mid);
352ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (m == nullptr) {
35332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes      return;
35432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
3552dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
356167350d9c781c5e3893714bb26ab5cb1c4abf6b4Mathieu Chartier    if (o == nullptr) {
357167350d9c781c5e3893714bb26ab5cb1c4abf6b4Mathieu Chartier      JniAbortF(function_name_, "can't call %s on null object", PrettyMethod(m).c_str());
358167350d9c781c5e3893714bb26ab5cb1c4abf6b4Mathieu Chartier    } else if (!o->InstanceOf(m->GetDeclaringClass())) {
3593f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "can't call %s on instance of %s",
3603f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
361a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
362a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
363a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
364a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /**
365a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * The format string is a sequence of the following characters,
366a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * and must be followed by arguments of the corresponding types
367a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * in the same order.
368a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
369a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Java primitive types:
370a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * B - jbyte
371a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * C - jchar
372a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * D - jdouble
373a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * F - jfloat
374a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * I - jint
375a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * J - jlong
376a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * S - jshort
377a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Z - jboolean (shown as true and false)
378a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * V - void
379a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
380a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Java reference types:
381a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * L - jobject
382a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * a - jarray
383a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * c - jclass
384a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * s - jstring
385a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
386a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * JNI types:
387a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
388a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * f - jfieldID
389a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * m - jmethodID
390a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * p - void*
391a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * r - jint (for release mode arguments)
39278090d119d5e23ff35ecddac1f4a98e4c050bb07Elliott Hughes   * u - const char* (Modified UTF-8)
393a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * z - jsize (for lengths; use i if negative values are okay)
394a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * v - JavaVM*
395a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * E - JNIEnv*
396a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * . - no argument; just print "..." (used for varargs JNI calls)
397a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
398a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
399a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
400df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  void Check(bool entry, const char* fmt0, ...) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
401a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    va_list ap;
402a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
403ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    mirror::ArtMethod* traceMethod = nullptr;
4049365f5890eb27e1c98038ecf5a7fa2cad0aa62e6Ian Rogers    if (has_method_ && (!soa_.Vm()->trace.empty() || VLOG_IS_ON(third_party_jni))) {
405a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      // We need to guard some of the invocation interface's calls: a bad caller might
406a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
407a09576416788b916095739e43a16917e7948f3a4Elliott Hughes      Thread* self = Thread::Current();
408ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
409ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        traceMethod = self->GetCurrentMethod(nullptr);
410a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
411a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
412a09576416788b916095739e43a16917e7948f3a4Elliott Hughes
413ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (((flags_ & kFlag_ForceTrace) != 0) ||
414ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        (traceMethod != nullptr && ShouldTrace(soa_.Vm(), traceMethod))) {
415a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      va_start(ap, fmt0);
416a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      std::string msg;
417a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      for (const char* fmt = fmt0; *fmt;) {
418a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        char ch = *fmt++;
4197934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        if (ch == 'B') {  // jbyte
420a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          jbyte b = va_arg(ap, int);
421a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          if (b >= 0 && b < 10) {
422a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            StringAppendF(&msg, "%d", b);
423a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          } else {
424a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            StringAppendF(&msg, "%#x (%d)", b, b);
425a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          }
4267934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        } else if (ch == 'C') {  // jchar
427a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          jchar c = va_arg(ap, int);
428a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          if (c < 0x7f && c >= ' ') {
429a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            StringAppendF(&msg, "U+%x ('%c')", c, c);
430a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          } else {
431a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            StringAppendF(&msg, "U+%x", c);
432a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          }
4337934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        } else if (ch == 'F' || ch == 'D') {  // jfloat, jdouble
434a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          StringAppendF(&msg, "%g", va_arg(ap, double));
4357934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        } else if (ch == 'I' || ch == 'S') {  // jint, jshort
436a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          StringAppendF(&msg, "%d", va_arg(ap, int));
4377934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        } else if (ch == 'J') {  // jlong
438ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          StringAppendF(&msg, "%" PRId64, va_arg(ap, jlong));
4397934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        } else if (ch == 'Z') {  // jboolean
440a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          StringAppendF(&msg, "%s", va_arg(ap, int) ? "true" : "false");
4417934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        } else if (ch == 'V') {  // void
442a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          msg += "void";
4437934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        } else if (ch == 'v') {  // JavaVM*
444a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          JavaVM* vm = va_arg(ap, JavaVM*);
445a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          StringAppendF(&msg, "(JavaVM*)%p", vm);
4467934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        } else if (ch == 'E') {  // JNIEnv*
447a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          JNIEnv* env = va_arg(ap, JNIEnv*);
448a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          StringAppendF(&msg, "(JNIEnv*)%p", env);
4497934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        } else if (ch == 'L' || ch == 'a' || ch == 's') {  // jobject, jarray, jstring
450a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          // For logging purposes, these are identical.
451a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          jobject o = va_arg(ap, jobject);
452ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          if (o == nullptr) {
453a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            msg += "NULL";
454a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          } else {
455a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            StringAppendF(&msg, "%p", o);
456a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          }
4577934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        } else if (ch == 'b') {  // jboolean (JNI-style)
458a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          jboolean b = va_arg(ap, int);
459a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          msg += (b ? "JNI_TRUE" : "JNI_FALSE");
4607934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        } else if (ch == 'c') {  // jclass
461a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          jclass jc = va_arg(ap, jclass);
4622dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers          mirror::Class* c = reinterpret_cast<mirror::Class*>(Thread::Current()->DecodeJObject(jc));
463ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          if (c == nullptr) {
464a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            msg += "NULL";
465590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier          } else if (c == kInvalidIndirectRefObject ||
466590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier              !Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) {
467485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes            StringAppendF(&msg, "INVALID POINTER:%p", jc);
468485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes          } else if (!c->IsClass()) {
469485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes            msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c);
470a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          } else {
47154e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes            msg += PrettyClass(c);
472a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            if (!entry) {
473a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes              StringAppendF(&msg, " (%p)", jc);
474a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            }
475a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          }
4767934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        } else if (ch == 'f') {  // jfieldID
477a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          jfieldID fid = va_arg(ap, jfieldID);
478ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom          mirror::ArtField* f = reinterpret_cast<mirror::ArtField*>(fid);
479a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          msg += PrettyField(f);
480a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          if (!entry) {
481a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            StringAppendF(&msg, " (%p)", fid);
482a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          }
4837934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        } else if (ch == 'z') {  // non-negative jsize
484a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          // You might expect jsize to be size_t, but it's not; it's the same as jint.
485a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          // We only treat this specially so we can do the non-negative check.
486a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          // TODO: maybe this wasn't worth it?
487a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          jint i = va_arg(ap, jint);
488a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          StringAppendF(&msg, "%d", i);
4897934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        } else if (ch == 'm') {  // jmethodID
490a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          jmethodID mid = va_arg(ap, jmethodID);
491ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom          mirror::ArtMethod* m = reinterpret_cast<mirror::ArtMethod*>(mid);
492a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          msg += PrettyMethod(m);
493a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          if (!entry) {
494a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            StringAppendF(&msg, " (%p)", mid);
495a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          }
4967934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        } else if (ch == 'p') {  // void* ("pointer")
497a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          void* p = va_arg(ap, void*);
498ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          if (p == nullptr) {
499a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            msg += "NULL";
500a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          } else {
501a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            StringAppendF(&msg, "(void*) %p", p);
502a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          }
5037934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        } else if (ch == 'r') {  // jint (release mode)
504a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          jint releaseMode = va_arg(ap, jint);
505a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          if (releaseMode == 0) {
506a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            msg += "0";
507a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          } else if (releaseMode == JNI_ABORT) {
508a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            msg += "JNI_ABORT";
509a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          } else if (releaseMode == JNI_COMMIT) {
510a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            msg += "JNI_COMMIT";
511a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          } else {
512a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            StringAppendF(&msg, "invalid release mode %d", releaseMode);
513a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          }
5147934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom        } else if (ch == 'u') {  // const char* (Modified UTF-8)
515a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          const char* utf = va_arg(ap, const char*);
516ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          if (utf == nullptr) {
517a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            msg += "NULL";
518a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          } else {
519a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes            StringAppendF(&msg, "\"%s\"", utf);
520a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          }
521a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else if (ch == '.') {
522a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          msg += "...";
523a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else {
5243f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes          JniAbortF(function_name_, "unknown trace format specifier: %c", ch);
525a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          return;
526a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
527a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        if (*fmt) {
528a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          StringAppendF(&msg, ", ");
529a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
530a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
531a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      va_end(ap);
532a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
533485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes      if ((flags_ & kFlag_ForceTrace) != 0) {
534485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes        LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
535485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes      } else if (entry) {
53632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        if (has_method_) {
537a09576416788b916095739e43a16917e7948f3a4Elliott Hughes          std::string methodName(PrettyMethod(traceMethod, false));
53832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
53932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          indent_ = methodName.size() + 1;
540a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else {
54132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
54232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          indent_ = 0;
543a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
544a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      } else {
54532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
546a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
547a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
548a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
549a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // We always do the thorough checks on entry, and never on exit...
550a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    if (entry) {
551a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      va_start(ap, fmt0);
552a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      for (const char* fmt = fmt0; *fmt; ++fmt) {
553a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        char ch = *fmt;
554a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        if (ch == 'a') {
55532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          CheckArray(va_arg(ap, jarray));
556a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else if (ch == 'c') {
55732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          CheckInstance(kClass, va_arg(ap, jclass));
558a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else if (ch == 'L') {
55932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          CheckObject(va_arg(ap, jobject));
560a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else if (ch == 'r') {
56132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          CheckReleaseMode(va_arg(ap, jint));
562a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else if (ch == 's') {
56332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          CheckInstance(kString, va_arg(ap, jstring));
564a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else if (ch == 'u') {
56532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          if ((flags_ & kFlag_Release) != 0) {
56632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes            CheckNonNull(va_arg(ap, const char*));
567a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          } else {
56832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes            bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
56932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes            CheckUtfString(va_arg(ap, const char*), nullable);
570a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          }
571a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else if (ch == 'z') {
57232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          CheckLengthPositive(va_arg(ap, jsize));
573ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        } else if (strchr("BCISZbfmpEv", ch) != nullptr) {
5747934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom          va_arg(ap, uint32_t);  // Skip this argument.
575a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else if (ch == 'D' || ch == 'F') {
5767934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom          va_arg(ap, double);  // Skip this argument.
577a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else if (ch == 'J') {
5787934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom          va_arg(ap, uint64_t);  // Skip this argument.
579a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else if (ch == '.') {
580a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else {
5813d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes          LOG(FATAL) << "Unknown check format specifier: " << ch;
582a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
583a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
584a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      va_end(ap);
585a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
586a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
587a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
588a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes  enum InstanceKind {
589a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    kClass,
5900f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes    kDirectByteBuffer,
5910f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes    kObject,
5920f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes    kString,
5930f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes    kThrowable,
594a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes  };
595a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
596a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes  /*
597a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   * Verify that "jobj" is a valid non-NULL object reference, and points to
598a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   * an instance of expectedClass.
599a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   *
600a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   * Because we're looking at an object on the GC heap, we have to switch
601a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   * to "running" mode before doing the checks.
602a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   */
60300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  bool CheckInstance(InstanceKind kind, jobject java_object)
604b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
605ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const char* what = nullptr;
606a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    switch (kind) {
607a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kClass:
608a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "jclass";
609a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
610a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kDirectByteBuffer:
611a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "direct ByteBuffer";
612a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
613a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kObject:
614a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "jobject";
615a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
616a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kString:
617a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "jstring";
618a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
619a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kThrowable:
620a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "jthrowable";
621a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
622a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    default:
6237b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes      LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
624a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
625a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
626ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (java_object == nullptr) {
6273f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "%s received null %s", function_name_, what);
628a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      return false;
629a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
630a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
6312dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Object* obj = soa_.Decode<mirror::Object*>(java_object);
632590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) {
633b76cac637691c29daa9c44e493b5bc26346ed116Mathieu Chartier      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
6343f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "%s is an invalid %s: %p (%p)",
6353f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object, obj);
636a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      return false;
637a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
638a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
639a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    bool okay = true;
640a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    switch (kind) {
641a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kClass:
642a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      okay = obj->IsClass();
643a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
644a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kDirectByteBuffer:
645a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      UNIMPLEMENTED(FATAL);
646a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
647a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kString:
648a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      okay = obj->GetClass()->IsStringClass();
649a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
650a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kThrowable:
651a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      okay = obj->GetClass()->IsThrowableClass();
652a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
653a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kObject:
654a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
655a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
656a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    if (!okay) {
6573f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "%s has wrong type: %s", what, PrettyTypeOf(obj).c_str());
658a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      return false;
659a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
660a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
661a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    return true;
662a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes  }
663a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
664ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes private:
66581ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // Set "has_method" to true if we have a valid thread with a method pointer.
66681ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // We won't have one before attaching a thread, after detaching a thread, or
66781ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // when shutting down the runtime.
668365c10235438607541fa2259a5fec48061b90bd8Ian Rogers  void Init(int flags, const char* functionName, bool has_method) {
66932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    flags_ = flags;
67032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    function_name_ = functionName;
67181ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes    has_method_ = has_method;
672a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
673a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
674a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
675a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that "array" is non-NULL and points to an Array object.
676a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
677a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Since we're dealing with objects, switch to "running" mode.
678a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
679b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers  void CheckArray(jarray java_array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
680ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (java_array == nullptr) {
6813f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "jarray was NULL");
682a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      return;
683a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
684a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
6852dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Array* a = soa_.Decode<mirror::Array*>(java_array);
686590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(a)) {
687b76cac637691c29daa9c44e493b5bc26346ed116Mathieu Chartier      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
6883f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "jarray is an invalid %s: %p (%p)",
6893f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(), java_array, a);
690a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    } else if (!a->IsArrayInstance()) {
6913f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "jarray argument has non-array type: %s", PrettyTypeOf(a).c_str());
692a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
693a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
694a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
69532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  void CheckLengthPositive(jsize length) {
696a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    if (length < 0) {
6973f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "negative jsize: %d", length);
698a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
699a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
700a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
701ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  mirror::ArtField* CheckFieldID(jfieldID fid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
702ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (fid == nullptr) {
7033f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "jfieldID was NULL");
704ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      return nullptr;
70532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
706ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    mirror::ArtField* f = soa_.DecodeField(fid);
707590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f) || !f->IsArtField()) {
708b76cac637691c29daa9c44e493b5bc26346ed116Mathieu Chartier      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
7093f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "invalid jfieldID: %p", fid);
710ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      return nullptr;
71132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
71232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    return f;
71332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  }
71432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes
715ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  mirror::ArtMethod* CheckMethodID(jmethodID mid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
716ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (mid == nullptr) {
7173f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "jmethodID was NULL");
718ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      return nullptr;
71932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
720ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    mirror::ArtMethod* m = soa_.DecodeMethod(mid);
721590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m) || !m->IsArtMethod()) {
722b76cac637691c29daa9c44e493b5bc26346ed116Mathieu Chartier      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
7233f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "invalid jmethodID: %p", mid);
724ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      return nullptr;
72532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
72632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    return m;
72732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  }
72832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes
729a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
730a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that "jobj" is a valid object, and that it's an object that JNI
731a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * is allowed to know about.  We allow NULL references.
732a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
733a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Switches to "running" mode before performing checks.
734a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
73500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void CheckObject(jobject java_object)
736b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
737ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (java_object == nullptr) {
738a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      return;
739a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
740a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
7412dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
742590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
743b76cac637691c29daa9c44e493b5bc26346ed116Mathieu Chartier      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
744c5bfa8f49d8548d7c685a99b411311ef56bedffaElliott Hughes      // TODO: when we remove work_around_app_jni_bugs, this should be impossible.
7453f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "native code passing in reference to invalid %s: %p",
7463f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
747a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
748a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
749a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
750a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
751a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that the "mode" argument passed to a primitive array Release
752a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * function is one of the valid values.
753a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
75432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  void CheckReleaseMode(jint mode) {
755a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
75696a9887f0bc912661e0a7478c7eb19847d2e2e06Elliott Hughes      JniAbortF(function_name_, "unknown value for release mode: %d", mode);
757a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
758a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
759a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
760b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers  void CheckThread(int flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
761a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    Thread* self = Thread::Current();
762ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (self == nullptr) {
7633f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_, "a thread (tid %d) is making JNI calls without being attached", GetTid());
764a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      return;
765a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
766a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
767a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // Get the *correct* JNIEnv by going through our TLS pointer.
768a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    JNIEnvExt* threadEnv = self->GetJniEnv();
769a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
7703f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Verify that the current thread is (a) attached and (b) associated with
7713f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // this particular instance of JNIEnv.
77200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    if (soa_.Env() != threadEnv) {
773987560fee798e48fb725c44b796d8ca7a5872ad6Ian Rogers      JniAbortF(function_name_, "thread %s using JNIEnv* from thread %s",
774987560fee798e48fb725c44b796d8ca7a5872ad6Ian Rogers                ToStr<Thread>(*self).c_str(), ToStr<Thread>(*soa_.Self()).c_str());
775987560fee798e48fb725c44b796d8ca7a5872ad6Ian Rogers      return;
776a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
777a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
7783f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Verify that, if this thread previously made a critical "get" call, we
7793f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // do the corresponding "release" call before we try anything else.
780a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    switch (flags & kFlag_CritMask) {
781a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    case kFlag_CritOkay:    // okay to call this method
782a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      break;
783a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    case kFlag_CritBad:     // not okay to call
784a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      if (threadEnv->critical) {
7853f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes        JniAbortF(function_name_, "thread %s using JNI after critical get", ToStr<Thread>(*self).c_str());
786a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        return;
787a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
788a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      break;
789a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    case kFlag_CritGet:     // this is a "get" call
7903f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      // Don't check here; we allow nested gets.
791a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      threadEnv->critical++;
792a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      break;
7937934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    case kFlag_CritRelease:  // this is a "release" call
794a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      threadEnv->critical--;
795a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      if (threadEnv->critical < 0) {
7963f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes        JniAbortF(function_name_, "thread %s called too many critical releases", ToStr<Thread>(*self).c_str());
797a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        return;
798a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
799a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      break;
800a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    default:
8013d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes      LOG(FATAL) << "Bad flags (internal error): " << flags;
802a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
803a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
8043f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Verify that, if an exception has been raised, the native code doesn't
8053f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // make any JNI calls other than the Exception* methods.
806a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    if ((flags & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
80762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ThrowLocation throw_location;
80862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      mirror::Throwable* exception = self->GetException(&throw_location);
80962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      std::string type(PrettyTypeOf(exception));
8108e4d3ed463df1a9f5fdc1e927a6afe6d208558e1Elliott Hughes      JniAbortF(function_name_, "JNI %s called with pending exception '%s' thrown in %s",
8118e4d3ed463df1a9f5fdc1e927a6afe6d208558e1Elliott Hughes                function_name_, type.c_str(), throw_location.Dump().c_str());
812a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      return;
813a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
814a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
815a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
8163f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes  // Verifies that "bytes" points to valid Modified UTF-8 data.
81732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  void CheckUtfString(const char* bytes, bool nullable) {
818ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (bytes == nullptr) {
819a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      if (!nullable) {
8203f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes        JniAbortF(function_name_, "non-nullable const char* was NULL");
821a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        return;
822a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
823a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      return;
824a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
825a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
826ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const char* errorKind = nullptr;
82732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    uint8_t utf8 = CheckUtfBytes(bytes, &errorKind);
828ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (errorKind != nullptr) {
8293f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(function_name_,
8303f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                "input is not valid Modified UTF-8: illegal %s byte %#x\n"
8313f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                "    string: '%s'", errorKind, utf8, bytes);
832a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      return;
833a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
834a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
835a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
83632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  static uint8_t CheckUtfBytes(const char* bytes, const char** errorKind) {
837a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    while (*bytes != '\0') {
838a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      uint8_t utf8 = *(bytes++);
839a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      // Switch on the high four bits.
840a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      switch (utf8 >> 4) {
841a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x00:
842a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x01:
843a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x02:
844a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x03:
845a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x04:
846a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x05:
847a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x06:
848a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x07:
849a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        // Bit pattern 0xxx. No need for any extra bytes.
850a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        break;
851a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x08:
852a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x09:
853a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0a:
854a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0b:
855a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0f:
856a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        /*
857a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes         * Bit pattern 10xx or 1111, which are illegal start bytes.
858a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes         * Note: 1111 is valid for normal UTF-8, but not the
85978090d119d5e23ff35ecddac1f4a98e4c050bb07Elliott Hughes         * Modified UTF-8 used here.
860a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes         */
861a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        *errorKind = "start";
862a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        return utf8;
863a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0e:
864a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        // Bit pattern 1110, so there are two additional bytes.
865a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        utf8 = *(bytes++);
866a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        if ((utf8 & 0xc0) != 0x80) {
867a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          *errorKind = "continuation";
868a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          return utf8;
869a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
870a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        // Fall through to take care of the final byte.
871a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0c:
872a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0d:
873a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        // Bit pattern 110x, so there is one additional byte.
874a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        utf8 = *(bytes++);
875a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        if ((utf8 & 0xc0) != 0x80) {
876a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          *errorKind = "continuation";
877a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          return utf8;
878a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
879a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        break;
880a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
881a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
882a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return 0;
883a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
884a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
88500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  const ScopedObjectAccess soa_;
88632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  const char* function_name_;
88732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  int flags_;
88832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  bool has_method_;
88992cb498ffd2185fc8f8da7cd25fe485d0e7e3355Elliott Hughes  int indent_;
890a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
891a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
892a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
893a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
894a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define CHECK_JNI_ENTRY(flags, types, args...) \
895a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  ScopedCheck sc(env, flags, __FUNCTION__); \
89632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  sc.Check(true, types, ##args)
897a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
898a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define CHECK_JNI_EXIT(type, exp) ({ \
8999b3c3cdb62f7142384e6bf2c0cb6e3a76b16f0e3Mathieu Chartier    auto _rc = (exp); \
90032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  sc.Check(false, type, _rc); \
901a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  _rc; })
902a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define CHECK_JNI_EXIT_VOID() \
90332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  sc.Check(false, "V")
904a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
905a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/*
906a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
907a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *      Guarded arrays
908a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
909a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */
910a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
911a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define kGuardLen       512         /* must be multiple of 2 */
912a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define kGuardPattern   0xd5e3      /* uncommon values; d5e3d5e3 invalid addr */
913a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define kGuardMagic     0xffd5aa96
914a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
915a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/* this gets tucked in at the start of the buffer; struct size must be even */
916a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesstruct GuardedCopy {
917a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  uint32_t magic;
918a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  uLong adler;
91932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  size_t original_length;
92032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  const void* original_ptr;
921a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
922a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /* find the GuardedCopy given the pointer into the "live" data */
92332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  static inline const GuardedCopy* FromData(const void* dataBuf) {
92432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    return reinterpret_cast<const GuardedCopy*>(ActualBuffer(dataBuf));
925a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
926a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
927a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
928a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Create an over-sized buffer to hold the contents of "buf".  Copy it in,
929a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * filling in the area around it with guard data.
930a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
931a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * We use a 16-bit pattern to make a rogue memset less likely to elude us.
932a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
93332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  static void* Create(const void* buf, size_t len, bool modOkay) {
93432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    size_t newLen = ActualLength(len);
93532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    uint8_t* newBuf = DebugAlloc(newLen);
936a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
9373f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Fill it in with a pattern.
938ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes    uint16_t* pat = reinterpret_cast<uint16_t*>(newBuf);
939a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    for (size_t i = 0; i < newLen / 2; i++) {
940a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      *pat++ = kGuardPattern;
941a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
942a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
9433f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Copy the data in; note "len" could be zero.
944a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    memcpy(newBuf + kGuardLen / 2, buf, len);
945a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
9463f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // If modification is not expected, grab a checksum.
947a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    uLong adler = 0;
948a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    if (!modOkay) {
949a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      adler = adler32(0L, Z_NULL, 0);
950ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes      adler = adler32(adler, reinterpret_cast<const Bytef*>(buf), len);
951ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes      *reinterpret_cast<uLong*>(newBuf) = adler;
952a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
953a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
954a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    GuardedCopy* pExtra = reinterpret_cast<GuardedCopy*>(newBuf);
955a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    pExtra->magic = kGuardMagic;
956a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    pExtra->adler = adler;
95732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    pExtra->original_ptr = buf;
95832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    pExtra->original_length = len;
959a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
960a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return newBuf + kGuardLen / 2;
961a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
962a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
963a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
964a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Free up the guard buffer, scrub it, and return the original pointer.
965a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
96632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  static void* Destroy(void* dataBuf) {
96732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    const GuardedCopy* pExtra = GuardedCopy::FromData(dataBuf);
968ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes    void* original_ptr = const_cast<void*>(pExtra->original_ptr);
96932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    size_t len = pExtra->original_length;
97032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    DebugFree(dataBuf, len);
97132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    return original_ptr;
972a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
973a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
974a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
975a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify the guard area and, if "modOkay" is false, that the data itself
976a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * has not been altered.
977a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
978a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * The caller has already checked that "dataBuf" is non-NULL.
979a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
98032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  static void Check(const char* functionName, const void* dataBuf, bool modOkay) {
981a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    static const uint32_t kMagicCmp = kGuardMagic;
98232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    const uint8_t* fullBuf = ActualBuffer(dataBuf);
98332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    const GuardedCopy* pExtra = GuardedCopy::FromData(dataBuf);
984a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
9853f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Before we do anything with "pExtra", check the magic number.  We
9863f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // do the check with memcmp rather than "==" in case the pointer is
9873f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // unaligned.  If it points to completely bogus memory we're going
9883f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // to crash, but there's no easy way around that.
989a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) {
990a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      uint8_t buf[4];
991a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      memcpy(buf, &pExtra->magic, 4);
9923f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(functionName,
9933f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes          "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
9947934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom          buf[3], buf[2], buf[1], buf[0], dataBuf);  // Assumes little-endian.
995a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
996a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
99732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    size_t len = pExtra->original_length;
998a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
9993f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Check bottom half of guard; skip over optional checksum storage.
1000ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes    const uint16_t* pat = reinterpret_cast<const uint16_t*>(fullBuf);
1001a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    for (size_t i = sizeof(GuardedCopy) / 2; i < (kGuardLen / 2 - sizeof(GuardedCopy)) / 2; i++) {
1002a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      if (pat[i] != kGuardPattern) {
1003ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        JniAbortF(functionName, "guard pattern(1) disturbed at %p +%zd", fullBuf, i*2);
1004a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1005a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1006a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1007a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    int offset = kGuardLen / 2 + len;
1008a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    if (offset & 0x01) {
10093f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      // Odd byte; expected value depends on endian.
1010a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      const uint16_t patSample = kGuardPattern;
10113f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      uint8_t expected_byte = reinterpret_cast<const uint8_t*>(&patSample)[1];
10123f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      if (fullBuf[offset] != expected_byte) {
10133f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes        JniAbortF(functionName, "guard pattern disturbed in odd byte after %p +%d 0x%02x 0x%02x",
10143f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                  fullBuf, offset, fullBuf[offset], expected_byte);
1015a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1016a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      offset++;
1017a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1018a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
10193f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Check top half of guard.
1020ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes    pat = reinterpret_cast<const uint16_t*>(fullBuf + offset);
1021a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    for (size_t i = 0; i < kGuardLen / 4; i++) {
1022a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      if (pat[i] != kGuardPattern) {
1023ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        JniAbortF(functionName, "guard pattern(2) disturbed at %p +%zd", fullBuf, offset + i*2);
1024a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1025a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1026a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
10273f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // If modification is not expected, verify checksum.  Strictly speaking
10283f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // this is wrong: if we told the client that we made a copy, there's no
10293f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // reason they can't alter the buffer.
1030a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    if (!modOkay) {
1031a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      uLong adler = adler32(0L, Z_NULL, 0);
1032a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      adler = adler32(adler, (const Bytef*)dataBuf, len);
1033a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      if (pExtra->adler != adler) {
10343f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes        JniAbortF(functionName, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
10353f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                  pExtra->adler, adler, dataBuf);
1036a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1037a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1038a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1039a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1040a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes private:
104132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  static uint8_t* DebugAlloc(size_t len) {
1042ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
1043a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    if (result == MAP_FAILED) {
1044a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1045a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1046a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return reinterpret_cast<uint8_t*>(result);
1047a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1048a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
104932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  static void DebugFree(void* dataBuf, size_t len) {
105032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    uint8_t* fullBuf = ActualBuffer(dataBuf);
105132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    size_t totalByteCount = ActualLength(len);
1052a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // TODO: we could mprotect instead, and keep the allocation around for a while.
1053a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // This would be even more expensive, but it might catch more errors.
1054a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // if (mprotect(fullBuf, totalByteCount, PROT_NONE) != 0) {
10557b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes    //     PLOG(WARNING) << "mprotect(PROT_NONE) failed";
1056a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // }
1057a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    if (munmap(fullBuf, totalByteCount) != 0) {
1058ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes      PLOG(FATAL) << "munmap(" << reinterpret_cast<void*>(fullBuf) << ", " << totalByteCount << ") failed";
1059a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1060a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1061a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
106232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  static const uint8_t* ActualBuffer(const void* dataBuf) {
1063a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return reinterpret_cast<const uint8_t*>(dataBuf) - kGuardLen / 2;
1064a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1065a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
106632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  static uint8_t* ActualBuffer(void* dataBuf) {
1067a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return reinterpret_cast<uint8_t*>(dataBuf) - kGuardLen / 2;
1068a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1069a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1070a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  // Underlying length of a user allocation of 'length' bytes.
107132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  static size_t ActualLength(size_t length) {
1072a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return (length + kGuardLen + 1) & ~0x01;
1073a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1074a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
1075a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1076a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/*
1077a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Create a guarded copy of a primitive array.  Modifications to the copied
1078a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * data are allowed.  Returns a pointer to the copied data.
1079a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */
10803f6635a2c84d645002f651c312d53f8348646c1fElliott Hughesstatic void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* isCopy) {
108100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(env);
1082a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
10832dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1084a15e67d5ee5aa9615596cee2be42c2b2caf128c6Ian Rogers  size_t component_size = a->GetClass()->GetComponentSize();
1085a15e67d5ee5aa9615596cee2be42c2b2caf128c6Ian Rogers  size_t byte_count = a->GetLength() * component_size;
1086ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  void* result = GuardedCopy::Create(a->GetRawData(component_size, 0), byte_count, true);
1087ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  if (isCopy != nullptr) {
1088a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    *isCopy = JNI_TRUE;
1089a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1090a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  return result;
1091a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}
1092a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1093a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/*
1094a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Perform the array "release" operation, which may or may not copy data
109581ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes * back into the managed heap, and may or may not release the underlying storage.
1096a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */
10973f6635a2c84d645002f651c312d53f8348646c1fElliott Hughesstatic void ReleaseGuardedPACopy(JNIEnv* env, jarray java_array, void* dataBuf, int mode) {
109800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(env);
10992dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1100a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
110132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  GuardedCopy::Check(__FUNCTION__, dataBuf, true);
1102a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1103a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  if (mode != JNI_ABORT) {
110432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    size_t len = GuardedCopy::FromData(dataBuf)->original_length;
1105ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    memcpy(a->GetRawData(a->GetClass()->GetComponentSize(), 0), dataBuf, len);
1106a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1107a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  if (mode != JNI_COMMIT) {
110832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    GuardedCopy::Destroy(dataBuf);
1109a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1110a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}
1111a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1112a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/*
1113a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
1114a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *      JNI functions
1115a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
1116a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */
1117a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1118a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesclass CheckJNI {
1119a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes public:
1120a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint GetVersion(JNIEnv* env) {
1121a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "E", env);
1122a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("I", baseEnv(env)->GetVersion(env));
1123a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1124a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1125a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf, jsize bufLen) {
1126a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "EuLpz", env, name, loader, buf, bufLen);
112732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    sc.CheckClassName(name);
1128a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("c", baseEnv(env)->DefineClass(env, name, loader, buf, bufLen));
1129a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1130a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1131a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jclass FindClass(JNIEnv* env, const char* name) {
1132a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "Eu", env, name);
113332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    sc.CheckClassName(name);
1134a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("c", baseEnv(env)->FindClass(env, name));
1135a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1136a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1137e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jclass GetSuperclass(JNIEnv* env, jclass c) {
1138e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c);
1139e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    return CHECK_JNI_EXIT("c", baseEnv(env)->GetSuperclass(env, c));
1140a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1141a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1142e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
1143e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "Ecc", env, c1, c2);
1144e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    return CHECK_JNI_EXIT("b", baseEnv(env)->IsAssignableFrom(env, c1, c2));
1145a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1146a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1147a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
1148a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "EL", env, method);
1149a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // TODO: check that 'field' is a java.lang.reflect.Method.
1150a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("m", baseEnv(env)->FromReflectedMethod(env, method));
1151a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1152a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1153a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
1154a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "EL", env, field);
1155a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // TODO: check that 'field' is a java.lang.reflect.Field.
1156a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("f", baseEnv(env)->FromReflectedField(env, field));
1157a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1158a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1159a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
1160a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "Ecmb", env, cls, mid, isStatic);
1161a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("L", baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic));
1162a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1163a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1164a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
1165a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "Ecfb", env, cls, fid, isStatic);
1166a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("L", baseEnv(env)->ToReflectedField(env, cls, fid, isStatic));
1167a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1168a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1169a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint Throw(JNIEnv* env, jthrowable obj) {
1170a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1171a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // TODO: check that 'obj' is a java.lang.Throwable.
1172a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("I", baseEnv(env)->Throw(env, obj));
1173a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1174a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1175e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
1176e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    CHECK_JNI_ENTRY(kFlag_NullableUtf, "Ecu", env, c, message);
1177e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    return CHECK_JNI_EXIT("I", baseEnv(env)->ThrowNew(env, c, message));
1178a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1179a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1180a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jthrowable ExceptionOccurred(JNIEnv* env) {
1181a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1182a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("L", baseEnv(env)->ExceptionOccurred(env));
1183a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1184a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1185a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void ExceptionDescribe(JNIEnv* env) {
1186a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1187a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    baseEnv(env)->ExceptionDescribe(env);
1188a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_EXIT_VOID();
1189a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1190a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1191a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void ExceptionClear(JNIEnv* env) {
1192a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1193a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    baseEnv(env)->ExceptionClear(env);
1194a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_EXIT_VOID();
1195a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1196a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1197a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void FatalError(JNIEnv* env, const char* msg) {
1198c4378df76edd637273813fef4da7f01c4e637defElliott Hughes    // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1199c4378df76edd637273813fef4da7f01c4e637defElliott Hughes    // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1200c4378df76edd637273813fef4da7f01c4e637defElliott Hughes    // and it's not unimaginable that you don't know that you do. So we allow it.
1201c4378df76edd637273813fef4da7f01c4e637defElliott Hughes    CHECK_JNI_ENTRY(kFlag_ExcepOkay | kFlag_NullableUtf, "Eu", env, msg);
1202a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    baseEnv(env)->FatalError(env, msg);
1203a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_EXIT_VOID();
1204a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1205a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1206a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint PushLocalFrame(JNIEnv* env, jint capacity) {
1207a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EI", env, capacity);
1208a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("I", baseEnv(env)->PushLocalFrame(env, capacity));
1209a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1210a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1211a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject PopLocalFrame(JNIEnv* env, jobject res) {
1212a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, res);
1213a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("L", baseEnv(env)->PopLocalFrame(env, res));
1214a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1215a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1216a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
1217a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1218a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("L", baseEnv(env)->NewGlobalRef(env, obj));
1219a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1220a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1221a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject NewLocalRef(JNIEnv* env, jobject ref) {
1222a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "EL", env, ref);
1223a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("L", baseEnv(env)->NewLocalRef(env, ref));
1224a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1225a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1226a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void DeleteGlobalRef(JNIEnv* env, jobject globalRef) {
1227a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, globalRef);
1228ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (globalRef != nullptr && GetIndirectRefKind(globalRef) != kGlobal) {
12293f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(__FUNCTION__, "DeleteGlobalRef on %s: %p",
12303f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                ToStr<IndirectRefKind>(GetIndirectRefKind(globalRef)).c_str(), globalRef);
1231a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    } else {
1232a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      baseEnv(env)->DeleteGlobalRef(env, globalRef);
1233a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      CHECK_JNI_EXIT_VOID();
1234a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1235a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1236a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1237a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void DeleteWeakGlobalRef(JNIEnv* env, jweak weakGlobalRef) {
1238a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, weakGlobalRef);
1239ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (weakGlobalRef != nullptr && GetIndirectRefKind(weakGlobalRef) != kWeakGlobal) {
12403f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(__FUNCTION__, "DeleteWeakGlobalRef on %s: %p",
12413f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                ToStr<IndirectRefKind>(GetIndirectRefKind(weakGlobalRef)).c_str(), weakGlobalRef);
1242a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    } else {
1243a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      baseEnv(env)->DeleteWeakGlobalRef(env, weakGlobalRef);
1244a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      CHECK_JNI_EXIT_VOID();
1245a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1246a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1247a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1248a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void DeleteLocalRef(JNIEnv* env, jobject localRef) {
1249a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, localRef);
1250eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    if (localRef != nullptr && GetIndirectRefKind(localRef) != kLocal && !IsHandleScopeLocalRef(env, localRef)) {
12513f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(__FUNCTION__, "DeleteLocalRef on %s: %p",
12523f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes                ToStr<IndirectRefKind>(GetIndirectRefKind(localRef)).c_str(), localRef);
1253a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    } else {
1254a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      baseEnv(env)->DeleteLocalRef(env, localRef);
1255a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      CHECK_JNI_EXIT_VOID();
1256a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1257a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1258a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1259a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1260a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "EI", env, capacity);
1261a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("I", baseEnv(env)->EnsureLocalCapacity(env, capacity));
1262a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1263a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1264a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1265a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "ELL", env, ref1, ref2);
1266a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("b", baseEnv(env)->IsSameObject(env, ref1, ref2));
1267a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1268a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1269e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jobject AllocObject(JNIEnv* env, jclass c) {
1270e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c);
1271e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    return CHECK_JNI_EXIT("L", baseEnv(env)->AllocObject(env, c));
1272a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1273a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1274e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
1275e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid);
1276a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    va_list args;
1277a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    va_start(args, mid);
1278e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    jobject result = baseEnv(env)->NewObjectV(env, c, mid, args);
1279a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    va_end(args);
1280a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("L", result);
1281a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1282a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1283e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list args) {
1284e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid);
1285e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    return CHECK_JNI_EXIT("L", baseEnv(env)->NewObjectV(env, c, mid, args));
1286a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1287a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1288e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* args) {
1289e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid);
1290e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    return CHECK_JNI_EXIT("L", baseEnv(env)->NewObjectA(env, c, mid, args));
1291a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1292a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1293a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jclass GetObjectClass(JNIEnv* env, jobject obj) {
1294a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1295a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("c", baseEnv(env)->GetObjectClass(env, obj));
1296a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1297a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1298e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
1299e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "ELc", env, obj, c);
1300e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    return CHECK_JNI_EXIT("b", baseEnv(env)->IsInstanceOf(env, obj, c));
1301a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1302a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1303e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1304e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1305e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    return CHECK_JNI_EXIT("m", baseEnv(env)->GetMethodID(env, c, name, sig));
1306a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1307a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1308e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1309e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1310e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    return CHECK_JNI_EXIT("f", baseEnv(env)->GetFieldID(env, c, name, sig));
1311a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1312a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1313e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1314e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1315e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    return CHECK_JNI_EXIT("m", baseEnv(env)->GetStaticMethodID(env, c, name, sig));
1316a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1317a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1318e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1319e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1320e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    return CHECK_JNI_EXIT("f", baseEnv(env)->GetStaticFieldID(env, c, name, sig));
1321a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1322a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1323ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#define FIELD_ACCESSORS(_ctype, _jname, _jvalue_type, _type) \
1324e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    static _ctype GetStatic##_jname##Field(JNIEnv* env, jclass c, jfieldID fid) { \
1325e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        CHECK_JNI_ENTRY(kFlag_Default, "Ecf", env, c, fid); \
1326e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        sc.CheckStaticFieldID(c, fid); \
1327e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        return CHECK_JNI_EXIT(_type, baseEnv(env)->GetStatic##_jname##Field(env, c, fid)); \
1328a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    } \
1329a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    static _ctype Get##_jname##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
1330a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        CHECK_JNI_ENTRY(kFlag_Default, "ELf", env, obj, fid); \
133132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        sc.CheckInstanceFieldID(obj, fid); \
1332a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        return CHECK_JNI_EXIT(_type, baseEnv(env)->Get##_jname##Field(env, obj, fid)); \
1333a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    } \
1334e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    static void SetStatic##_jname##Field(JNIEnv* env, jclass c, jfieldID fid, _ctype value) { \
1335e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        CHECK_JNI_ENTRY(kFlag_Default, "Ecf" _type, env, c, fid, value); \
1336e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        sc.CheckStaticFieldID(c, fid); \
1337a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        /* "value" arg only used when type == ref */ \
1338ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        jvalue java_type_value; \
1339ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        java_type_value._jvalue_type = value; \
1340ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        sc.CheckFieldType(java_type_value, fid, _type[0], true); \
1341e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        baseEnv(env)->SetStatic##_jname##Field(env, c, fid, value); \
1342a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        CHECK_JNI_EXIT_VOID(); \
1343a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    } \
1344a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    static void Set##_jname##Field(JNIEnv* env, jobject obj, jfieldID fid, _ctype value) { \
1345a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        CHECK_JNI_ENTRY(kFlag_Default, "ELf" _type, env, obj, fid, value); \
134632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        sc.CheckInstanceFieldID(obj, fid); \
1347a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        /* "value" arg only used when type == ref */ \
1348ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        jvalue java_type_value; \
1349ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        java_type_value._jvalue_type = value; \
1350ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        sc.CheckFieldType(java_type_value, fid, _type[0], false); \
1351a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        baseEnv(env)->Set##_jname##Field(env, obj, fid, value); \
1352a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        CHECK_JNI_EXIT_VOID(); \
1353a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1354a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1355ef7d42fca18c16fbaf103822ad16f23246e2905dIan RogersFIELD_ACCESSORS(jobject, Object, l, "L");
1356ef7d42fca18c16fbaf103822ad16f23246e2905dIan RogersFIELD_ACCESSORS(jboolean, Boolean, z, "Z");
1357ef7d42fca18c16fbaf103822ad16f23246e2905dIan RogersFIELD_ACCESSORS(jbyte, Byte, b, "B");
1358ef7d42fca18c16fbaf103822ad16f23246e2905dIan RogersFIELD_ACCESSORS(jchar, Char, c, "C");
1359ef7d42fca18c16fbaf103822ad16f23246e2905dIan RogersFIELD_ACCESSORS(jshort, Short, s, "S");
1360ef7d42fca18c16fbaf103822ad16f23246e2905dIan RogersFIELD_ACCESSORS(jint, Int, i, "I");
1361ef7d42fca18c16fbaf103822ad16f23246e2905dIan RogersFIELD_ACCESSORS(jlong, Long, j, "J");
1362ef7d42fca18c16fbaf103822ad16f23246e2905dIan RogersFIELD_ACCESSORS(jfloat, Float, f, "F");
1363ef7d42fca18c16fbaf103822ad16f23246e2905dIan RogersFIELD_ACCESSORS(jdouble, Double, d, "D");
1364a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1365a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define CALL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
1366a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    /* Virtual... */ \
1367a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    static _ctype Call##_jname##Method(JNIEnv* env, jobject obj, \
1368a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        jmethodID mid, ...) \
1369a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    { \
1370a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
137132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        sc.CheckSig(mid, _retsig, false); \
137232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        sc.CheckVirtualMethod(obj, mid); \
1373a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        _retdecl; \
1374a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        va_list args; \
1375a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        va_start(args, mid); \
1376ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes        _retasgn(baseEnv(env)->Call##_jname##MethodV(env, obj, mid, args)); \
1377a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        va_end(args); \
1378a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        _retok; \
1379a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    } \
1380a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    static _ctype Call##_jname##MethodV(JNIEnv* env, jobject obj, \
1381a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        jmethodID mid, va_list args) \
1382a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    { \
1383a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
138432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        sc.CheckSig(mid, _retsig, false); \
138532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        sc.CheckVirtualMethod(obj, mid); \
1386a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        _retdecl; \
1387ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes        _retasgn(baseEnv(env)->Call##_jname##MethodV(env, obj, mid, args)); \
1388a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        _retok; \
1389a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    } \
1390a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    static _ctype Call##_jname##MethodA(JNIEnv* env, jobject obj, \
1391a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        jmethodID mid, jvalue* args) \
1392a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    { \
1393a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
139432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        sc.CheckSig(mid, _retsig, false); \
139532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        sc.CheckVirtualMethod(obj, mid); \
1396a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        _retdecl; \
1397ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes        _retasgn(baseEnv(env)->Call##_jname##MethodA(env, obj, mid, args)); \
1398a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        _retok; \
1399a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    } \
1400a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    /* Non-virtual... */ \
1401a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    static _ctype CallNonvirtual##_jname##Method(JNIEnv* env, \
1402e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        jobject obj, jclass c, jmethodID mid, ...) \
1403a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    { \
1404e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \
140532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        sc.CheckSig(mid, _retsig, false); \
140632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        sc.CheckVirtualMethod(obj, mid); \
1407a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        _retdecl; \
1408a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        va_list args; \
1409a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        va_start(args, mid); \
1410e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, c, mid, args)); \
1411a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        va_end(args); \
1412a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        _retok; \
1413a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    } \
1414a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    static _ctype CallNonvirtual##_jname##MethodV(JNIEnv* env, \
1415e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        jobject obj, jclass c, jmethodID mid, va_list args) \
1416a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    { \
1417e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \
141832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        sc.CheckSig(mid, _retsig, false); \
141932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        sc.CheckVirtualMethod(obj, mid); \
1420a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        _retdecl; \
1421e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, c, mid, args)); \
1422a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        _retok; \
1423a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    } \
1424a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    static _ctype CallNonvirtual##_jname##MethodA(JNIEnv* env, \
1425e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        jobject obj, jclass c, jmethodID mid, jvalue* args) \
1426a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    { \
1427e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \
142832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        sc.CheckSig(mid, _retsig, false); \
142932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        sc.CheckVirtualMethod(obj, mid); \
1430a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        _retdecl; \
1431e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodA(env, obj, c, mid, args)); \
1432a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        _retok; \
1433a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    } \
1434a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    /* Static... */ \
1435e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    static _ctype CallStatic##_jname##Method(JNIEnv* env, jclass c, jmethodID mid, ...) \
1436a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    { \
1437e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \
143832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        sc.CheckSig(mid, _retsig, true); \
1439e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        sc.CheckStaticMethod(c, mid); \
1440a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        _retdecl; \
1441a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        va_list args; \
1442a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        va_start(args, mid); \
1443e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        _retasgn(baseEnv(env)->CallStatic##_jname##MethodV(env, c, mid, args)); \
1444a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        va_end(args); \
1445a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        _retok; \
1446a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    } \
1447e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    static _ctype CallStatic##_jname##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list args) \
1448a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    { \
1449e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \
145032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        sc.CheckSig(mid, _retsig, true); \
1451e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        sc.CheckStaticMethod(c, mid); \
1452a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        _retdecl; \
1453e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes         _retasgn(baseEnv(env)->CallStatic##_jname##MethodV(env, c, mid, args)); \
1454a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        _retok; \
1455a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    } \
1456e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    static _ctype CallStatic##_jname##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* args) \
1457a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    { \
1458e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \
145932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        sc.CheckSig(mid, _retsig, true); \
1460e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        sc.CheckStaticMethod(c, mid); \
1461a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        _retdecl; \
1462e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes        _retasgn(baseEnv(env)->CallStatic##_jname##MethodA(env, c, mid, args)); \
1463a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        _retok; \
1464a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1465a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1466a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define NON_VOID_RETURN(_retsig, _ctype) return CHECK_JNI_EXIT(_retsig, (_ctype) result)
1467a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define VOID_RETURN CHECK_JNI_EXIT_VOID()
1468a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
14692dd0e2cea360bc9206eb88ecc40d259e796c239dIan RogersCALL(jobject, Object, mirror::Object* result, result = reinterpret_cast<mirror::Object*>, NON_VOID_RETURN("L", jobject), "L");
1470ba8eee10607a524f43b55a6f33c13924fb16d435Elliott HughesCALL(jboolean, Boolean, jboolean result, result =, NON_VOID_RETURN("Z", jboolean), "Z");
1471ba8eee10607a524f43b55a6f33c13924fb16d435Elliott HughesCALL(jbyte, Byte, jbyte result, result =, NON_VOID_RETURN("B", jbyte), "B");
1472ba8eee10607a524f43b55a6f33c13924fb16d435Elliott HughesCALL(jchar, Char, jchar result, result =, NON_VOID_RETURN("C", jchar), "C");
1473ba8eee10607a524f43b55a6f33c13924fb16d435Elliott HughesCALL(jshort, Short, jshort result, result =, NON_VOID_RETURN("S", jshort), "S");
1474ba8eee10607a524f43b55a6f33c13924fb16d435Elliott HughesCALL(jint, Int, jint result, result =, NON_VOID_RETURN("I", jint), "I");
1475ba8eee10607a524f43b55a6f33c13924fb16d435Elliott HughesCALL(jlong, Long, jlong result, result =, NON_VOID_RETURN("J", jlong), "J");
1476ba8eee10607a524f43b55a6f33c13924fb16d435Elliott HughesCALL(jfloat, Float, jfloat result, result =, NON_VOID_RETURN("F", jfloat), "F");
1477ba8eee10607a524f43b55a6f33c13924fb16d435Elliott HughesCALL(jdouble, Double, jdouble result, result =, NON_VOID_RETURN("D", jdouble), "D");
1478a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesCALL(void, Void, , , VOID_RETURN, "V");
1479a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1480a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jstring NewString(JNIEnv* env, const jchar* unicodeChars, jsize len) {
1481a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "Epz", env, unicodeChars, len);
1482a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("s", baseEnv(env)->NewString(env, unicodeChars, len));
1483a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1484a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1485a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jsize GetStringLength(JNIEnv* env, jstring string) {
1486a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_CritOkay, "Es", env, string);
1487a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("I", baseEnv(env)->GetStringLength(env, string));
1488a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1489a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1490a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static const jchar* GetStringChars(JNIEnv* env, jstring java_string, jboolean* isCopy) {
1491a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, java_string, isCopy);
1492a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    const jchar* result = baseEnv(env)->GetStringChars(env, java_string, isCopy);
1493ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (sc.ForceCopy() && result != nullptr) {
14942dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::String* s = sc.soa().Decode<mirror::String*>(java_string);
1495a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      int byteCount = s->GetLength() * 2;
149632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes      result = (const jchar*) GuardedCopy::Create(result, byteCount, false);
1497ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      if (isCopy != nullptr) {
1498a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        *isCopy = JNI_TRUE;
1499a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1500a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1501a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("p", result);
1502a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1503a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1504a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
1505a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "Esp", env, string, chars);
150632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    sc.CheckNonNull(chars);
150732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    if (sc.ForceCopy()) {
150832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes      GuardedCopy::Check(__FUNCTION__, chars, false);
1509ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes      chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<jchar*>(chars)));
1510a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1511a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    baseEnv(env)->ReleaseStringChars(env, string, chars);
1512a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_EXIT_VOID();
1513a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1514a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1515a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jstring NewStringUTF(JNIEnv* env, const char* bytes) {
15167934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    CHECK_JNI_ENTRY(kFlag_NullableUtf, "Eu", env, bytes);  // TODO: show pointer and truncate string.
1517a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("s", baseEnv(env)->NewStringUTF(env, bytes));
1518a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1519a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1520a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
1521a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_CritOkay, "Es", env, string);
1522a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("I", baseEnv(env)->GetStringUTFLength(env, string));
1523a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1524a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1525a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* isCopy) {
1526a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, string, isCopy);
1527a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    const char* result = baseEnv(env)->GetStringUTFChars(env, string, isCopy);
1528ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (sc.ForceCopy() && result != nullptr) {
152932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes      result = (const char*) GuardedCopy::Create(result, strlen(result) + 1, false);
1530ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      if (isCopy != nullptr) {
1531a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        *isCopy = JNI_TRUE;
1532a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1533a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
15347934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    return CHECK_JNI_EXIT("u", result);  // TODO: show pointer and truncate string.
1535a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1536a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1537a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
15387934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    CHECK_JNI_ENTRY(kFlag_ExcepOkay | kFlag_Release, "Esu", env, string, utf);  // TODO: show pointer and truncate string.
153932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    if (sc.ForceCopy()) {
154032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes      GuardedCopy::Check(__FUNCTION__, utf, false);
1541ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes      utf = reinterpret_cast<const char*>(GuardedCopy::Destroy(const_cast<char*>(utf)));
1542a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1543a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    baseEnv(env)->ReleaseStringUTFChars(env, string, utf);
1544a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_EXIT_VOID();
1545a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1546a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1547a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jsize GetArrayLength(JNIEnv* env, jarray array) {
1548a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_CritOkay, "Ea", env, array);
1549a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("I", baseEnv(env)->GetArrayLength(env, array));
1550a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1551a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1552a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass elementClass, jobject initialElement) {
1553a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "EzcL", env, length, elementClass, initialElement);
1554a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("a", baseEnv(env)->NewObjectArray(env, length, elementClass, initialElement));
1555a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1556a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1557a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
1558a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "EaI", env, array, index);
1559a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("L", baseEnv(env)->GetObjectArrayElement(env, array, index));
1560a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1561a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1562a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
1563a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "EaIL", env, array, index, value);
1564a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    baseEnv(env)->SetObjectArrayElement(env, array, index, value);
1565a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_EXIT_VOID();
1566a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1567a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1568a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define NEW_PRIMITIVE_ARRAY(_artype, _jname) \
1569a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    static _artype New##_jname##Array(JNIEnv* env, jsize length) { \
1570a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        CHECK_JNI_ENTRY(kFlag_Default, "Ez", env, length); \
1571a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        return CHECK_JNI_EXIT("a", baseEnv(env)->New##_jname##Array(env, length)); \
1572a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1573a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesNEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
1574a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesNEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
1575a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesNEW_PRIMITIVE_ARRAY(jcharArray, Char);
1576a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesNEW_PRIMITIVE_ARRAY(jshortArray, Short);
1577a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesNEW_PRIMITIVE_ARRAY(jintArray, Int);
1578a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesNEW_PRIMITIVE_ARRAY(jlongArray, Long);
1579a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesNEW_PRIMITIVE_ARRAY(jfloatArray, Float);
1580a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesNEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
1581a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
158232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughesstruct ForceCopyGetChecker {
1583ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes public:
1584a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  ForceCopyGetChecker(ScopedCheck& sc, jboolean* isCopy) {
158532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    force_copy = sc.ForceCopy();
158632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    no_copy = 0;
1587ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (force_copy && isCopy != nullptr) {
15883f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      // Capture this before the base call tramples on it.
1589ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes      no_copy = *reinterpret_cast<uint32_t*>(isCopy);
1590a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1591a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1592a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1593a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  template<typename ResultT>
159432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  ResultT Check(JNIEnv* env, jarray array, jboolean* isCopy, ResultT result) {
1595ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (force_copy && result != nullptr) {
159677129ff50fc0234b62684e556d2c0bcb86123e80Mathieu Chartier      result = reinterpret_cast<ResultT>(CreateGuardedPACopy(env, array, isCopy));
1597a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1598a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return result;
1599a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1600a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
160132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  uint32_t no_copy;
160232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  bool force_copy;
1603a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
1604a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1605a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1606a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static _ctype* Get##_jname##ArrayElements(JNIEnv* env, _ctype##Array array, jboolean* isCopy) { \
1607a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "Eap", env, array, isCopy); \
160832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    _ctype* result = ForceCopyGetChecker(sc, isCopy).Check(env, array, isCopy, baseEnv(env)->Get##_jname##ArrayElements(env, array, isCopy)); \
1609a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("p", result); \
1610a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1611a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1612a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1613a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void Release##_jname##ArrayElements(JNIEnv* env, _ctype##Array array, _ctype* elems, jint mode) { \
1614a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "Eapr", env, array, elems, mode); \
161532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    sc.CheckNonNull(elems); \
161632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    if (sc.ForceCopy()) { \
1617a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      ReleaseGuardedPACopy(env, array, elems, mode); \
1618a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    } \
1619a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    baseEnv(env)->Release##_jname##ArrayElements(env, array, elems, mode); \
1620a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_EXIT_VOID(); \
1621a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1622a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1623a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1624a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    static void Get##_jname##ArrayRegion(JNIEnv* env, _ctype##Array array, jsize start, jsize len, _ctype* buf) { \
1625a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        CHECK_JNI_ENTRY(kFlag_Default, "EaIIp", env, array, start, len, buf); \
1626a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        baseEnv(env)->Get##_jname##ArrayRegion(env, array, start, len, buf); \
1627a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        CHECK_JNI_EXIT_VOID(); \
1628a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1629a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1630a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1631a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    static void Set##_jname##ArrayRegion(JNIEnv* env, _ctype##Array array, jsize start, jsize len, const _ctype* buf) { \
1632a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        CHECK_JNI_ENTRY(kFlag_Default, "EaIIp", env, array, start, len, buf); \
1633a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        baseEnv(env)->Set##_jname##ArrayRegion(env, array, start, len, buf); \
1634a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        CHECK_JNI_EXIT_VOID(); \
1635a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1636a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1637a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar) \
1638a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1639a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1640a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); \
1641a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
1642a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
16433f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes// TODO: verify primitive array type matches call type.
1644a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesPRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
1645a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesPRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
1646a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesPRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
1647a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesPRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
1648a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesPRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
1649a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesPRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
1650a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesPRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
1651a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesPRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
1652a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1653e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1654e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "EcpI", env, c, methods, nMethods);
1655e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    return CHECK_JNI_EXIT("I", baseEnv(env)->RegisterNatives(env, c, methods, nMethods));
1656a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1657a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1658e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jint UnregisterNatives(JNIEnv* env, jclass c) {
1659e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c);
1660e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes    return CHECK_JNI_EXIT("I", baseEnv(env)->UnregisterNatives(env, c));
1661a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1662a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1663a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint MonitorEnter(JNIEnv* env, jobject obj) {
1664a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1665a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    if (!sc.CheckInstance(ScopedCheck::kObject, obj)) {
16667934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom      return JNI_ERR;  // Only for jni_internal_test. Real code will have aborted already.
1667a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
1668a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("I", baseEnv(env)->MonitorEnter(env, obj));
1669a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1670a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1671a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint MonitorExit(JNIEnv* env, jobject obj) {
1672a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, obj);
1673a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    if (!sc.CheckInstance(ScopedCheck::kObject, obj)) {
16747934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom      return JNI_ERR;  // Only for jni_internal_test. Real code will have aborted already.
1675a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
1676a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("I", baseEnv(env)->MonitorExit(env, obj));
1677a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1678a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1679a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1680a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "Ep", env, vm);
1681a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("I", baseEnv(env)->GetJavaVM(env, vm));
1682a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1683a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1684a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar* buf) {
1685a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_CritOkay, "EsIIp", env, str, start, len, buf);
1686a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    baseEnv(env)->GetStringRegion(env, str, start, len, buf);
1687a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_EXIT_VOID();
1688a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1689a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1690a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char* buf) {
1691a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_CritOkay, "EsIIp", env, str, start, len, buf);
1692a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    baseEnv(env)->GetStringUTFRegion(env, str, start, len, buf);
1693a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_EXIT_VOID();
1694a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1695a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1696a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* isCopy) {
1697a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_CritGet, "Eap", env, array, isCopy);
1698a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    void* result = baseEnv(env)->GetPrimitiveArrayCritical(env, array, isCopy);
1699ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (sc.ForceCopy() && result != nullptr) {
1700a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      result = CreateGuardedPACopy(env, array, isCopy);
1701a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1702a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("p", result);
1703a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1704a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1705a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
1706a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_CritRelease | kFlag_ExcepOkay, "Eapr", env, array, carray, mode);
170732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    sc.CheckNonNull(carray);
170832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    if (sc.ForceCopy()) {
1709a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      ReleaseGuardedPACopy(env, array, carray, mode);
1710a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1711a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
1712a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_EXIT_VOID();
1713a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1714a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1715a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static const jchar* GetStringCritical(JNIEnv* env, jstring java_string, jboolean* isCopy) {
1716a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_CritGet, "Esp", env, java_string, isCopy);
1717a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    const jchar* result = baseEnv(env)->GetStringCritical(env, java_string, isCopy);
1718ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (sc.ForceCopy() && result != nullptr) {
17192dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::String* s = sc.soa().Decode<mirror::String*>(java_string);
1720a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      int byteCount = s->GetLength() * 2;
172132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes      result = (const jchar*) GuardedCopy::Create(result, byteCount, false);
1722ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      if (isCopy != nullptr) {
1723a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        *isCopy = JNI_TRUE;
1724a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1725a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1726a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("p", result);
1727a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1728a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1729a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* carray) {
1730a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_CritRelease | kFlag_ExcepOkay, "Esp", env, string, carray);
173132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    sc.CheckNonNull(carray);
173232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    if (sc.ForceCopy()) {
173332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes      GuardedCopy::Check(__FUNCTION__, carray, false);
1734ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes      carray = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<jchar*>(carray)));
1735a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1736a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    baseEnv(env)->ReleaseStringCritical(env, string, carray);
1737a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_EXIT_VOID();
1738a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1739a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1740a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
1741a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1742a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("L", baseEnv(env)->NewWeakGlobalRef(env, obj));
1743a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1744a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1745a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jboolean ExceptionCheck(JNIEnv* env) {
1746a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_CritOkay | kFlag_ExcepOkay, "E", env);
1747a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("b", baseEnv(env)->ExceptionCheck(env));
1748a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1749a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1750a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
1751a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // Note: we use "Ep" rather than "EL" because this is the one JNI function
1752a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // that it's okay to pass an invalid reference to.
1753a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "Ep", env, obj);
1754a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // TODO: proper decoding of jobjectRefType!
1755a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("I", baseEnv(env)->GetObjectRefType(env, obj));
1756a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1757a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1758a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
1759a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "EpJ", env, address, capacity);
1760ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (address == nullptr) {
17613f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      JniAbortF(__FUNCTION__, "non-nullable address is NULL");
176245d26c86b00580593067ca42091ad66cf7dc4f7cBrian Carlstrom      return nullptr;
1763a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1764a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("L", baseEnv(env)->NewDirectByteBuffer(env, address, capacity));
1765a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1766a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1767a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
1768a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "EL", env, buf);
1769a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // TODO: check that 'buf' is a java.nio.Buffer.
1770a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("p", baseEnv(env)->GetDirectBufferAddress(env, buf));
1771a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1772a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1773a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
1774a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    CHECK_JNI_ENTRY(kFlag_Default, "EL", env, buf);
1775a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // TODO: check that 'buf' is a java.nio.Buffer.
1776a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return CHECK_JNI_EXIT("J", baseEnv(env)->GetDirectBufferCapacity(env, buf));
1777a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1778a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1779a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes private:
1780a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static inline const JNINativeInterface* baseEnv(JNIEnv* env) {
1781a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
1782a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1783a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
1784a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1785a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNINativeInterface gCheckNativeInterface = {
1786ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved0.
1787ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved1.
1788ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved2.
1789ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved3.
1790a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetVersion,
1791a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::DefineClass,
1792a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::FindClass,
1793a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::FromReflectedMethod,
1794a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::FromReflectedField,
1795a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ToReflectedMethod,
1796a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetSuperclass,
1797a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::IsAssignableFrom,
1798a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ToReflectedField,
1799a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::Throw,
1800a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ThrowNew,
1801a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ExceptionOccurred,
1802a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ExceptionDescribe,
1803a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ExceptionClear,
1804a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::FatalError,
1805a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::PushLocalFrame,
1806a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::PopLocalFrame,
1807a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewGlobalRef,
1808a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::DeleteGlobalRef,
1809a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::DeleteLocalRef,
1810a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::IsSameObject,
1811a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewLocalRef,
1812a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::EnsureLocalCapacity,
1813a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::AllocObject,
1814a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewObject,
1815a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewObjectV,
1816a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewObjectA,
1817a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetObjectClass,
1818a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::IsInstanceOf,
1819a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetMethodID,
1820a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallObjectMethod,
1821a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallObjectMethodV,
1822a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallObjectMethodA,
1823a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallBooleanMethod,
1824a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallBooleanMethodV,
1825a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallBooleanMethodA,
1826a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallByteMethod,
1827a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallByteMethodV,
1828a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallByteMethodA,
1829a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallCharMethod,
1830a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallCharMethodV,
1831a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallCharMethodA,
1832a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallShortMethod,
1833a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallShortMethodV,
1834a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallShortMethodA,
1835a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallIntMethod,
1836a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallIntMethodV,
1837a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallIntMethodA,
1838a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallLongMethod,
1839a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallLongMethodV,
1840a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallLongMethodA,
1841a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallFloatMethod,
1842a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallFloatMethodV,
1843a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallFloatMethodA,
1844a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallDoubleMethod,
1845a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallDoubleMethodV,
1846a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallDoubleMethodA,
1847a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallVoidMethod,
1848a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallVoidMethodV,
1849a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallVoidMethodA,
1850a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualObjectMethod,
1851a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualObjectMethodV,
1852a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualObjectMethodA,
1853a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualBooleanMethod,
1854a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualBooleanMethodV,
1855a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualBooleanMethodA,
1856a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualByteMethod,
1857a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualByteMethodV,
1858a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualByteMethodA,
1859a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualCharMethod,
1860a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualCharMethodV,
1861a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualCharMethodA,
1862a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualShortMethod,
1863a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualShortMethodV,
1864a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualShortMethodA,
1865a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualIntMethod,
1866a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualIntMethodV,
1867a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualIntMethodA,
1868a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualLongMethod,
1869a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualLongMethodV,
1870a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualLongMethodA,
1871a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualFloatMethod,
1872a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualFloatMethodV,
1873a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualFloatMethodA,
1874a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualDoubleMethod,
1875a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualDoubleMethodV,
1876a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualDoubleMethodA,
1877a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualVoidMethod,
1878a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualVoidMethodV,
1879a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualVoidMethodA,
1880a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetFieldID,
1881a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetObjectField,
1882a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetBooleanField,
1883a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetByteField,
1884a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetCharField,
1885a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetShortField,
1886a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetIntField,
1887a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetLongField,
1888a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetFloatField,
1889a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDoubleField,
1890a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetObjectField,
1891a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetBooleanField,
1892a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetByteField,
1893a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetCharField,
1894a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetShortField,
1895a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetIntField,
1896a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetLongField,
1897a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetFloatField,
1898a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetDoubleField,
1899a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticMethodID,
1900a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticObjectMethod,
1901a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticObjectMethodV,
1902a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticObjectMethodA,
1903a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticBooleanMethod,
1904a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticBooleanMethodV,
1905a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticBooleanMethodA,
1906a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticByteMethod,
1907a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticByteMethodV,
1908a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticByteMethodA,
1909a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticCharMethod,
1910a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticCharMethodV,
1911a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticCharMethodA,
1912a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticShortMethod,
1913a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticShortMethodV,
1914a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticShortMethodA,
1915a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticIntMethod,
1916a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticIntMethodV,
1917a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticIntMethodA,
1918a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticLongMethod,
1919a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticLongMethodV,
1920a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticLongMethodA,
1921a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticFloatMethod,
1922a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticFloatMethodV,
1923a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticFloatMethodA,
1924a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticDoubleMethod,
1925a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticDoubleMethodV,
1926a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticDoubleMethodA,
1927a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticVoidMethod,
1928a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticVoidMethodV,
1929a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticVoidMethodA,
1930a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticFieldID,
1931a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticObjectField,
1932a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticBooleanField,
1933a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticByteField,
1934a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticCharField,
1935a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticShortField,
1936a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticIntField,
1937a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticLongField,
1938a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticFloatField,
1939a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticDoubleField,
1940a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticObjectField,
1941a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticBooleanField,
1942a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticByteField,
1943a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticCharField,
1944a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticShortField,
1945a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticIntField,
1946a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticLongField,
1947a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticFloatField,
1948a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticDoubleField,
1949a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewString,
1950a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringLength,
1951a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringChars,
1952a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseStringChars,
1953a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewStringUTF,
1954a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringUTFLength,
1955a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringUTFChars,
1956a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseStringUTFChars,
1957a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetArrayLength,
1958a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewObjectArray,
1959a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetObjectArrayElement,
1960a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetObjectArrayElement,
1961a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewBooleanArray,
1962a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewByteArray,
1963a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewCharArray,
1964a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewShortArray,
1965a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewIntArray,
1966a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewLongArray,
1967a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewFloatArray,
1968a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewDoubleArray,
1969a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetBooleanArrayElements,
1970a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetByteArrayElements,
1971a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetCharArrayElements,
1972a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetShortArrayElements,
1973a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetIntArrayElements,
1974a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetLongArrayElements,
1975a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetFloatArrayElements,
1976a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDoubleArrayElements,
1977a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseBooleanArrayElements,
1978a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseByteArrayElements,
1979a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseCharArrayElements,
1980a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseShortArrayElements,
1981a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseIntArrayElements,
1982a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseLongArrayElements,
1983a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseFloatArrayElements,
1984a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseDoubleArrayElements,
1985a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetBooleanArrayRegion,
1986a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetByteArrayRegion,
1987a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetCharArrayRegion,
1988a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetShortArrayRegion,
1989a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetIntArrayRegion,
1990a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetLongArrayRegion,
1991a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetFloatArrayRegion,
1992a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDoubleArrayRegion,
1993a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetBooleanArrayRegion,
1994a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetByteArrayRegion,
1995a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetCharArrayRegion,
1996a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetShortArrayRegion,
1997a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetIntArrayRegion,
1998a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetLongArrayRegion,
1999a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetFloatArrayRegion,
2000a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetDoubleArrayRegion,
2001a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::RegisterNatives,
2002a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::UnregisterNatives,
2003a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::MonitorEnter,
2004a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::MonitorExit,
2005a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetJavaVM,
2006a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringRegion,
2007a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringUTFRegion,
2008a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetPrimitiveArrayCritical,
2009a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleasePrimitiveArrayCritical,
2010a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringCritical,
2011a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseStringCritical,
2012a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewWeakGlobalRef,
2013a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::DeleteWeakGlobalRef,
2014a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ExceptionCheck,
2015a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewDirectByteBuffer,
2016a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDirectBufferAddress,
2017a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDirectBufferCapacity,
2018a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetObjectRefType,
2019a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
2020a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2021a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNINativeInterface* GetCheckJniNativeInterface() {
2022a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  return &gCheckNativeInterface;
2023a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}
2024a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2025a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesclass CheckJII {
2026ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes public:
2027a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint DestroyJavaVM(JavaVM* vm) {
2028a09576416788b916095739e43a16917e7948f3a4Elliott Hughes    ScopedCheck sc(vm, false, __FUNCTION__);
202932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    sc.Check(true, "v", vm);
203032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    return CHECK_JNI_EXIT("I", BaseVm(vm)->DestroyJavaVM(vm));
2031a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2032a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2033a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2034a09576416788b916095739e43a16917e7948f3a4Elliott Hughes    ScopedCheck sc(vm, false, __FUNCTION__);
203532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    sc.Check(true, "vpp", vm, p_env, thr_args);
203632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    return CHECK_JNI_EXIT("I", BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args));
2037a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2038a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2039a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2040a09576416788b916095739e43a16917e7948f3a4Elliott Hughes    ScopedCheck sc(vm, false, __FUNCTION__);
204132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    sc.Check(true, "vpp", vm, p_env, thr_args);
204232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    return CHECK_JNI_EXIT("I", BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args));
2043a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2044a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2045a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint DetachCurrentThread(JavaVM* vm) {
2046a09576416788b916095739e43a16917e7948f3a4Elliott Hughes    ScopedCheck sc(vm, true, __FUNCTION__);
204732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    sc.Check(true, "v", vm);
204832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    return CHECK_JNI_EXIT("I", BaseVm(vm)->DetachCurrentThread(vm));
2049a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2050a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2051a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint GetEnv(JavaVM* vm, void** env, jint version) {
2052a09576416788b916095739e43a16917e7948f3a4Elliott Hughes    ScopedCheck sc(vm, true, __FUNCTION__);
205383a25328c595975097cf3948451088cbfc64fc09Elliott Hughes    sc.Check(true, "vpI", vm);
205432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    return CHECK_JNI_EXIT("I", BaseVm(vm)->GetEnv(vm, env, version));
2055a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2056a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2057a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes private:
205832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  static inline const JNIInvokeInterface* BaseVm(JavaVM* vm) {
2059a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return reinterpret_cast<JavaVMExt*>(vm)->unchecked_functions;
2060a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2061a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
2062a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2063a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNIInvokeInterface gCheckInvokeInterface = {
2064ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved0
2065ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved1
2066ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved2
2067a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::DestroyJavaVM,
2068a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::AttachCurrentThread,
2069a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::DetachCurrentThread,
2070a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::GetEnv,
2071a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::AttachCurrentThreadAsDaemon
2072a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
2073a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2074a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNIInvokeInterface* GetCheckJniInvokeInterface() {
2075a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  return &gCheckInvokeInterface;
2076a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}
2077a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2078a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}  // namespace art
2079