check_jni.cc revision 277ccbd200ea43590dfc06a93ae184a765327ad0
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
17277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#include "check_jni.h"
18a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
19a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include <sys/mman.h>
20a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include <zlib.h>
21a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2207ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
23c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers#include "base/to_str.h"
24a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include "class_linker.h"
252dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "class_linker-inl.h"
264f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h"
2722d5e735f403c57525fe868304c7123f0ce66399Ian Rogers#include "field_helper.h"
281d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/space.h"
2968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#include "java_vm_ext.h"
30277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#include "jni_internal.h"
31ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_field-inl.h"
32ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h"
332dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h"
342dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h"
352dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h"
36b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers#include "mirror/string-inl.h"
372dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/throwable.h"
3858df32711162823647356afe25ae2cde04133563Jeff Hao#include "runtime.h"
3900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h"
40a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include "thread.h"
4168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#include "well_known_classes.h"
42a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
43a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesnamespace art {
44a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
45a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/*
46a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
47a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *      JNI function helpers
48a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
49a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */
50a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
513f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes// Flags passed into ScopedCheck.
52a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define kFlag_Default       0x0000
53a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
543f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritBad       0x0000      // Calling while in critical is not allowed.
553f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritOkay      0x0001      // Calling while in critical is allowed.
563f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritGet       0x0002      // This is a critical "get".
573f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritRelease   0x0003      // This is a critical "release".
583f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritMask      0x0003      // Bit mask to get "crit" value.
59a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
603f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_ExcepBad      0x0000      // Raised exceptions are not allowed.
613f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_ExcepOkay     0x0004      // Raised exceptions are allowed.
62a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
633f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_Release       0x0010      // Are we in a non-critical release function?
643f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_NullableUtf   0x0020      // Are our UTF parameters nullable?
65a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
663f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_Invocation    0x8000      // Part of the invocation interface (JavaVM*).
67a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
68485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes#define kFlag_ForceTrace    0x80000000  // Add this to a JNI function's flags if you want to trace every call.
6968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers/*
7068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Java primitive types:
7168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * B - jbyte
7268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * C - jchar
7368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * D - jdouble
7468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * F - jfloat
7568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * I - jint
7668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * J - jlong
7768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * S - jshort
7868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Z - jboolean (shown as true and false)
7968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * V - void
8068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *
8168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Java reference types:
8268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * L - jobject
8368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * a - jarray
8468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * c - jclass
8568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * s - jstring
8668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * t - jthrowable
8768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *
8868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * JNI types:
8968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
9068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * f - jfieldID
9168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION)
9268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * m - jmethodID
9368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * p - void*
9468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * r - jint (for release mode arguments)
9568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * u - const char* (Modified UTF-8)
9668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * z - jsize (for lengths; use i if negative values are okay)
9768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * v - JavaVM*
9868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * w - jobjectRefType
9968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * E - JNIEnv*
10068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * . - no argument; just print "..." (used for varargs JNI calls)
10168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *
10268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers */
10368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogersunion JniValueType {
10468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jarray a;
10568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jboolean b;
10668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jclass c;
10768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jfieldID f;
10868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jint i;
10968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jmethodID m;
11068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const void* p;  // Pointer.
11168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jint r;  // Release mode.
11268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jstring s;
11368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jthrowable t;
11468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const char* u;  // Modified UTF-8.
11568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  JavaVM* v;
11668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jobjectRefType w;
11768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jsize z;
11868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jbyte B;
11968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jchar C;
12068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jdouble D;
12168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  JNIEnv* E;
12268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jfloat F;
12368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jint I;
12468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jlong J;
12568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jobject L;
12668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jshort S;
12768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const void* V;  // void
12868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jboolean Z;
129a09576416788b916095739e43a16917e7948f3a4Elliott Hughes};
130a09576416788b916095739e43a16917e7948f3a4Elliott Hughes
131a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesclass ScopedCheck {
132ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes public:
13368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  explicit ScopedCheck(int flags, const char* functionName, bool has_method = true)
13468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      : function_name_(functionName), flags_(flags), indent_(0), has_method_(has_method) {
13500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
13600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
13768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  ~ScopedCheck() {}
138a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
13981ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
14081ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
14181ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
14281ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // circumstances, but this is incorrect.
14368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckClassName(const char* class_name) {
1442d10b206f9d0b97396b7dadb9a6415cd39efd341Ian Rogers    if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
14568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("illegal class name '%s'\n"
14668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             "    (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
14768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             class_name);
14868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
149a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
15068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
151a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
152a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
153a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
154a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that this instance field ID is valid for this object.
155a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
156a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Assumes "jobj" has already been validated.
157a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
15868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
159b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
16068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
16168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (o == nullptr) {
16268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("field operation on NULL object: %p", java_object);
16368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
16468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
16568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
1664c13a3ff475f206c4d0a86ee2595c45392fd942fMathieu Chartier      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
16768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("field operation on invalid %s: %p",
16868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
16968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             java_object);
17068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
171a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
172a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
17368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::ArtField* f = CheckFieldID(soa, fid);
174ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (f == nullptr) {
17568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
17632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
1772dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Class* c = o->GetClass();
17861c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier    if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
17968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("jfieldID %s not valid for an object of class %s",
18068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             PrettyField(f).c_str(), PrettyTypeOf(o).c_str());
18168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
182a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
18368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
184a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
185a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
186a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
187a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that the pointer value is non-NULL.
188a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
18968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckNonNull(const void* ptr) {
19068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (UNLIKELY(ptr == nullptr)) {
19168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("non-nullable argument was NULL");
19268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
193a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
19468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
195a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
196a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
197a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
198a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that the method's return type matches the type of call.
199a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * 'expectedType' will be "L" for all objects, including arrays.
200a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
20168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
20268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                         jmethodID mid, Primitive::Type type, InvokeType invoke)
203b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
20468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::ArtMethod* m = CheckMethodID(soa, mid);
205ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (m == nullptr) {
20668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
20732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
20868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (type != Primitive::GetType(m->GetShorty()[0])) {
20968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("the return type of %s does not match %s", function_name_, PrettyMethod(m).c_str());
21068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
2113f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    }
21268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    bool is_static = (invoke == kStatic);
21368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (is_static != m->IsStatic()) {
21468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (is_static) {
21568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("calling non-static method %s with %s",
21668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               PrettyMethod(m).c_str(), function_name_);
217a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      } else {
21868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("calling static method %s with %s",
21968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               PrettyMethod(m).c_str(), function_name_);
22068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
22168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
22268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
22368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (invoke != kVirtual) {
22468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      mirror::Class* c = soa.Decode<mirror::Class*>(jc);
22568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
22668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
22768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            PrettyMethod(m).c_str(), PrettyClass(c).c_str());
22868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
22968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
23068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
23168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (invoke != kStatic) {
23268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      mirror::Object* o = soa.Decode<mirror::Object*>(jobj);
233a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier      if (o == nullptr) {
234a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier        AbortF("can't call %s on null object", PrettyMethod(m).c_str());
235a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier        return false;
236a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier      } else if (!o->InstanceOf(m->GetDeclaringClass())) {
23768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
23868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
239a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
240a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
24168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
242a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
243a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
244a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
245a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that this static field ID is valid for this class.
246a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
247a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Assumes "java_class" has already been validated.
248a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
24968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
250b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
25168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
25268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::ArtField* f = CheckFieldID(soa, fid);
253ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (f == nullptr) {
25468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
25532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
256a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    if (f->GetDeclaringClass() != c) {
25768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("static jfieldID %p not valid for class %s", fid, PrettyClass(c).c_str());
25868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
259a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
26068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
261a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
262a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
263a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
264e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes   * Verify that "mid" is appropriate for "java_class".
265a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
266a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * A mismatch isn't dangerous, because the jmethodID defines the class.  In
267e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes   * fact, java_class is unused in the implementation.  It's best if we don't
268a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * allow bad code in the system though.
269a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
270e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes   * Instances of "java_class" must be instances of the method's declaring class.
271a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
27268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
273b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
27468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::ArtMethod* m = CheckMethodID(soa, mid);
275ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (m == nullptr) {
27668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
27732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
27868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
27967fe2b41a6afccf6ab1a58879eae3e0e8f3d6c7aBrian Carlstrom    if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
28068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("can't call static %s on class %s", PrettyMethod(m).c_str(), PrettyClass(c).c_str());
28168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
282a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
28368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
284a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
285a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
286a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
287a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that "mid" is appropriate for "jobj".
288a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
289a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Make sure the object is an instance of the method's declaring class.
290a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * (Note the mid might point to a declaration in an interface; this
291a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * will be handled automatically by the instanceof check.)
292a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
29368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
294b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
29568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::ArtMethod* m = CheckMethodID(soa, mid);
296ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (m == nullptr) {
29768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
29832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
29968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
300a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier    if (o == nullptr) {
301a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier      AbortF("can't call %s on null object", PrettyMethod(m).c_str());
302a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier      return false;
303a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier    } else if (!o->InstanceOf(m->GetDeclaringClass())) {
30468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
30568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
306a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
30768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
308a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
309a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
310a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /**
311a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * The format string is a sequence of the following characters,
312a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * and must be followed by arguments of the corresponding types
313a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * in the same order.
314a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
315a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Java primitive types:
316a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * B - jbyte
317a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * C - jchar
318a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * D - jdouble
319a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * F - jfloat
320a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * I - jint
321a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * J - jlong
322a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * S - jshort
323a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Z - jboolean (shown as true and false)
324a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * V - void
325a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
326a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Java reference types:
327a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * L - jobject
328a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * a - jarray
329a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * c - jclass
330a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * s - jstring
331a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
332a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * JNI types:
333a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
334a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * f - jfieldID
335a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * m - jmethodID
336a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * p - void*
337a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * r - jint (for release mode arguments)
33878090d119d5e23ff35ecddac1f4a98e4c050bb07Elliott Hughes   * u - const char* (Modified UTF-8)
339a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * z - jsize (for lengths; use i if negative values are okay)
340a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * v - JavaVM*
341a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * E - JNIEnv*
342a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * . - no argument; just print "..." (used for varargs JNI calls)
343a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
344a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
345a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
34668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
34768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
348ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    mirror::ArtMethod* traceMethod = nullptr;
34968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (has_method_ && soa.Vm()->IsTracingEnabled()) {
350a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      // We need to guard some of the invocation interface's calls: a bad caller might
351a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
352a09576416788b916095739e43a16917e7948f3a4Elliott Hughes      Thread* self = Thread::Current();
353ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
354ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        traceMethod = self->GetCurrentMethod(nullptr);
355a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
356a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
357a09576416788b916095739e43a16917e7948f3a4Elliott Hughes
358ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (((flags_ & kFlag_ForceTrace) != 0) ||
35968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
360a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      std::string msg;
36168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      for (size_t i = 0; fmt[i] != '\0'; ++i) {
36268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
36368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (fmt[i + 1] != '\0') {
36468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(&msg, ", ");
36568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
36668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
36768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
36868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if ((flags_ & kFlag_ForceTrace) != 0) {
36968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
37068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      } else if (entry) {
37168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (has_method_) {
37268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          std::string methodName(PrettyMethod(traceMethod, false));
37368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
37468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          indent_ = methodName.size() + 1;
375a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else {
37668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
37768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          indent_ = 0;
37868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
37968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      } else {
38068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
38168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
38268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
38368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
38468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // We always do the thorough checks on entry, and never on exit...
38568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (entry) {
38668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      for (size_t i = 0; fmt[i] != '\0'; ++i) {
38768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
38868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          return false;
389a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
39068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
39168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
39268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
39368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
39468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
39568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
39668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
39768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!should_trace && vm->IsTracingEnabled()) {
39868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // We need to guard some of the invocation interface's calls: a bad caller might
39968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
40068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      Thread* self = Thread::Current();
40168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
40268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        ScopedObjectAccess soa(self);
40368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        mirror::ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
40468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
40568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
40668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
40768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (should_trace) {
40868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      std::string msg;
40968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      for (size_t i = 0; fmt[i] != '\0'; ++i) {
41068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        TraceNonHeapValue(fmt[i], args[i], &msg);
41168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (fmt[i + 1] != '\0') {
412a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          StringAppendF(&msg, ", ");
413a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
414a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
415a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
416485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes      if ((flags_ & kFlag_ForceTrace) != 0) {
417485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes        LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
418485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes      } else if (entry) {
41932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        if (has_method_) {
42068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          Thread* self = Thread::Current();
42168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          ScopedObjectAccess soa(self);
42268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          mirror::ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
423a09576416788b916095739e43a16917e7948f3a4Elliott Hughes          std::string methodName(PrettyMethod(traceMethod, false));
42432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
42532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          indent_ = methodName.size() + 1;
426a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else {
42732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
42832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          indent_ = 0;
429a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
430a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      } else {
43132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
432a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
433a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
434a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
435a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // We always do the thorough checks on entry, and never on exit...
436a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    if (entry) {
43768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      for (size_t i = 0; fmt[i] != '\0'; ++i) {
43868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (!CheckNonHeapValue(fmt[i], args[i])) {
43968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          return false;
440a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
441a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
442a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
44368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
44468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
44568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
44668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
44768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
44868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Object* method = soa.Decode<mirror::Object*>(jmethod);
44968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (method == nullptr) {
45068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected non-null method");
45168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
45268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
45368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Class* c = method->GetClass();
45468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Method) != c &&
45568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
45668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected java.lang.reflect.Method or "
45768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          "java.lang.reflect.Constructor but got object of type %s: %p",
45868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          PrettyTypeOf(method).c_str(), jmethod);
45968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
46068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
46168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
46268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
46368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
46468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckConstructor(ScopedObjectAccess& soa, jmethodID mid)
46568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
46668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::ArtMethod* method = soa.DecodeMethod(mid);
46768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (method == nullptr) {
46868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected non-null constructor");
46968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
47068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
47168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!method->IsConstructor() || method->IsStatic()) {
47268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected a constructor but %s: %p", PrettyTypeOf(method).c_str(), mid);
47368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
47468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
47568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
47668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
47768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
47868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
47968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
48068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Object* field = soa.Decode<mirror::Object*>(jfield);
48168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (field == nullptr) {
48268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected non-null java.lang.reflect.Field");
48368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
48468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
48568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Class* c = field->GetClass();
48668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Field) != c) {
48768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
48868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             PrettyTypeOf(field).c_str(), jfield);
48968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
49068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
49168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
49268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
49368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
49468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
49568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
49668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Object* obj = soa.Decode<mirror::Object*>(jobj);
49768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!obj->GetClass()->IsThrowableClass()) {
49868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected java.lang.Throwable but got object of type "
49968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             "%s: %p", PrettyTypeOf(obj).c_str(), obj);
50068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
50168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
50268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
50368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
50468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
50568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
50668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
50768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Class* c = soa.Decode<mirror::Class*>(jc);
50868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!c->IsThrowableClass()) {
50968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected java.lang.Throwable class but got object of "
51068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             "type %s: %p", PrettyDescriptor(c).c_str(), c);
51168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
51268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
51368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
51468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
51568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
5166a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
51768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    IndirectRefKind found_kind;
51868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (expected_kind == kLocal) {
51968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      found_kind = GetIndirectRefKind(obj);
52068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
52168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        found_kind = kLocal;
52268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
52368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    } else {
52468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      found_kind = GetIndirectRefKind(obj);
52568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
52668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (obj != nullptr && found_kind != expected_kind) {
52768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected reference of kind %s but found %s: %p",
52868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             ToStr<IndirectRefKind>(expected_kind).c_str(),
52968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             ToStr<IndirectRefKind>(GetIndirectRefKind(obj)).c_str(),
53068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             obj);
53168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
53268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
53368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
53468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
53568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
53668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
53768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
53868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Class* c = soa.Decode<mirror::Class*>(jc);
53968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!c->IsInstantiableNonArray()) {
54068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("can't make objects of type %s: %p", PrettyDescriptor(c).c_str(), c);
54168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
54268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
54368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
54468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
54568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
54668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
54768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
54868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!CheckArray(soa, array)) {
54968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
55068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
55168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Array* a = soa.Decode<mirror::Array*>(array);
55268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
55368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("incompatible array type %s expected %s[]: %p",
55468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             PrettyDescriptor(a->GetClass()).c_str(), PrettyDescriptor(type).c_str(), array);
55568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
55668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
55768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
55868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
55968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
56068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
56168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                        Primitive::Type type)
56268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
56368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
56468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
56568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
56668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
56768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
56868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
56968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::ArtField* field = soa.DecodeField(fid);
57068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    DCHECK(field != nullptr);  // Already checked by Check.
57168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (is_static != field->IsStatic()) {
57268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("attempt to access %s field %s: %p",
57368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             field->IsStatic() ? "static" : "non-static", PrettyField(field).c_str(), fid);
57468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
57568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
57668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (type != field->GetTypeAsPrimitiveType()) {
57768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
57868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             PrettyField(field).c_str(), PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
57968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             PrettyDescriptor(type).c_str(), fid);
58068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
58168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
58268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (is_static) {
58368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      mirror::Object* o = soa.Decode<mirror::Object*>(obj);
58468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (o == nullptr || !o->IsClass()) {
58568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("attempt to access static field %s with a class argument of type %s: %p",
58668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid);
58768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
58868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
58968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      mirror::Class* c = o->AsClass();
59068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (field->GetDeclaringClass() != c) {
59168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
59268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               PrettyField(field).c_str(), PrettyDescriptor(c).c_str(), fid);
59368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
59468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
59568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    } else {
59668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      mirror::Object* o = soa.Decode<mirror::Object*>(obj);
59768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
59868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("attempt to access field %s from an object argument of type %s: %p",
59968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid);
60068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
60168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
60268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
60368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
604a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
605a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
60668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers private:
607a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes  enum InstanceKind {
608a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    kClass,
6090f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes    kDirectByteBuffer,
6100f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes    kObject,
6110f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes    kString,
6120f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes    kThrowable,
613a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes  };
614a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
615a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes  /*
616a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   * Verify that "jobj" is a valid non-NULL object reference, and points to
617a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   * an instance of expectedClass.
618a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   *
619a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   * Because we're looking at an object on the GC heap, we have to switch
620a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   * to "running" mode before doing the checks.
621a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   */
62268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
623b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
624ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const char* what = nullptr;
625a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    switch (kind) {
626a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kClass:
627a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "jclass";
628a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
629a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kDirectByteBuffer:
630a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "direct ByteBuffer";
631a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
632a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kObject:
633a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "jobject";
634a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
635a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kString:
636a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "jstring";
637a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
638a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kThrowable:
639a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "jthrowable";
640a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
641a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    default:
6427b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes      LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
643a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
644a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
645ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (java_object == nullptr) {
64668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (null_ok) {
64768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return true;
64868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      } else {
64968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("%s received NULL %s", function_name_, what);
65068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
65168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
652a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
653a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
65468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Object* obj = soa.Decode<mirror::Object*>(java_object);
655c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    if (obj == nullptr) {
656c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      // Either java_object is invalid or is a cleared weak.
657c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
658c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      bool okay;
659c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      if (GetIndirectRefKind(ref) != kWeakGlobal) {
660c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        okay = false;
661c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      } else {
662c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
663c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
664c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      }
665c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      if (!okay) {
666c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        AbortF("%s is an invalid %s: %p (%p)",
667c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers               what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
668c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers               java_object, obj);
669c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        return false;
670c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      }
671c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    }
672c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers
673590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) {
6744c13a3ff475f206c4d0a86ee2595c45392fd942fMathieu Chartier      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
67568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("%s is an invalid %s: %p (%p)",
67668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
67768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             java_object, obj);
678a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      return false;
679a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
680a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
681a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    bool okay = true;
682a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    switch (kind) {
683a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kClass:
684a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      okay = obj->IsClass();
685a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
686a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kDirectByteBuffer:
687a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      UNIMPLEMENTED(FATAL);
688a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
689a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kString:
690a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      okay = obj->GetClass()->IsStringClass();
691a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
692a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kThrowable:
693a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      okay = obj->GetClass()->IsThrowableClass();
694a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
695a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kObject:
696a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
697a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
698a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    if (!okay) {
69968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("%s has wrong type: %s", what, PrettyTypeOf(obj).c_str());
700a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      return false;
701a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
702a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
703a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    return true;
704a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes  }
705a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
706a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
70768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * Verify that the "mode" argument passed to a primitive array Release
70868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * function is one of the valid values.
709a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
71068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckReleaseMode(jint mode) {
71168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
71268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("unknown value for release mode: %d", mode);
71368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
714a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
71568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
716a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
717a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
71868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
71968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
72068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    switch (fmt) {
72168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'a':  // jarray
72268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckArray(soa, arg.a);
72368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'c':  // jclass
72468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckInstance(soa, kClass, arg.c, false);
72568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'f':  // jfieldID
72668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckFieldID(soa, arg.f) != nullptr;
72768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'm':  // jmethodID
72868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckMethodID(soa, arg.m) != nullptr;
72968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'r':  // release int
73068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckReleaseMode(arg.r);
73168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 's':  // jstring
73268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckInstance(soa, kString, arg.s, false);
73368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 't':  // jthrowable
73468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckInstance(soa, kThrowable, arg.t, false);
73568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'E':  // JNIEnv*
73668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckThread(arg.E);
73768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'L':  // jobject
73868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckInstance(soa, kObject, arg.L, true);
73968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      default:
74068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckNonHeapValue(fmt, arg);
74168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
74268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
74368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
74468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckNonHeapValue(char fmt, JniValueType arg) {
74568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    switch (fmt) {
74668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case '.':  // ...
74768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'p':  // TODO: pointer - null or readable?
74868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'v':  // JavaVM*
74968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'B':  // jbyte
75068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'C':  // jchar
75168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'D':  // jdouble
75268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'F':  // jfloat
75368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'I':  // jint
75468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'J':  // jlong
75568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'S':  // jshort
75668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;  // Ignored.
75768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'b':  // jboolean, why two? Fall-through.
75868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'Z':
75968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckBoolean(arg.Z);
76068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'u':  // utf8
76168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if ((flags_ & kFlag_Release) != 0) {
76268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          return CheckNonNull(arg.u);
76368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
76468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
76568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          return CheckUtfString(arg.u, nullable);
76668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
76768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'w':  // jobjectRefType
76868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        switch (arg.w) {
76968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNIInvalidRefType:
77068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNILocalRefType:
77168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNIGlobalRefType:
77268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNIWeakGlobalRefType:
77368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            break;
77468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          default:
77568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            AbortF("Unknown reference type");
77668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            return false;
77768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
77868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
77968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'z':  // jsize
78068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckLengthPositive(arg.z);
78168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      default:
78268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("unknown format specifier: '%c'", fmt);
78368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
78432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
78568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
78632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  }
78732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes
78868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
78968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                              std::string* msg)
79068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
79168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    switch (fmt) {
79268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'L':  // jobject fall-through.
79368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'a':  // jarray fall-through.
79468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 's':  // jstring fall-through.
79568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 't':  // jthrowable fall-through.
79668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (arg.L == nullptr) {
79768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "NULL";
79868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
79968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "%p", arg.L);
80068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
80168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
80268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'c': {  // jclass
80368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        jclass jc = arg.c;
80468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        mirror::Class* c = soa.Decode<mirror::Class*>(jc);
80568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (c == nullptr) {
80668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "NULL";
807c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) {
80868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "INVALID POINTER:%p", jc);
80968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else if (!c->IsClass()) {
81068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c);
81168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
81268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += PrettyClass(c);
81368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (!entry) {
81468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            StringAppendF(msg, " (%p)", jc);
81568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
81668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
81768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
81868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
81968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'f': {  // jfieldID
82068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        jfieldID fid = arg.f;
82168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        mirror::ArtField* f = soa.DecodeField(fid);
82268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        *msg += PrettyField(f);
82368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (!entry) {
82468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, " (%p)", fid);
82568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
82668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
82768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
82868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'm': {  // jmethodID
82968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        jmethodID mid = arg.m;
83068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        mirror::ArtMethod* m = soa.DecodeMethod(mid);
83168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        *msg += PrettyMethod(m);
83268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (!entry) {
83368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, " (%p)", mid);
83468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
83568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
83668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
83768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      default:
83868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        TraceNonHeapValue(fmt, arg, msg);
83968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
84032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
84132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  }
84232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes
84368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
84468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    switch (fmt) {
84568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'B':  // jbyte
84668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (arg.B >= 0 && arg.B < 10) {
84768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "%d", arg.B);
84868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
84968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
85068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
85168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
85268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'C':  // jchar
85368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (arg.C < 0x7f && arg.C >= ' ') {
85468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
85568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
85668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "U+%x", arg.C);
85768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
85868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
85968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'F':  // jfloat
86068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "%g", arg.F);
86168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
86268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'D':  // jdouble
86368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "%g", arg.D);
86468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
86568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'S':  // jshort
86668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "%d", arg.S);
86768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
86868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'i':  // jint - fall-through.
86968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'I':  // jint
87068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "%d", arg.I);
87168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
87268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'J':  // jlong
87368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "%" PRId64, arg.J);
87468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
87568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'Z':  // jboolean
87668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'b':  // jboolean (JNI-style)
87768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        *msg += arg.b == JNI_TRUE ? "true" : "false";
87868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
87968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'V':  // void
88068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        DCHECK(arg.V == nullptr);
88168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        *msg += "void";
88268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
88368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'v':  // JavaVM*
88468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "(JavaVM*)%p", arg.v);
88568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
88668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'E':
88768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "(JNIEnv*)%p", arg.E);
88868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
88968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'z':  // non-negative jsize
89068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        // You might expect jsize to be size_t, but it's not; it's the same as jint.
89168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        // We only treat this specially so we can do the non-negative check.
89268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        // TODO: maybe this wasn't worth it?
89368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "%d", arg.z);
89468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
89568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'p':  // void* ("pointer")
89668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (arg.p == nullptr) {
89768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "NULL";
89868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
89968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "(void*) %p", arg.p);
90068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
90168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
90268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'r': {  // jint (release mode)
90368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        jint releaseMode = arg.r;
90468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (releaseMode == 0) {
90568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "0";
90668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else if (releaseMode == JNI_ABORT) {
90768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "JNI_ABORT";
90868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else if (releaseMode == JNI_COMMIT) {
90968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "JNI_COMMIT";
91068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
91168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "invalid release mode %d", releaseMode);
91268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
91368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
91468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
91568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'u':  // const char* (Modified UTF-8)
91668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (arg.u == nullptr) {
91768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "NULL";
91868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
91968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "\"%s\"", arg.u);
92068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
92168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
92268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'w':  // jobjectRefType
92368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        switch (arg.w) {
92468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNIInvalidRefType:
92568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            *msg += "invalid reference type";
92668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            break;
92768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNILocalRefType:
92868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            *msg += "local ref type";
92968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            break;
93068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNIGlobalRefType:
93168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            *msg += "global ref type";
93268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            break;
93368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNIWeakGlobalRefType:
93468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            *msg += "weak global ref type";
93568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            break;
93668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          default:
93768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            *msg += "unknown ref type";
93868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            break;
93968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
94068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
94168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case '.':
94268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        *msg += "...";
94368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
94468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      default:
94568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
94668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
94768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
948a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
94968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * Verify that "array" is non-NULL and points to an Array object.
950a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
95168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * Since we're dealing with objects, switch to "running" mode.
952a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
95368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
954b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
95568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (UNLIKELY(java_array == nullptr)) {
95668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("jarray was NULL");
95768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
958a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
959a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
96068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
96168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a))) {
9624c13a3ff475f206c4d0a86ee2595c45392fd942fMathieu Chartier      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
96368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("jarray is an invalid %s: %p (%p)",
96468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(),
96568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             java_array, a);
96668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
96768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    } else if (!a->IsArrayInstance()) {
96868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("jarray argument has non-array type: %s", PrettyTypeOf(a).c_str());
96968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
970a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
97168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
972a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
973a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
97468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckBoolean(jboolean z) {
97568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (z != JNI_TRUE && z != JNI_FALSE) {
97668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("unexpected jboolean value: %d", z);
97768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
97868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
97968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
98068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
98168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
98268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckLengthPositive(jsize length) {
98368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (length < 0) {
98468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("negative jsize: %d", length);
98568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
98668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
98768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
98868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
98968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
99068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  mirror::ArtField* CheckFieldID(ScopedObjectAccess& soa, jfieldID fid)
99168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
99268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (fid == nullptr) {
99368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("jfieldID was NULL");
99468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return nullptr;
99568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
99668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::ArtField* f = soa.DecodeField(fid);
99768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f) || !f->IsArtField()) {
99868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
99968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("invalid jfieldID: %p", fid);
100068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return nullptr;
100168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
100268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return f;
100368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
100468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
100568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  mirror::ArtMethod* CheckMethodID(ScopedObjectAccess& soa, jmethodID mid)
100668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
100768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (mid == nullptr) {
100868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("jmethodID was NULL");
100968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return nullptr;
101068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
101168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::ArtMethod* m = soa.DecodeMethod(mid);
101268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m) || !m->IsArtMethod()) {
101368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
101468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("invalid jmethodID: %p", mid);
101568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return nullptr;
1016a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
101768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return m;
1018a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1019a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
102068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckThread(JNIEnv* env) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1021a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    Thread* self = Thread::Current();
1022ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (self == nullptr) {
102368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
102468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
1025a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1026a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1027a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // Get the *correct* JNIEnv by going through our TLS pointer.
1028a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    JNIEnvExt* threadEnv = self->GetJniEnv();
1029a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
10303f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Verify that the current thread is (a) attached and (b) associated with
10313f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // this particular instance of JNIEnv.
103268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (env != threadEnv) {
103368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("thread %s using JNIEnv* from thread %s",
103468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             ToStr<Thread>(*self).c_str(), ToStr<Thread>(*self).c_str());
103568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
1036a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1037a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
10383f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Verify that, if this thread previously made a critical "get" call, we
10393f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // do the corresponding "release" call before we try anything else.
104068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    switch (flags_ & kFlag_CritMask) {
1041a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    case kFlag_CritOkay:    // okay to call this method
1042a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      break;
1043a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    case kFlag_CritBad:     // not okay to call
1044a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      if (threadEnv->critical) {
104568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("thread %s using JNI after critical get",
104668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               ToStr<Thread>(*self).c_str());
104768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
1048a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1049a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      break;
1050a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    case kFlag_CritGet:     // this is a "get" call
10513f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      // Don't check here; we allow nested gets.
1052a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      threadEnv->critical++;
1053a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      break;
10547934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    case kFlag_CritRelease:  // this is a "release" call
1055a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      threadEnv->critical--;
1056a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      if (threadEnv->critical < 0) {
105768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("thread %s called too many critical releases",
105868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               ToStr<Thread>(*self).c_str());
105968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
1060a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1061a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      break;
1062a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    default:
106368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      LOG(FATAL) << "Bad flags (internal error): " << flags_;
1064a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1065a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
10663f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Verify that, if an exception has been raised, the native code doesn't
10673f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // make any JNI calls other than the Exception* methods.
106868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
106962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ThrowLocation throw_location;
107062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      mirror::Throwable* exception = self->GetException(&throw_location);
107162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      std::string type(PrettyTypeOf(exception));
107268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("JNI %s called with pending exception '%s' thrown in %s",
107368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             function_name_, type.c_str(), throw_location.Dump().c_str());
107468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
1075a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
107668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
1077a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1078a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
10793f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes  // Verifies that "bytes" points to valid Modified UTF-8 data.
108068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckUtfString(const char* bytes, bool nullable) {
1081ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (bytes == nullptr) {
1082a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      if (!nullable) {
108368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("non-nullable const char* was NULL");
108468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
1085a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
108668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return true;
1087a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1088a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1089ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const char* errorKind = nullptr;
109032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    uint8_t utf8 = CheckUtfBytes(bytes, &errorKind);
1091ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (errorKind != nullptr) {
109268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
109368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          "    string: '%s'", errorKind, utf8, bytes);
109468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
1095a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
109668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
1097a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1098a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
109932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  static uint8_t CheckUtfBytes(const char* bytes, const char** errorKind) {
1100a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    while (*bytes != '\0') {
1101a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      uint8_t utf8 = *(bytes++);
1102a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      // Switch on the high four bits.
1103a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      switch (utf8 >> 4) {
1104a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x00:
1105a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x01:
1106a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x02:
1107a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x03:
1108a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x04:
1109a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x05:
1110a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x06:
1111a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x07:
1112a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        // Bit pattern 0xxx. No need for any extra bytes.
1113a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        break;
1114a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x08:
1115a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x09:
1116a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0a:
1117a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0b:
1118a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0f:
1119a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        /*
1120a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes         * Bit pattern 10xx or 1111, which are illegal start bytes.
1121a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes         * Note: 1111 is valid for normal UTF-8, but not the
112278090d119d5e23ff35ecddac1f4a98e4c050bb07Elliott Hughes         * Modified UTF-8 used here.
1123a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes         */
1124a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        *errorKind = "start";
1125a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        return utf8;
1126a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0e:
1127a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        // Bit pattern 1110, so there are two additional bytes.
1128a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        utf8 = *(bytes++);
1129a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        if ((utf8 & 0xc0) != 0x80) {
1130a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          *errorKind = "continuation";
1131a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          return utf8;
1132a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
1133fc787ecd91127b2c8458afd94e5148e2ae51a1f5Ian Rogers        FALLTHROUGH_INTENDED;  // Fall-through to take care of the final byte.
1134a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0c:
1135a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0d:
1136a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        // Bit pattern 110x, so there is one additional byte.
1137a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        utf8 = *(bytes++);
1138a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        if ((utf8 & 0xc0) != 0x80) {
1139a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          *errorKind = "continuation";
1140a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          return utf8;
1141a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
1142a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        break;
1143a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1144a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1145a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return 0;
1146a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1147a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
114868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
114968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list args;
115068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(args, fmt);
115168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
115268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(args);
115368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
115468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
115568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // The name of the JNI function being checked.
115668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const char* const function_name_;
115768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
115868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const int flags_;
115992cb498ffd2185fc8f8da7cd25fe485d0e7e3355Elliott Hughes  int indent_;
1160a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
116168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const bool has_method_;
116268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
1163a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1164a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
1165a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1166a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/*
1167a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
1168a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *      Guarded arrays
1169a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
1170a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */
1171a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1172a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/* this gets tucked in at the start of the buffer; struct size must be even */
117368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogersclass GuardedCopy {
117468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers public:
1175a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
1176a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Create an over-sized buffer to hold the contents of "buf".  Copy it in,
1177a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * filling in the area around it with guard data.
1178a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
117968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void* Create(const void* original_buf, size_t len, bool mod_okay) {
118068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const size_t new_len = LengthIncludingRedZones(len);
118168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    uint8_t* const new_buf = DebugAlloc(new_len);
1182a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
118368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // If modification is not expected, grab a checksum.
118468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    uLong adler = 0;
118568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!mod_okay) {
118668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
118768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
118868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
118968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
119068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
119168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Fill begin region with canary pattern.
119268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
119368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
119468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
119568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (kCanary[j] == '\0') {
119668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        j = 0;
119768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
1198a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1199a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
12003f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Copy the data in; note "len" could be zero.
120168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1202a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
120368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Fill end region with canary pattern.
120468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
120568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
120668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (kCanary[j] == '\0') {
120768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        j = 0;
120868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
120968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
121068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
121168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return const_cast<uint8_t*>(copy->BufferWithinRedZones());
121268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
121368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
121468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  /*
121568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * Create a guarded copy of a primitive array.  Modifications to the copied
121668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * data are allowed.  Returns a pointer to the copied data.
121768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   */
121868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy) {
121968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
122068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
122168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
122268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    size_t component_size = a->GetClass()->GetComponentSize();
122368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    size_t byte_count = a->GetLength() * component_size;
122468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    void* result = Create(a->GetRawData(component_size, 0), byte_count, true);
122568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (is_copy != nullptr) {
122668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      *is_copy = JNI_TRUE;
1227a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
122868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result;
122968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
1230a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
123168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  /*
123268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * Perform the array "release" operation, which may or may not copy data
123368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * back into the managed heap, and may or may not release the underlying storage.
123468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   */
123568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env, jarray java_array,
123668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                   void* embedded_buf, int mode) {
123768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
123868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1239a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
124068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
124168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return nullptr;
124268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
124368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (mode != JNI_ABORT) {
124468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      size_t len = FromEmbedded(embedded_buf)->original_length_;
124568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      memcpy(a->GetRawData(a->GetClass()->GetComponentSize(), 0), embedded_buf, len);
124668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
124768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (mode != JNI_COMMIT) {
124868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return Destroy(embedded_buf);
124968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
125068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return embedded_buf;
1251a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1252a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
125368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
1254a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
1255a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Free up the guard buffer, scrub it, and return the original pointer.
1256a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
125768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void* Destroy(void* embedded_buf) {
125868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    GuardedCopy* copy = FromEmbedded(embedded_buf);
125968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    void* original_ptr = const_cast<void*>(copy->original_ptr_);
126068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    size_t len = LengthIncludingRedZones(copy->original_length_);
126168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    DebugFree(copy, len);
126232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    return original_ptr;
1263a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1264a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1265a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
1266a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify the guard area and, if "modOkay" is false, that the data itself
1267a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * has not been altered.
1268a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
1269a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * The caller has already checked that "dataBuf" is non-NULL.
1270a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
127168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
127268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const GuardedCopy* copy = FromEmbedded(embedded_buf);
127368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
127468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
127568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
127668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers private:
127768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  GuardedCopy(const void* original_buf, size_t len, uLong adler) :
127868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
127968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
128068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
128168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static uint8_t* DebugAlloc(size_t len) {
128268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
128368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (result == MAP_FAILED) {
128468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
128568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
128668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<uint8_t*>(result);
128768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
128868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
128968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void DebugFree(void* buf, size_t len) {
129068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (munmap(buf, len) != 0) {
129168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
129268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
129368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
129468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
129568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static size_t LengthIncludingRedZones(size_t len) {
129668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return len + kRedZoneSize;
129768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
129868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
129968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Get the GuardedCopy from the interior pointer.
130068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static GuardedCopy* FromEmbedded(void* embedded_buf) {
130168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<GuardedCopy*>(
130268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
130368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
130468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
130568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
130668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<const GuardedCopy*>(
130768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
130868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
130968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
131068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void AbortF(const char* jni_function_name, const char* fmt, ...) {
131168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list args;
131268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(args, fmt);
131368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
131468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(args);
131568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
131668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
131768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckHeader(const char* function_name, bool mod_okay) const {
1318a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    static const uint32_t kMagicCmp = kGuardMagic;
1319a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
13203f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Before we do anything with "pExtra", check the magic number.  We
13213f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // do the check with memcmp rather than "==" in case the pointer is
13223f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // unaligned.  If it points to completely bogus memory we're going
13233f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // to crash, but there's no easy way around that.
132468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1325a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      uint8_t buf[4];
132668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      memcpy(buf, &magic_, 4);
132768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF(function_name,
132868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
132968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             buf[3], buf[2], buf[1], buf[0], this);  // Assumes little-endian.
133068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
1331a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1332a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
133368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
133468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // told the client that we made a copy, there's no reason they can't alter the buffer.
133568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!mod_okay) {
133668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      uLong computed_adler =
133768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
133868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (computed_adler != adler_) {
133968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
134068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               computed_adler, adler_, this);
134168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
1342a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1343a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
134468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
134568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
1346a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
134768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckRedZones(const char* function_name) const {
134868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Check the begin red zone.
134968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
135068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
135168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
135268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
135368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
1354a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
135568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (kCanary[j] == '\0') {
135668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        j = 0;
1357a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1358a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1359a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
136068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Check end region.
136168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
136268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
136368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        size_t offset_from_buffer_start =
136468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
136568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
136668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               offset_from_buffer_start);
136768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
136868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
136968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (kCanary[j] == '\0') {
137068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        j = 0;
1371a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1372a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
137368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
1374a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1375a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
137668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Location that canary value will be written before the guarded region.
137768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const char* StartRedZone() const {
137868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
137968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1380a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1381a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
138268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Return the interior embedded buffer.
138368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const uint8_t* BufferWithinRedZones() const {
138468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
138568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return embedded_buf;
1386a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1387a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
138868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Location that canary value will be written after the guarded region.
138968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const char* EndRedZone() const {
139068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
139168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    size_t buf_len = LengthIncludingRedZones(original_length_);
139268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1393a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1394a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
139568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static constexpr size_t kRedZoneSize = 512;
139668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1397a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
139868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Value written before and after the guarded array.
139968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const char* const kCanary;
1400a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
140168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1402a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
140368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const uint32_t magic_;
140468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const uLong adler_;
140568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const void* const original_ptr_;
140668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const size_t original_length_;
140768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers};
140868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogersconst char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
1409a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1410a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/*
1411a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
1412a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *      JNI functions
1413a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
1414a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */
1415a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1416a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesclass CheckJNI {
1417a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes public:
1418a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint GetVersion(JNIEnv* env) {
141968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
142068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
142168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.E = env }};
142268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "E", args)) {
142368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
142468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.I = baseEnv(env)->GetVersion(env);
142568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "I", &result)) {
142668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.I;
142768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
142868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
142968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
143068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
143168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
143268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
143368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
143468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
143568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env }, {.p = vm}};
143668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ep", args)) {
143768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
143868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->GetJavaVM(env, vm);
143968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
144068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
144168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
144268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
144368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
144468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
144568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
144668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
144768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
144868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
144968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
145068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EcpI", args)) {
145168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
145268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
145368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
145468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
145568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
145668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
145768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
145868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
145968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
146068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jint UnregisterNatives(JNIEnv* env, jclass c) {
146168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
146268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
146368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env }, {.c = c}};
146468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ec", args)) {
146568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
146668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->UnregisterNatives(env, c);
146768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
146868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
146968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
147068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
147168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
147268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
147368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
147468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
1475c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1476c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    // know the object is invalid. The spec says that passing invalid objects or even ones that
1477c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    // are deleted isn't supported.
147868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
147968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1480c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    JniValueType args[2] = {{.E = env }, {.L = obj}};
1481c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    if (sc.Check(soa, true, "EL", args)) {
148268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
148368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.w = baseEnv(env)->GetObjectRefType(env, obj);
148468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "w", &result)) {
148568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.w;
148668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
148768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
148868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNIInvalidRefType;
1489a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1490a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
149168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
149268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                            jsize bufLen) {
149368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
149468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
149568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
149668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
149768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
149868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
149968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "c", &result)) {
150068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.c;
150168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
150268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
150368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1504a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1505a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1506a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jclass FindClass(JNIEnv* env, const char* name) {
150768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
150868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
150968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.u = name}};
151068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
151168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
151268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.c = baseEnv(env)->FindClass(env, name);
151368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "c", &result)) {
151468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.c;
151568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
151668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
151768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1518a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1519a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1520e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jclass GetSuperclass(JNIEnv* env, jclass c) {
152168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
152268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
152368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.c = c}};
152468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ec", args)) {
152568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
152668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.c = baseEnv(env)->GetSuperclass(env, c);
152768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "c", &result)) {
152868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.c;
152968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
153068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
153168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1532a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1533a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1534e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
153568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
153668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
153768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
153868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecc", args)) {
153968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
154068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
154168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "b", &result)) {
154268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.b;
154368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
154468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
154568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_FALSE;
1546a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1547a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1548a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
154968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
155068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
155168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = method}};
155268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
155368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
155468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.m = baseEnv(env)->FromReflectedMethod(env, method);
155568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "m", &result)) {
155668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.m;
155768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
155868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
155968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1560a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1561a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1562a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
156368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
156468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
156568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = field}};
156668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
156768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
156868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.f = baseEnv(env)->FromReflectedField(env, field);
156968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "f", &result)) {
157068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.f;
157168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
157268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
157368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1574a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1575a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1576a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
157768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
157868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
157968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
158068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecmb", args)) {
158168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
158268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
158368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
158468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        DCHECK(sc.CheckReflectedMethod(soa, result.L));
158568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
158668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
158768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
158868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1589a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1590a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1591a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
159268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
159368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
159468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
159568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecfb", args)) {
159668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
159768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
159868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
159968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        DCHECK(sc.CheckReflectedField(soa, result.L));
160068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
160168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
160268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
160368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1604a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1605a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1606a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint Throw(JNIEnv* env, jthrowable obj) {
160768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
160868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
160968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.t = obj}};
161068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
161168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
161268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->Throw(env, obj);
161368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
161468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
161568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
161668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
161768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
1618a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1619a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1620e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
162168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
162268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
162368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[5] = {{.E = env}, {.c = c}, {.u = message}};
162468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
162568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
162668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->ThrowNew(env, c, message);
162768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
162868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
162968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
163068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
163168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
1632a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1633a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1634a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jthrowable ExceptionOccurred(JNIEnv* env) {
163568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
163668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
163768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.E = env}};
163868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "E", args)) {
163968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
164068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.t = baseEnv(env)->ExceptionOccurred(env);
164168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "t", &result)) {
164268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.t;
164368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
164468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
164568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1646a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1647a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1648a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void ExceptionDescribe(JNIEnv* env) {
164968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
165068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
165168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.E = env}};
165268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "E", args)) {
165368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
165468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->ExceptionDescribe(env);
165568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
165668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
165768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
1658a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1659a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1660a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void ExceptionClear(JNIEnv* env) {
166168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
166268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
166368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.E = env}};
166468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "E", args)) {
166568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
166668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->ExceptionClear(env);
166768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
166868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
166968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
167068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
167168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
167268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jboolean ExceptionCheck(JNIEnv* env) {
167368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
167468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
167568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.E = env}};
167668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "E", args)) {
167768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
167868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.b = baseEnv(env)->ExceptionCheck(env);
167968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "b", &result)) {
168068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.b;
168168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
168268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
168368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_FALSE;
1684a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1685a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1686a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void FatalError(JNIEnv* env, const char* msg) {
1687c4378df76edd637273813fef4da7f01c4e637defElliott Hughes    // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1688c4378df76edd637273813fef4da7f01c4e637defElliott Hughes    // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1689c4378df76edd637273813fef4da7f01c4e637defElliott Hughes    // and it's not unimaginable that you don't know that you do. So we allow it.
169068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
169168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
169268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.u = msg}};
169368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eu", args)) {
169468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
169568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->FatalError(env, msg);
169668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // Unreachable.
169768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
169868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
169968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
1700a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1701a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1702a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint PushLocalFrame(JNIEnv* env, jint capacity) {
170368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
170468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
170568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.I = capacity}};
170668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EI", args)) {
170768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
170868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->PushLocalFrame(env, capacity);
170968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
171068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
171168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
171268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
171368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
1714a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1715a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1716a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject PopLocalFrame(JNIEnv* env, jobject res) {
171768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
171868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
171968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = res}};
172068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
172168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
172268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->PopLocalFrame(env, res);
172368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "L", &result);
172468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return result.L;
172568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
172668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1727a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1728a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1729a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
173068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return NewRef(__FUNCTION__, env, obj, kGlobal);
1731a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1732a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
173368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobject NewLocalRef(JNIEnv* env, jobject obj) {
173468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return NewRef(__FUNCTION__, env, obj, kLocal);
1735a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1736a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
173768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
173868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
1739a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1740a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
174168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
174268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    DeleteRef(__FUNCTION__, env, obj, kGlobal);
1743a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1744a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
174568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
174668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
174768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
174868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
174968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void DeleteLocalRef(JNIEnv* env, jobject obj) {
175068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    DeleteRef(__FUNCTION__, env, obj, kLocal);
1751a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1752a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1753a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
175468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
175568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
175668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.I = capacity}};
175768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EI", args)) {
175868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
175968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
176068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
176168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
176268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
176368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
176468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
1765a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1766a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1767a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
176868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
176968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
177068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
177168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "ELL", args)) {
177268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
177368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
177468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "b", &result)) {
177568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.b;
177668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
177768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
177868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_FALSE;
1779a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1780a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1781e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jobject AllocObject(JNIEnv* env, jclass c) {
178268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
178368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
178468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.c = c}};
178568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
178668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
178768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->AllocObject(env, c);
178868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result)) {
178968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
179068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
179168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
179268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
179368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
179468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
179568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
179668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
179768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
179868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
179968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
180068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.CheckConstructor(soa, mid)) {
180168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
180268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
180368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result)) {
180468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
180568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
180668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
180768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1808a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1809a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1810e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
1811a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    va_list args;
1812a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    va_start(args, mid);
181368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    jobject result = NewObjectV(env, c, mid, args);
1814a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    va_end(args);
181568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result;
1816a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1817a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
181868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
181968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
182068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
182168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
182268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
182368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.CheckConstructor(soa, mid)) {
182468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
182568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
182668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result)) {
182768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
182868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
182968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
183068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1831a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1832a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1833a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jclass GetObjectClass(JNIEnv* env, jobject obj) {
183468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
183568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
183668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = obj}};
183768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
183868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
183968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.c = baseEnv(env)->GetObjectClass(env, obj);
184068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "c", &result)) {
184168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.c;
184268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
184368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
184468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1845a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1846a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1847e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
184868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
184968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
185068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
185168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "ELc", args)) {
185268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
185368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
185468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "b", &result)) {
185568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.b;
185668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
185768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
185868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_FALSE;
1859a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1860a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1861e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
186268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
1863a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1864a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
186568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
186668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
1867a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1868a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
186968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
187068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
1871a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1872a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1873e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
187468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
187568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
187668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
187768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
187868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
187968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
188068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
188168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
188268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
188368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
188468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
188568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
188668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
188768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType value; \
188868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    value.shorty = v; \
188968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
189068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
189168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
189268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
189368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType value; \
189468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    value.shorty = v; \
189568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
189668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
189768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
189868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
189968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
190068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
190168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
190268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
190368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
190468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
190568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
190668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
190768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#undef FIELD_ACCESSORS
190868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
190968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
191068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
191168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
191268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
191368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
191468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                        jvalue* vargs) {
191568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
191668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
191768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
191868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
191951be0a7158b62d6da6a3ccb6fce9f7f677ec3ce3Marcus Oakland    CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
192068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
192168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
192268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
192368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
192468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
192568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
192668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
192768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                        va_list vargs) {
192868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
192968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
193068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
193168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
193268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
193368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
193468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
193568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
193668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list vargs;
193768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(vargs, mid);
193868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
193968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(vargs);
194068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
194168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
194268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
194368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list vargs;
194468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(vargs, mid);
194568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
194668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(vargs);
194768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
194868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
194968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
195068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list vargs;
195168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(vargs, mid);
195268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
195368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(vargs);
195468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
195568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
195668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#define CALL(rtype, name, ptype, shorty) \
195768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
195868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
195968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
196068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
196168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
196268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                             jvalue* vargs) { \
196368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
196468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
196568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
196668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
196768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
196868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
196968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
197068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
197168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
197268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
197368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
197468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
197568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                             va_list vargs) { \
197668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
197768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
197868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
197968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
198068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
198168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
198268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
198368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
198468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list vargs; \
198568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(vargs, mid); \
198668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    rtype result = \
198768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
198868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(vargs); \
198968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result; \
199068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
199168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
199268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
199368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                            ...) { \
199468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list vargs; \
199568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(vargs, mid); \
199668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    rtype result = \
199768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
199868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(vargs); \
199968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result; \
200068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
200168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
200268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
200368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list vargs; \
200468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(vargs, mid); \
200568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    rtype result = \
200668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
200768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(vargs); \
200868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result; \
200968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
201068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
201168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jobject, Object, Primitive::kPrimNot, L)
201268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
201368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jbyte, Byte, Primitive::kPrimByte, B)
201468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jchar, Char, Primitive::kPrimChar, C)
201568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jshort, Short, Primitive::kPrimShort, S)
201668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jint, Int, Primitive::kPrimInt, I)
201768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jlong, Long, Primitive::kPrimLong, J)
201868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jfloat, Float, Primitive::kPrimFloat, F)
201968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jdouble, Double, Primitive::kPrimDouble, D)
202068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#undef CALL
202168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
202268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
202368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
202468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
202568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
202668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Epz", args)) {
202768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
202868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.s = baseEnv(env)->NewString(env, unicode_chars, len);
202968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "s", &result)) {
203068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.s;
203168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
203268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
203368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2034a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2035a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
203668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jstring NewStringUTF(JNIEnv* env, const char* chars) {
203768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
203868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
203968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.u = chars}};
204068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eu", args)) {
204168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
204268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // TODO: stale? show pointer and truncate string.
204368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.s = baseEnv(env)->NewStringUTF(env, chars);
204468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "s", &result)) {
204568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.s;
204668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
204768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
204868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2049a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2050a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
205168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jsize GetStringLength(JNIEnv* env, jstring string) {
205268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
205368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
205468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.s = string}};
205568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Es", args)) {
205668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
205768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.z = baseEnv(env)->GetStringLength(env, string);
205868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "z", &result)) {
205968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.z;
2060a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
2061a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
206268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
2063a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2064a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
206568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
206668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
206768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
206868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.s = string}};
206968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Es", args)) {
207068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
207168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.z = baseEnv(env)->GetStringUTFLength(env, string);
207268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "z", &result)) {
207368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.z;
207468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2075a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
207668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
2077a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2078a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
207968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
208068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
208168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                                 is_copy, false, false));
2082a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2083a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
208468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
208568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
208668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                                is_copy, true, false));
2087a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2088a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
208968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
209068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
209168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                                 is_copy, false, true));
209268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
209368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
209468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
209568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2096a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2097a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2098a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
209968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
210068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
210168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
210268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
210368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
210468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
210568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
210668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
210768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
210868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
210968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
211068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
211168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
211268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EsIIp", args)) {
211368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->GetStringRegion(env, string, start, len, buf);
211468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
211568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
211668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
2117a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
2118a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2119a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
212068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
212168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
212268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
212368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
212468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
212568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
212668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EsIIp", args)) {
212768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
212868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
212968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
213068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
213168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
2132a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2133a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
213468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jsize GetArrayLength(JNIEnv* env, jarray array) {
213568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
213668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
213768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.a = array}};
213868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ea", args)) {
213968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
214068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.z = baseEnv(env)->GetArrayLength(env, array);
214168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "z", &result)) {
214268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.z;
214368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
214468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
214568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
214668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
214768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
214868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
214968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                     jobject initial_element) {
215068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
215168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
215268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] =
215368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
215468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EzcL", args)) {
215568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
215668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // Note: assignability tests of initial_element are done in the base implementation.
215768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
215868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "a", &result)) {
215968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return down_cast<jobjectArray>(result.a);
216068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
216168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
216268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2163a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2164a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2165a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
216668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
216768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
216868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
216968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eaz", args)) {
217068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
217168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
217268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result)) {
217368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
217468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
217568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
217668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2177a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2178a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2179a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
218068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
218168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
218268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
218368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
218468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
218568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // in ArrayStoreExceptions.
218668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EaIL", args)) {
218768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->SetObjectArrayElement(env, array, index, value);
218868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
218968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
219068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
2191a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
2192a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2193a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
219468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
219568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
219668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                      Primitive::kPrimBoolean));
2197a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2198a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
219968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
220068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
220168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                   Primitive::kPrimByte));
220268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
2203a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
220468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jcharArray NewCharArray(JNIEnv* env, jsize length) {
220568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
220668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                   Primitive::kPrimChar));
220768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
2208a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
220968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jshortArray NewShortArray(JNIEnv* env, jsize length) {
221068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
221168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                    Primitive::kPrimShort));
2212a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2213a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
221468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jintArray NewIntArray(JNIEnv* env, jsize length) {
221568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2216a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2217a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
221868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jlongArray NewLongArray(JNIEnv* env, jsize length) {
221968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
222068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                   Primitive::kPrimLong));
222168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
222268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
222368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
222468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
222568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                    Primitive::kPrimFloat));
222668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
222768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
222868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
222968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
223068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                     Primitive::kPrimDouble));
223168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
223268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
223368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
223468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { \
223568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<ctype*>( \
223668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
223768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
223868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
223968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, \
224068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                           jint mode) { \
224168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
224268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
224368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
224468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
224568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                     ctype* buf) { \
224668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
224768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
224868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
224968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
225068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                     const ctype* buf) { \
225168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
225268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
225368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
225468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
225568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
225668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
225768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
225868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
225968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
226068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
226168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
226268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#undef PRIMITIVE_ARRAY_FUNCTIONS
226368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
2264a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint MonitorEnter(JNIEnv* env, jobject obj) {
226568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
226668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
226768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = obj}};
226868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
226968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
227068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->MonitorEnter(env, obj);
227168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
227268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
227368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2274a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
227568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
2276a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2277a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2278a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint MonitorExit(JNIEnv* env, jobject obj) {
227968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
228068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
228168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = obj}};
228268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
228368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
228468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->MonitorExit(env, obj);
228568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
228668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
228768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2288a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
228968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
2290a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2291a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
229268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
229368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
229468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
229568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
229668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eap", args)) {
229768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
229868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.p = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
229968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (result.p != nullptr && soa.ForceCopy()) {
230068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        result.p = GuardedCopy::CreateGuardedPACopy(env, array, is_copy);
230168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
230268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "p", &result)) {
230368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return const_cast<void*>(result.p);
230468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
230568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
230668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2307a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2308a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
230968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
231068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
231168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
231268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonNull(carray);
231368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
231468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eapr", args)) {
231568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (soa.ForceCopy()) {
231668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
231768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
231868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
231968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
232068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
232168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
232268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
2323a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2324a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
232568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
232668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
232768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
232868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
232968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EpJ", args)) {
233068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
233168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // Note: the validity of address and capacity are checked in the base implementation.
233268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
233368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result)) {
233468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
233568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
233668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
233768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2338a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2339a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
234068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
234168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
234268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
234368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = buf}};
234468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
234568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
234668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // Note: this is implemented in the base environment by a GetLongField which will sanity
234768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // check the type of buf in GetLongField above.
234868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
234968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "p", &result)) {
235068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return const_cast<void*>(result.p);
235168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2352a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
235368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2354a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2355a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
235668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
235768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
235868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
235968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = buf}};
236068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
236168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
236268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // Note: this is implemented in the base environment by a GetIntField which will sanity
236368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // check the type of buf in GetIntField above.
236468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
236568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "J", &result)) {
236668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.J;
236768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2368a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
236968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
237068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
237168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
237268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers private:
237368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
237468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<JNIEnvExt*>(env)->vm;
2375a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2376a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
237768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const JNINativeInterface* baseEnv(JNIEnv* env) {
237868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
237968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
238068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
238168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
238268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
238368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
238468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = obj}};
238568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
238668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
238768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (kind) {
238868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case kGlobal:
238968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.L = baseEnv(env)->NewGlobalRef(env, obj);
239068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
239168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case kLocal:
239268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.L = baseEnv(env)->NewLocalRef(env, obj);
239368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
239468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case kWeakGlobal:
239568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
239668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
239768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
239868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected reference kind: " << kind;
239968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
240068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result)) {
240168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
24026a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers        DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
240368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
2404a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
2405a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
240668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
240768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
240868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
240968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
241068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
241168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, function_name);
241268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = obj}};
241368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.Check(soa, true, "EL", args);
24146a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
241568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
241668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (kind) {
241768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case kGlobal:
241868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->DeleteGlobalRef(env, obj);
241968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
242068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case kLocal:
242168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->DeleteLocalRef(env, obj);
242268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
242368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case kWeakGlobal:
242468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->DeleteWeakGlobalRef(env, obj);
242568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
242668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
242768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected reference kind: " << kind;
242868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
242968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
243068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
243168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
2432a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2433a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
243468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
243568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                       const char* name, const char* sig, bool is_static) {
243668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
243768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
243868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
243968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecuu", args)) {
244068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
244168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (is_static) {
244268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
244368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      } else {
244468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
244568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
244668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "m", &result)) {
244768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.m;
244868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2449a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
245068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2451a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2452a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
245368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
245468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                     const char* name, const char* sig, bool is_static) {
245568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
245668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
245768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
245868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecuu", args)) {
245968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
246068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (is_static) {
246168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
246268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      } else {
246368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
246468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
246568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "f", &result)) {
246668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.f;
246768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
246868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
246968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
247068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
247168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
247268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
247368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                               bool is_static, Primitive::Type type) {
247468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
247568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
247668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
247768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
247868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
247968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
248068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      const char* result_check = nullptr;
248168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
248268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimNot:
248368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
248468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
248568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
248668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.L = baseEnv(env)->GetObjectField(env, obj, fid);
248768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
248868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "L";
248968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
249068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
249168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
249268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
249368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
249468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
249568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
249668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "Z";
249768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
249868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
249968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
250068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
250168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
250268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.B = baseEnv(env)->GetByteField(env, obj, fid);
250368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
250468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "B";
250568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
250668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
250768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
250868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
250968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
251068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.C = baseEnv(env)->GetCharField(env, obj, fid);
251168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
251268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "C";
251368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
251468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
251568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
251668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
251768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
251868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.S = baseEnv(env)->GetShortField(env, obj, fid);
251968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
252068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "S";
252168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
252268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
252368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
252468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
252568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
252668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.I = baseEnv(env)->GetIntField(env, obj, fid);
252768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
252868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "I";
252968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
253068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
253168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
253268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
253368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
253468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.J = baseEnv(env)->GetLongField(env, obj, fid);
253568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
253668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "J";
253768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
253868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
253968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
254068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
254168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
254268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.F = baseEnv(env)->GetFloatField(env, obj, fid);
254368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
254468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "F";
254568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
254668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
254768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
254868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
254968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
255068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
255168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
255268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "D";
255368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
255468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimVoid:
255568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected type: " << type;
255668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
255768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
255868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, result_check, &result)) {
255968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result;
256068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
256168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
256268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.J = 0;
256368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result;
2564a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2565a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
256668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
256768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                       bool is_static, Primitive::Type type, JniValueType value) {
256868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
256968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
257068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
257168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
257268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
257368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, sig, args) &&
257468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
257568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
257668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimNot:
257768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
257868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
257968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
258068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetObjectField(env, obj, fid, value.L);
258168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
258268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
258368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
258468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
258568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
258668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
258768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
258868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
258968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
259068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
259168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
259268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
259368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
259468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetByteField(env, obj, fid, value.B);
259568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
259668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
259768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
259868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
259968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
260068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
260168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetCharField(env, obj, fid, value.C);
260268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
260368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
260468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
260568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
260668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
260768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
260868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetShortField(env, obj, fid, value.S);
260968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
261068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
261168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
261268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
261368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
261468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
261568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetIntField(env, obj, fid, value.I);
261668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
261768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
261868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
261968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
262068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
262168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
262268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetLongField(env, obj, fid, value.J);
262368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
262468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
262568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
262668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
262768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
262868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
262968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetFloatField(env, obj, fid, value.F);
263068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
263168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
263268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
263368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
263468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
263568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
263668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
263768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
263868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
263968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimVoid:
264068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected type: " << type;
264168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
264268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
264368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
264468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
264568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
264668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
2647a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2648a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
264968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
265068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                            jclass c, jmethodID mid, InvokeType invoke)
265168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
265268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    bool checked;
265368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    switch (invoke) {
265468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case kVirtual: {
265568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        DCHECK(c == nullptr);
265668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        JniValueType args[3] = {{.E = env}, {.L = obj}, {.m = mid}};
265768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        checked = sc.Check(soa, true, "ELm.", args);
265868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
265968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
266068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case kDirect: {
266168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        JniValueType args[4] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}};
266268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        checked = sc.Check(soa, true, "ELcm.", args);
266368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
266468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
266568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case kStatic: {
266668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        DCHECK(obj == nullptr);
266768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
266868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        checked = sc.Check(soa, true, "Ecm.", args);
266968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
267068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
267168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      default:
267268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        LOG(FATAL) << "Unexpected invoke: " << invoke;
267368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        checked = false;
267468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
267568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
267668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return checked;
267768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
267868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
267968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
268068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                  jmethodID mid, jvalue* vargs, Primitive::Type type,
268168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                  InvokeType invoke) {
268268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
268368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
268468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
268568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke) &&
268668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
268768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      const char* result_check;
268868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
268968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimNot:
269068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "L";
269168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
269268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
269368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
269468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
269568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
269668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
269768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
269868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
269968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
270068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
270168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
270268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
270368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
270468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
270568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
270668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "Z";
270768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
270868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
270968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
271068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
271168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
271268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
271368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
271468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
271568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
271668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
271768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
271868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
271968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
272068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
272168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
272268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "B";
272368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
272468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
272568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
272668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
272768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
272868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
272968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
273068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
273168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
273268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
273368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
273468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
273568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
273668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
273768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
273868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "C";
273968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
274068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
274168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
274268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
274368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
274468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
274568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
274668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
274768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
274868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
274968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
275068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
275168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
275268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
275368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
275468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "S";
275568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
275668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
275768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
275868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
275968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
276068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
276168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
276268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
276368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
276468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
276568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
276668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
276768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
276868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
276968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
277068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "I";
277168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
277268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
277368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
277468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
277568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
277668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
277768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
277868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
277968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
278068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
278168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
278268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
278368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
278468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
278568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
278668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "J";
278768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
278868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
278968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
279068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
279168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
279268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
279368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
279468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
279568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
279668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
279768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
279868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
279968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
280068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
280168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
280268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "F";
280368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
280468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
280568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
280668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
280768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
280868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
280968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
281068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
281168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
281268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
281368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
281468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
281568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
281668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
281768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
281868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "D";
281968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
282068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
282168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
282268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
282368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
282468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
282568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
282668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
282768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
282868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
282968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
283068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
283168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
283268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
283368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimVoid:
283468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "V";
283568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.V = nullptr;
283668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
283768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
283868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
283968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
284068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
284168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
284268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
284368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
284468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
284568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
284668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
284768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
284868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
284968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
285068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
285168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected return type: " << type;
285268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = nullptr;
285368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
285468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, result_check, &result)) {
285568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result;
285668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
285768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
285868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.J = 0;
285968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result;
2860a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2861a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
286268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
286368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                  jmethodID mid, va_list vargs, Primitive::Type type,
286468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                  InvokeType invoke) {
286568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
286668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
286768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
286868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke) &&
286968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
287068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      const char* result_check;
287168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
287268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimNot:
287368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "L";
287468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
287568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
287668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
287768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
287868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
287968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
288068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
288168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
288268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
288368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
288468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
288568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
288668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
288768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
288868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
288968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "Z";
289068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
289168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
289268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
289368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
289468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
289568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
289668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
289768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
289868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
289968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
290068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
290168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
290268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
290368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
290468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
290568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "B";
290668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
290768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
290868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
290968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
291068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
291168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
291268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
291368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
291468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
291568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
291668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
291768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
291868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
291968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
292068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
292168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "C";
292268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
292368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
292468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
292568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
292668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
292768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
292868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
292968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
293068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
293168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
293268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
293368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
293468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
293568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
293668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
293768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "S";
293868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
293968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
294068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
294168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
294268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
294368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
294468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
294568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
294668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
294768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
294868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
294968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
295068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
295168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
295268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
295368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "I";
295468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
295568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
295668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
295768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
295868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
295968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
296068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
296168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
296268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
296368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
296468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
296568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
296668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
296768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
296868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
296968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "J";
297068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
297168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
297268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
297368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
297468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
297568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
297668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
297768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
297868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
297968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
298068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
298168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
298268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
298368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
298468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
298568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "F";
298668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
298768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
298868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
298968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
299068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
299168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
299268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
299368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
299468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
299568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
299668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
299768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
299868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
299968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
300068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
300168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "D";
300268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
300368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
300468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
300568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
300668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
300768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
300868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
300968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
301068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
301168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
301268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
301368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
301468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
301568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
301668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimVoid:
301768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "V";
301868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.V = nullptr;
301968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
302068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
302168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
302268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
302368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
302468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
302568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
302668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
302768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
302868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
302968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
303068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
303168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
303268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
303368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
303468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected return type: " << type;
303568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = nullptr;
303668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
303768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, result_check, &result)) {
303868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result;
303968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
3040a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
304168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.J = 0;
304268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result;
3043a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3044a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
304568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
304668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                            jboolean* is_copy, bool utf, bool critical) {
304768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
304868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
304968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(flags, function_name);
305068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
305168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Esp", args)) {
305268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
305368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (utf) {
305468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        CHECK(!critical);
305568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        result.u = baseEnv(env)->GetStringUTFChars(env, string, is_copy);
305668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      } else {
305768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (critical) {
305868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.p = baseEnv(env)->GetStringCritical(env, string, is_copy);
305968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
306068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.p = baseEnv(env)->GetStringChars(env, string, is_copy);
306168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
306268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
306368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // TODO: could we be smarter about not copying when local_is_copy?
306468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (result.p != nullptr && soa.ForceCopy()) {
306568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (utf) {
306668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          size_t length_in_bytes = strlen(result.u) + 1;
306768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.u =
306868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              reinterpret_cast<const char*>(GuardedCopy::Create(result.u, length_in_bytes, false));
306968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
307068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
307168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.p =
307268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              reinterpret_cast<const jchar*>(GuardedCopy::Create(result.p, length_in_bytes, false));
307368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
307468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (is_copy != nullptr) {
307568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *is_copy = JNI_TRUE;
307668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
307768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
307868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
307968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return utf ? result.u : result.p;
308068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
308168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
308268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
3083a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3084a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
308568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
308668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                         const void* chars, bool utf, bool critical) {
308768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
308868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    int flags = kFlag_ExcepOkay | kFlag_Release;
308968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (critical) {
309068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      flags |= kFlag_CritRelease;
309168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
309268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(flags, function_name);
309368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonNull(chars);
309468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
309568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (force_copy_ok && soa.ForceCopy()) {
309668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
309768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
309868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (force_copy_ok) {
309968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
310068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
310168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (utf) {
310268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          CHECK(!critical);
310368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
310468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
310568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (critical) {
310668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
310768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
310868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
310968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
311068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
311168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        JniValueType result;
311268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.Check(soa, false, "V", &result);
311368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
311468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
3115a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3116a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
311768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
311868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                  Primitive::Type type) {
311968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
31206a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
312168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.z = length}};
312268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ez", args)) {
312368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
312468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
312568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
312668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewBooleanArray(env, length);
312768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
312868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
312968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewByteArray(env, length);
313068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
313168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
313268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewCharArray(env, length);
313368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
313468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
313568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewShortArray(env, length);
313668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
313768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
313868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewIntArray(env, length);
313968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
314068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
314168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewLongArray(env, length);
314268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
314368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
314468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewFloatArray(env, length);
314568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
314668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
314768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewDoubleArray(env, length);
314868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
314968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
315068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected primitive type: " << type;
315168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
315268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "a", &result)) {
315368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.a;
315468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
315568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
315668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
315768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
315868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
315968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
316068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                         JNIEnv* env, jarray array, jboolean* is_copy) {
316168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
316268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
316368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
316468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
316568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
316668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
316768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
316868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.p = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
316968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                           is_copy);
317068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
317168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
317268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.p = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array),
317368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                        is_copy);
317468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
317568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
317668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.p = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array),
317768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                        is_copy);
317868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
317968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
318068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.p = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array),
318168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                         is_copy);
318268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
318368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
318468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.p = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
318568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
318668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
318768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.p = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array),
318868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                        is_copy);
318968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
319068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
319168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.p = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array),
319268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                         is_copy);
319368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
319468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
319568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.p = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array),
319668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                          is_copy);
319768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
319868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
319968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected primitive type: " << type;
320068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
320168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (result.p != nullptr && soa.ForceCopy()) {
320268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        result.p = GuardedCopy::CreateGuardedPACopy(env, array, is_copy);
320368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (is_copy != nullptr) {
320468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *is_copy = JNI_TRUE;
320568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
320668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
320768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "p", &result)) {
320868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return const_cast<void*>(result.p);
320968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
321068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
321168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
321268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
321368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
321468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
321568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                            JNIEnv* env, jarray array, void* elems, jint mode) {
321668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
321768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, function_name);
321868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
321968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (soa.ForceCopy()) {
322068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
322168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
322268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (!soa.ForceCopy() || elems != nullptr) {
322368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
322468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (sc.Check(soa, true, "Eapr", args)) {
322568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (type) {
322668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimBoolean:
322768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
322868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                        reinterpret_cast<jboolean*>(elems), mode);
322968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
323068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimByte:
323168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
323268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                     reinterpret_cast<jbyte*>(elems), mode);
323368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
323468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimChar:
323568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
323668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                     reinterpret_cast<jchar*>(elems), mode);
323768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
323868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimShort:
323968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
324068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                      reinterpret_cast<jshort*>(elems), mode);
324168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
324268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimInt:
324368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
324468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                    reinterpret_cast<jint*>(elems), mode);
324568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
324668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimLong:
324768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
324868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                     reinterpret_cast<jlong*>(elems), mode);
324968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
325068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimFloat:
325168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
325268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                      reinterpret_cast<jfloat*>(elems), mode);
325368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
325468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimDouble:
325568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
325668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                       reinterpret_cast<jdouble*>(elems), mode);
325768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
325868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
325968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected primitive type: " << type;
326068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
326168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          JniValueType result;
326268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.V = nullptr;
326368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          sc.Check(soa, false, "V", &result);
326468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
326568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
326668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
326768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
326868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
326968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
327068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                      jarray array, jsize start, jsize len, void* buf) {
327168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
327268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
327368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
327468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
327568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
327668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
327768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
327868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
327968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
328068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                              reinterpret_cast<jboolean*>(buf));
328168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
328268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
328368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
328468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                           reinterpret_cast<jbyte*>(buf));
328568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
328668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
328768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
328868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                           reinterpret_cast<jchar*>(buf));
328968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
329068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
329168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
329268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                            reinterpret_cast<jshort*>(buf));
329368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
329468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
329568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
329668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                          reinterpret_cast<jint*>(buf));
329768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
329868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
329968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
330068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                           reinterpret_cast<jlong*>(buf));
330168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
330268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
330368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
330468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                            reinterpret_cast<jfloat*>(buf));
330568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
330668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
330768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
330868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                             reinterpret_cast<jdouble*>(buf));
330968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
331068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
331168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected primitive type: " << type;
331268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
331368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
331468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
331568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
331668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
331768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
331868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
331968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
332068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                      jarray array, jsize start, jsize len, const void* buf) {
332168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
332268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
332368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
332468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
332568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
332668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
332768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
332868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
332968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
333068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                              reinterpret_cast<const jboolean*>(buf));
333168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
333268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
333368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
333468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                           reinterpret_cast<const jbyte*>(buf));
333568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
333668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
333768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
333868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                           reinterpret_cast<const jchar*>(buf));
333968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
334068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
334168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
334268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                              reinterpret_cast<const jshort*>(buf));
334368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
334468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
334568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
334668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                          reinterpret_cast<const jint*>(buf));
334768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
334868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
334968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
335068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                              reinterpret_cast<const jlong*>(buf));
335168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
335268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
335368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
335468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                            reinterpret_cast<const jfloat*>(buf));
335568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
335668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
335768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
335868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                             reinterpret_cast<const jdouble*>(buf));
335968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
336068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
336168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected primitive type: " << type;
336268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
336368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
336468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
336568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
336668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
3367a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3368a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
3369a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3370a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNINativeInterface gCheckNativeInterface = {
3371ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved0.
3372ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved1.
3373ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved2.
3374ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved3.
3375a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetVersion,
3376a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::DefineClass,
3377a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::FindClass,
3378a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::FromReflectedMethod,
3379a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::FromReflectedField,
3380a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ToReflectedMethod,
3381a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetSuperclass,
3382a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::IsAssignableFrom,
3383a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ToReflectedField,
3384a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::Throw,
3385a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ThrowNew,
3386a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ExceptionOccurred,
3387a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ExceptionDescribe,
3388a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ExceptionClear,
3389a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::FatalError,
3390a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::PushLocalFrame,
3391a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::PopLocalFrame,
3392a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewGlobalRef,
3393a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::DeleteGlobalRef,
3394a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::DeleteLocalRef,
3395a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::IsSameObject,
3396a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewLocalRef,
3397a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::EnsureLocalCapacity,
3398a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::AllocObject,
3399a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewObject,
3400a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewObjectV,
3401a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewObjectA,
3402a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetObjectClass,
3403a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::IsInstanceOf,
3404a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetMethodID,
3405a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallObjectMethod,
3406a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallObjectMethodV,
3407a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallObjectMethodA,
3408a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallBooleanMethod,
3409a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallBooleanMethodV,
3410a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallBooleanMethodA,
3411a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallByteMethod,
3412a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallByteMethodV,
3413a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallByteMethodA,
3414a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallCharMethod,
3415a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallCharMethodV,
3416a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallCharMethodA,
3417a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallShortMethod,
3418a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallShortMethodV,
3419a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallShortMethodA,
3420a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallIntMethod,
3421a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallIntMethodV,
3422a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallIntMethodA,
3423a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallLongMethod,
3424a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallLongMethodV,
3425a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallLongMethodA,
3426a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallFloatMethod,
3427a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallFloatMethodV,
3428a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallFloatMethodA,
3429a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallDoubleMethod,
3430a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallDoubleMethodV,
3431a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallDoubleMethodA,
3432a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallVoidMethod,
3433a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallVoidMethodV,
3434a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallVoidMethodA,
3435a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualObjectMethod,
3436a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualObjectMethodV,
3437a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualObjectMethodA,
3438a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualBooleanMethod,
3439a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualBooleanMethodV,
3440a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualBooleanMethodA,
3441a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualByteMethod,
3442a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualByteMethodV,
3443a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualByteMethodA,
3444a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualCharMethod,
3445a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualCharMethodV,
3446a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualCharMethodA,
3447a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualShortMethod,
3448a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualShortMethodV,
3449a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualShortMethodA,
3450a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualIntMethod,
3451a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualIntMethodV,
3452a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualIntMethodA,
3453a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualLongMethod,
3454a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualLongMethodV,
3455a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualLongMethodA,
3456a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualFloatMethod,
3457a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualFloatMethodV,
3458a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualFloatMethodA,
3459a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualDoubleMethod,
3460a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualDoubleMethodV,
3461a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualDoubleMethodA,
3462a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualVoidMethod,
3463a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualVoidMethodV,
3464a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualVoidMethodA,
3465a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetFieldID,
3466a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetObjectField,
3467a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetBooleanField,
3468a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetByteField,
3469a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetCharField,
3470a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetShortField,
3471a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetIntField,
3472a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetLongField,
3473a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetFloatField,
3474a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDoubleField,
3475a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetObjectField,
3476a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetBooleanField,
3477a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetByteField,
3478a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetCharField,
3479a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetShortField,
3480a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetIntField,
3481a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetLongField,
3482a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetFloatField,
3483a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetDoubleField,
3484a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticMethodID,
3485a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticObjectMethod,
3486a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticObjectMethodV,
3487a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticObjectMethodA,
3488a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticBooleanMethod,
3489a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticBooleanMethodV,
3490a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticBooleanMethodA,
3491a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticByteMethod,
3492a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticByteMethodV,
3493a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticByteMethodA,
3494a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticCharMethod,
3495a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticCharMethodV,
3496a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticCharMethodA,
3497a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticShortMethod,
3498a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticShortMethodV,
3499a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticShortMethodA,
3500a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticIntMethod,
3501a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticIntMethodV,
3502a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticIntMethodA,
3503a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticLongMethod,
3504a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticLongMethodV,
3505a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticLongMethodA,
3506a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticFloatMethod,
3507a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticFloatMethodV,
3508a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticFloatMethodA,
3509a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticDoubleMethod,
3510a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticDoubleMethodV,
3511a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticDoubleMethodA,
3512a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticVoidMethod,
3513a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticVoidMethodV,
3514a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticVoidMethodA,
3515a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticFieldID,
3516a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticObjectField,
3517a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticBooleanField,
3518a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticByteField,
3519a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticCharField,
3520a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticShortField,
3521a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticIntField,
3522a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticLongField,
3523a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticFloatField,
3524a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticDoubleField,
3525a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticObjectField,
3526a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticBooleanField,
3527a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticByteField,
3528a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticCharField,
3529a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticShortField,
3530a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticIntField,
3531a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticLongField,
3532a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticFloatField,
3533a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticDoubleField,
3534a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewString,
3535a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringLength,
3536a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringChars,
3537a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseStringChars,
3538a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewStringUTF,
3539a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringUTFLength,
3540a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringUTFChars,
3541a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseStringUTFChars,
3542a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetArrayLength,
3543a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewObjectArray,
3544a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetObjectArrayElement,
3545a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetObjectArrayElement,
3546a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewBooleanArray,
3547a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewByteArray,
3548a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewCharArray,
3549a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewShortArray,
3550a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewIntArray,
3551a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewLongArray,
3552a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewFloatArray,
3553a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewDoubleArray,
3554a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetBooleanArrayElements,
3555a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetByteArrayElements,
3556a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetCharArrayElements,
3557a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetShortArrayElements,
3558a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetIntArrayElements,
3559a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetLongArrayElements,
3560a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetFloatArrayElements,
3561a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDoubleArrayElements,
3562a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseBooleanArrayElements,
3563a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseByteArrayElements,
3564a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseCharArrayElements,
3565a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseShortArrayElements,
3566a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseIntArrayElements,
3567a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseLongArrayElements,
3568a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseFloatArrayElements,
3569a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseDoubleArrayElements,
3570a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetBooleanArrayRegion,
3571a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetByteArrayRegion,
3572a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetCharArrayRegion,
3573a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetShortArrayRegion,
3574a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetIntArrayRegion,
3575a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetLongArrayRegion,
3576a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetFloatArrayRegion,
3577a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDoubleArrayRegion,
3578a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetBooleanArrayRegion,
3579a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetByteArrayRegion,
3580a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetCharArrayRegion,
3581a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetShortArrayRegion,
3582a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetIntArrayRegion,
3583a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetLongArrayRegion,
3584a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetFloatArrayRegion,
3585a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetDoubleArrayRegion,
3586a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::RegisterNatives,
3587a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::UnregisterNatives,
3588a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::MonitorEnter,
3589a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::MonitorExit,
3590a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetJavaVM,
3591a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringRegion,
3592a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringUTFRegion,
3593a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetPrimitiveArrayCritical,
3594a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleasePrimitiveArrayCritical,
3595a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringCritical,
3596a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseStringCritical,
3597a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewWeakGlobalRef,
3598a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::DeleteWeakGlobalRef,
3599a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ExceptionCheck,
3600a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewDirectByteBuffer,
3601a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDirectBufferAddress,
3602a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDirectBufferCapacity,
3603a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetObjectRefType,
3604a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
3605a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3606a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNINativeInterface* GetCheckJniNativeInterface() {
3607a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  return &gCheckNativeInterface;
3608a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}
3609a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3610a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesclass CheckJII {
3611ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes public:
3612a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint DestroyJavaVM(JavaVM* vm) {
361368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
361468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.v = vm}};
361568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
361668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
361768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.i = BaseVm(vm)->DestroyJavaVM(vm);
361868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
361968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result.i;
3620a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3621a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3622a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
362368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
362468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
362568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
362668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
362768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
362868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
362968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result.i;
3630a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3631a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3632a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
363368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
363468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
363568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
363668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
363768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
363868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
363968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result.i;
3640a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3641a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3642a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint DetachCurrentThread(JavaVM* vm) {
364368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
364468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.v = vm}};
364568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
364668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
364768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.i = BaseVm(vm)->DetachCurrentThread(vm);
364868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
364968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result.i;
3650a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3651a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
365268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
365368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
365468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
365568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
365668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
365768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
365868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
365968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result.i;
3660a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3661a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3662a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes private:
366368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
366468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
3665a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3666a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
3667a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3668a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNIInvokeInterface gCheckInvokeInterface = {
3669ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved0
3670ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved1
3671ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved2
3672a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::DestroyJavaVM,
3673a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::AttachCurrentThread,
3674a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::DetachCurrentThread,
3675a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::GetEnv,
3676a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::AttachCurrentThreadAsDaemon
3677a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
3678a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3679a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNIInvokeInterface* GetCheckJniInvokeInterface() {
3680a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  return &gCheckInvokeInterface;
3681a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}
3682a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3683a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}  // namespace art
3684