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
22c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier#include "art_field-inl.h"
233d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier#include "art_method-inl.h"
2407ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
25c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers#include "base/to_str.h"
26a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include "class_linker.h"
272dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "class_linker-inl.h"
284f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h"
291d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/space.h"
3068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#include "java_vm_ext.h"
31277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#include "jni_internal.h"
322dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h"
332dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h"
342dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h"
35b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers#include "mirror/string-inl.h"
362dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/throwable.h"
3758df32711162823647356afe25ae2cde04133563Jeff Hao#include "runtime.h"
3800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h"
39a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include "thread.h"
4068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#include "well_known_classes.h"
41a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
42a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesnamespace art {
43a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
44a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/*
45a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
46a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *      JNI function helpers
47a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
48a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */
49a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
503f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes// Flags passed into ScopedCheck.
51a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define kFlag_Default       0x0000
52a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
533f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritBad       0x0000      // Calling while in critical is not allowed.
543f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritOkay      0x0001      // Calling while in critical is allowed.
553f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritGet       0x0002      // This is a critical "get".
563f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritRelease   0x0003      // This is a critical "release".
573f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritMask      0x0003      // Bit mask to get "crit" value.
58a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
593f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_ExcepBad      0x0000      // Raised exceptions are not allowed.
603f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_ExcepOkay     0x0004      // Raised exceptions are allowed.
61a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
623f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_Release       0x0010      // Are we in a non-critical release function?
633f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_NullableUtf   0x0020      // Are our UTF parameters nullable?
64a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
653f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_Invocation    0x8000      // Part of the invocation interface (JavaVM*).
66a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
67485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes#define kFlag_ForceTrace    0x80000000  // Add this to a JNI function's flags if you want to trace every call.
6868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers/*
6968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Java primitive types:
7068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * B - jbyte
7168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * C - jchar
7268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * D - jdouble
7368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * F - jfloat
7468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * I - jint
7568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * J - jlong
7668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * S - jshort
7768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Z - jboolean (shown as true and false)
7868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * V - void
7968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *
8068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Java reference types:
8168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * L - jobject
8268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * a - jarray
8368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * c - jclass
8468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * s - jstring
8568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * t - jthrowable
8668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *
8768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * JNI types:
8868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
8968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * f - jfieldID
9068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION)
9168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * m - jmethodID
9268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * p - void*
9368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * r - jint (for release mode arguments)
9468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * u - const char* (Modified UTF-8)
9568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * z - jsize (for lengths; use i if negative values are okay)
9668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * v - JavaVM*
9768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * w - jobjectRefType
9868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * E - JNIEnv*
9968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * . - no argument; just print "..." (used for varargs JNI calls)
10068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *
10168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers */
10268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogersunion JniValueType {
10368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jarray a;
10468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jboolean b;
10568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jclass c;
10668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jfieldID f;
10768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jint i;
10868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jmethodID m;
10968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const void* p;  // Pointer.
11068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jint r;  // Release mode.
11168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jstring s;
11268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jthrowable t;
11368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const char* u;  // Modified UTF-8.
11468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  JavaVM* v;
11568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jobjectRefType w;
11668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jsize z;
11768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jbyte B;
11868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jchar C;
11968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jdouble D;
12068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  JNIEnv* E;
12168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jfloat F;
12268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jint I;
12368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jlong J;
12468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jobject L;
12568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jshort S;
12668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const void* V;  // void
12768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jboolean Z;
128a09576416788b916095739e43a16917e7948f3a4Elliott Hughes};
129a09576416788b916095739e43a16917e7948f3a4Elliott Hughes
130a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesclass ScopedCheck {
131ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes public:
13268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  explicit ScopedCheck(int flags, const char* functionName, bool has_method = true)
13368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      : function_name_(functionName), flags_(flags), indent_(0), has_method_(has_method) {
13400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
13500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
13668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  ~ScopedCheck() {}
137a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
13881ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
13981ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
14081ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
14181ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // circumstances, but this is incorrect.
14268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckClassName(const char* class_name) {
1432d10b206f9d0b97396b7dadb9a6415cd39efd341Ian Rogers    if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
14468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("illegal class name '%s'\n"
14568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             "    (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
14668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             class_name);
14768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
148a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
14968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
150a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
151a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
152a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
153a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that this instance field ID is valid for this object.
154a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
155a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Assumes "jobj" has already been validated.
156a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
15768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
158b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
15968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
16068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (o == nullptr) {
16168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("field operation on NULL object: %p", java_object);
16268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
16368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
16468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
1654c13a3ff475f206c4d0a86ee2595c45392fd942fMathieu Chartier      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
16668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("field operation on invalid %s: %p",
16768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
16868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             java_object);
16968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
170a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
171a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
172c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    ArtField* f = CheckFieldID(soa, fid);
173ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (f == nullptr) {
17468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
17532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
1762dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Class* c = o->GetClass();
17761c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier    if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
17868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("jfieldID %s not valid for an object of class %s",
17968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             PrettyField(f).c_str(), PrettyTypeOf(o).c_str());
18068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
181a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
18268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
183a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
184a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
185a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
1862cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier   * Verify that the pointer value is non-null.
187a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
18868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckNonNull(const void* ptr) {
18968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (UNLIKELY(ptr == nullptr)) {
19068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("non-nullable argument was NULL");
19168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
192a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
19368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
194a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
195a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
196a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
197a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that the method's return type matches the type of call.
198a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * 'expectedType' will be "L" for all objects, including arrays.
199a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
20068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
20168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                         jmethodID mid, Primitive::Type type, InvokeType invoke)
202b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2033d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    ArtMethod* m = CheckMethodID(soa, mid);
204ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (m == nullptr) {
20568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
20632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
20768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (type != Primitive::GetType(m->GetShorty()[0])) {
20868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("the return type of %s does not match %s", function_name_, PrettyMethod(m).c_str());
20968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
2103f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    }
21168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    bool is_static = (invoke == kStatic);
21268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (is_static != m->IsStatic()) {
21368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (is_static) {
21468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("calling non-static method %s with %s",
21568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               PrettyMethod(m).c_str(), function_name_);
216a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      } else {
21768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("calling static method %s with %s",
21868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               PrettyMethod(m).c_str(), function_name_);
21968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
22068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
22168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
22268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (invoke != kVirtual) {
22368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      mirror::Class* c = soa.Decode<mirror::Class*>(jc);
22468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
22568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
22668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            PrettyMethod(m).c_str(), PrettyClass(c).c_str());
22768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
22868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
22968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
23068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (invoke != kStatic) {
23168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      mirror::Object* o = soa.Decode<mirror::Object*>(jobj);
232a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier      if (o == nullptr) {
233a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier        AbortF("can't call %s on null object", PrettyMethod(m).c_str());
234a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier        return false;
235a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier      } else if (!o->InstanceOf(m->GetDeclaringClass())) {
23668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
23768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
238a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
239a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
24068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
241a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
242a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
243a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
244a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that this static field ID is valid for this class.
245a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
246a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Assumes "java_class" has already been validated.
247a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
24868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
249b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
25068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
251c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    ArtField* f = CheckFieldID(soa, fid);
252ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (f == nullptr) {
25368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
25432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
255a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    if (f->GetDeclaringClass() != c) {
25668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("static jfieldID %p not valid for class %s", fid, PrettyClass(c).c_str());
25768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
258a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
25968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
260a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
261a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
262a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
263e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes   * Verify that "mid" is appropriate for "java_class".
264a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
265a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * A mismatch isn't dangerous, because the jmethodID defines the class.  In
266e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes   * fact, java_class is unused in the implementation.  It's best if we don't
267a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * allow bad code in the system though.
268a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
269e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes   * Instances of "java_class" must be instances of the method's declaring class.
270a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
27168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
272b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2733d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    ArtMethod* m = CheckMethodID(soa, mid);
274ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (m == nullptr) {
27568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
27632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
27768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
27867fe2b41a6afccf6ab1a58879eae3e0e8f3d6c7aBrian Carlstrom    if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
27968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("can't call static %s on class %s", PrettyMethod(m).c_str(), PrettyClass(c).c_str());
28068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
281a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
28268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
283a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
284a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
285a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
286a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that "mid" is appropriate for "jobj".
287a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
288a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Make sure the object is an instance of the method's declaring class.
289a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * (Note the mid might point to a declaration in an interface; this
290a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * will be handled automatically by the instanceof check.)
291a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
29268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
293b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2943d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    ArtMethod* m = CheckMethodID(soa, mid);
295ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (m == nullptr) {
29668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
29732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
29868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
299a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier    if (o == nullptr) {
300a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier      AbortF("can't call %s on null object", PrettyMethod(m).c_str());
301a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier      return false;
302a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier    } else if (!o->InstanceOf(m->GetDeclaringClass())) {
30368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
30468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
305a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
30668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
307a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
308a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
309a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /**
310a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * The format string is a sequence of the following characters,
311a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * and must be followed by arguments of the corresponding types
312a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * in the same order.
313a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
314a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Java primitive types:
315a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * B - jbyte
316a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * C - jchar
317a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * D - jdouble
318a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * F - jfloat
319a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * I - jint
320a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * J - jlong
321a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * S - jshort
322a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Z - jboolean (shown as true and false)
323a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * V - void
324a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
325a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Java reference types:
326a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * L - jobject
327a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * a - jarray
328a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * c - jclass
329a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * s - jstring
330a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
331a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * JNI types:
332a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
333a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * f - jfieldID
334a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * m - jmethodID
335a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * p - void*
336a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * r - jint (for release mode arguments)
33778090d119d5e23ff35ecddac1f4a98e4c050bb07Elliott Hughes   * u - const char* (Modified UTF-8)
338a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * z - jsize (for lengths; use i if negative values are okay)
339a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * v - JavaVM*
340a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * E - JNIEnv*
341a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * . - no argument; just print "..." (used for varargs JNI calls)
342a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
343a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
344a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
34568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
34668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
3473d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    ArtMethod* traceMethod = nullptr;
34868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (has_method_ && soa.Vm()->IsTracingEnabled()) {
349a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      // We need to guard some of the invocation interface's calls: a bad caller might
350a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
351a09576416788b916095739e43a16917e7948f3a4Elliott Hughes      Thread* self = Thread::Current();
352ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
353ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        traceMethod = self->GetCurrentMethod(nullptr);
354a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
355a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
356a09576416788b916095739e43a16917e7948f3a4Elliott Hughes
357ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (((flags_ & kFlag_ForceTrace) != 0) ||
35868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
359a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      std::string msg;
36068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      for (size_t i = 0; fmt[i] != '\0'; ++i) {
36168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
36268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (fmt[i + 1] != '\0') {
36368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(&msg, ", ");
36468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
36568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
36668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
36768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if ((flags_ & kFlag_ForceTrace) != 0) {
36868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
36968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      } else if (entry) {
37068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (has_method_) {
37168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          std::string methodName(PrettyMethod(traceMethod, false));
37268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
37368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          indent_ = methodName.size() + 1;
374a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else {
37568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
37668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          indent_ = 0;
37768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
37868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      } else {
37968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
38068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
38168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
38268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
38368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // We always do the thorough checks on entry, and never on exit...
38468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (entry) {
38568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      for (size_t i = 0; fmt[i] != '\0'; ++i) {
38668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
38768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          return false;
388a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
38968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
39068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
39168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
39268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
39368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
39468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
39568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
396def194e182ce703077e20bb59025998039fadb75Andreas Gampe    if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
39768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // We need to guard some of the invocation interface's calls: a bad caller might
39868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
39968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      Thread* self = Thread::Current();
40068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
40168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        ScopedObjectAccess soa(self);
4023d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
40368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
40468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
40568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
40668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (should_trace) {
40768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      std::string msg;
40868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      for (size_t i = 0; fmt[i] != '\0'; ++i) {
40968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        TraceNonHeapValue(fmt[i], args[i], &msg);
41068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (fmt[i + 1] != '\0') {
411a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          StringAppendF(&msg, ", ");
412a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
413a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
414a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
415485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes      if ((flags_ & kFlag_ForceTrace) != 0) {
416485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes        LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
417485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes      } else if (entry) {
41832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        if (has_method_) {
41968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          Thread* self = Thread::Current();
42068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          ScopedObjectAccess soa(self);
4213d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
422a09576416788b916095739e43a16917e7948f3a4Elliott Hughes          std::string methodName(PrettyMethod(traceMethod, false));
42332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
42432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          indent_ = methodName.size() + 1;
425a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else {
42632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
42732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          indent_ = 0;
428a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
429a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      } else {
43032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
431a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
432a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
433a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
434a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // We always do the thorough checks on entry, and never on exit...
435a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    if (entry) {
43668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      for (size_t i = 0; fmt[i] != '\0'; ++i) {
43768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (!CheckNonHeapValue(fmt[i], args[i])) {
43868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          return false;
439a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
440a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
441a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
44268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
44368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
44468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
44568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
44668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
44768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Object* method = soa.Decode<mirror::Object*>(jmethod);
44868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (method == nullptr) {
44968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected non-null method");
45068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
45168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
45268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Class* c = method->GetClass();
45368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Method) != c &&
45468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
45568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected java.lang.reflect.Method or "
45668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          "java.lang.reflect.Constructor but got object of type %s: %p",
45768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          PrettyTypeOf(method).c_str(), jmethod);
45868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
45968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
46068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
46168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
46268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
46368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckConstructor(ScopedObjectAccess& soa, jmethodID mid)
46468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
4653d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    ArtMethod* method = soa.DecodeMethod(mid);
46668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (method == nullptr) {
46768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected non-null constructor");
46868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
46968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
47068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!method->IsConstructor() || method->IsStatic()) {
4713d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      AbortF("expected a constructor but %s: %p", PrettyMethod(method).c_str(), mid);
47268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
47368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
47468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
47568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
47668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
47768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
47868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
47968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Object* field = soa.Decode<mirror::Object*>(jfield);
48068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (field == nullptr) {
48168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected non-null java.lang.reflect.Field");
48268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
48368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
48468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Class* c = field->GetClass();
48568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Field) != c) {
48668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
48768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             PrettyTypeOf(field).c_str(), jfield);
48868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
48968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
49068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
49168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
49268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
49368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
49468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
49568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Object* obj = soa.Decode<mirror::Object*>(jobj);
49668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!obj->GetClass()->IsThrowableClass()) {
49768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected java.lang.Throwable but got object of type "
49868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             "%s: %p", PrettyTypeOf(obj).c_str(), obj);
49968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
50068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
50168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
50268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
50368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
50468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
50568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
50668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Class* c = soa.Decode<mirror::Class*>(jc);
50768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!c->IsThrowableClass()) {
50868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected java.lang.Throwable class but got object of "
50968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             "type %s: %p", PrettyDescriptor(c).c_str(), c);
51068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
51168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
51268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
51368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
51468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
5156a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
51668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    IndirectRefKind found_kind;
51768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (expected_kind == kLocal) {
51868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      found_kind = GetIndirectRefKind(obj);
51968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
52068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        found_kind = kLocal;
52168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
52268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    } else {
52368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      found_kind = GetIndirectRefKind(obj);
52468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
52568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (obj != nullptr && found_kind != expected_kind) {
52668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected reference of kind %s but found %s: %p",
52768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             ToStr<IndirectRefKind>(expected_kind).c_str(),
52868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             ToStr<IndirectRefKind>(GetIndirectRefKind(obj)).c_str(),
52968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             obj);
53068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
53168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
53268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
53368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
53468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
53568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
53668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
53768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Class* c = soa.Decode<mirror::Class*>(jc);
53868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!c->IsInstantiableNonArray()) {
53968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("can't make objects of type %s: %p", PrettyDescriptor(c).c_str(), c);
54068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
54168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
54268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
54368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
54468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
54568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
54668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
54768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!CheckArray(soa, array)) {
54868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
54968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
55068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Array* a = soa.Decode<mirror::Array*>(array);
55168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
55268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("incompatible array type %s expected %s[]: %p",
55368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             PrettyDescriptor(a->GetClass()).c_str(), PrettyDescriptor(type).c_str(), array);
55468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
55568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
55668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
55768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
55868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
55968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
56068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                        Primitive::Type type)
56168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
56268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
56368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
56468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
56568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
56668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
56768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
568c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    ArtField* field = soa.DecodeField(fid);
56968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    DCHECK(field != nullptr);  // Already checked by Check.
57068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (is_static != field->IsStatic()) {
57168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("attempt to access %s field %s: %p",
57268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             field->IsStatic() ? "static" : "non-static", PrettyField(field).c_str(), fid);
57368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
57468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
57568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (type != field->GetTypeAsPrimitiveType()) {
57668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
57768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             PrettyField(field).c_str(), PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
57868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             PrettyDescriptor(type).c_str(), fid);
57968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
58068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
58168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (is_static) {
58268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      mirror::Object* o = soa.Decode<mirror::Object*>(obj);
58368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (o == nullptr || !o->IsClass()) {
58468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("attempt to access static field %s with a class argument of type %s: %p",
58568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid);
58668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
58768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
58868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      mirror::Class* c = o->AsClass();
58968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (field->GetDeclaringClass() != c) {
59068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
59168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               PrettyField(field).c_str(), PrettyDescriptor(c).c_str(), fid);
59268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
59368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
59468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    } else {
59568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      mirror::Object* o = soa.Decode<mirror::Object*>(obj);
59668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
59768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("attempt to access field %s from an object argument of type %s: %p",
59868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid);
59968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
60068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
60168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
60268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
603a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
604a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
60568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers private:
606a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes  enum InstanceKind {
607a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    kClass,
6080f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes    kDirectByteBuffer,
6090f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes    kObject,
6100f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes    kString,
6110f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes    kThrowable,
612a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes  };
613a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
614a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes  /*
6152cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier   * Verify that "jobj" is a valid non-null object reference, and points to
616a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   * an instance of expectedClass.
617a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   *
618a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   * Because we're looking at an object on the GC heap, we have to switch
619a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   * to "running" mode before doing the checks.
620a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   */
62168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
622b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
623ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const char* what = nullptr;
624a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    switch (kind) {
625a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kClass:
626a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "jclass";
627a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
628a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kDirectByteBuffer:
629a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "direct ByteBuffer";
630a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
631a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kObject:
632a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "jobject";
633a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
634a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kString:
635a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "jstring";
636a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
637a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kThrowable:
638a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "jthrowable";
639a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
640a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    default:
6417b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes      LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
642a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
643a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
644ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (java_object == nullptr) {
64568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (null_ok) {
64668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return true;
64768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      } else {
64868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("%s received NULL %s", function_name_, what);
64968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
65068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
651a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
652a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
65368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Object* obj = soa.Decode<mirror::Object*>(java_object);
654c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    if (obj == nullptr) {
655c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      // Either java_object is invalid or is a cleared weak.
656c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
657c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      bool okay;
658c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      if (GetIndirectRefKind(ref) != kWeakGlobal) {
659c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        okay = false;
660c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      } else {
661c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
662c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
663c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      }
664c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      if (!okay) {
665c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        AbortF("%s is an invalid %s: %p (%p)",
666c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers               what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
667c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers               java_object, obj);
668c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        return false;
669c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      }
670c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    }
671c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers
672590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) {
6734c13a3ff475f206c4d0a86ee2595c45392fd942fMathieu Chartier      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
67468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("%s is an invalid %s: %p (%p)",
67568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
67668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             java_object, obj);
677a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      return false;
678a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
679a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
680a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    bool okay = true;
681a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    switch (kind) {
682a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kClass:
683a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      okay = obj->IsClass();
684a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
685a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kDirectByteBuffer:
686a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      UNIMPLEMENTED(FATAL);
687a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
688a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kString:
689a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      okay = obj->GetClass()->IsStringClass();
690a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
691a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kThrowable:
692a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      okay = obj->GetClass()->IsThrowableClass();
693a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
694a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kObject:
695a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
696a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
697a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    if (!okay) {
69868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("%s has wrong type: %s", what, PrettyTypeOf(obj).c_str());
699a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      return false;
700a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
701a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
702a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    return true;
703a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes  }
704a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
705a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
70668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * Verify that the "mode" argument passed to a primitive array Release
70768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * function is one of the valid values.
708a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
70968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckReleaseMode(jint mode) {
71068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
71168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("unknown value for release mode: %d", mode);
71268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
713a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
71468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
715a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
716a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
71768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
71868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
71968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    switch (fmt) {
72068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'a':  // jarray
72168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckArray(soa, arg.a);
72268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'c':  // jclass
72368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckInstance(soa, kClass, arg.c, false);
72468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'f':  // jfieldID
72568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckFieldID(soa, arg.f) != nullptr;
72668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'm':  // jmethodID
72768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckMethodID(soa, arg.m) != nullptr;
72868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'r':  // release int
72968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckReleaseMode(arg.r);
73068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 's':  // jstring
73168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckInstance(soa, kString, arg.s, false);
73268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 't':  // jthrowable
73368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckInstance(soa, kThrowable, arg.t, false);
73468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'E':  // JNIEnv*
73568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckThread(arg.E);
73668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'L':  // jobject
73768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckInstance(soa, kObject, arg.L, true);
73868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      default:
73968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckNonHeapValue(fmt, arg);
74068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
74168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
74268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
74368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckNonHeapValue(char fmt, JniValueType arg) {
74468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    switch (fmt) {
74568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'p':  // TODO: pointer - null or readable?
74668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'v':  // JavaVM*
74768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'B':  // jbyte
74868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'C':  // jchar
74968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'D':  // jdouble
75068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'F':  // jfloat
75168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'I':  // jint
75268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'J':  // jlong
75368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'S':  // jshort
75468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;  // Ignored.
75568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'b':  // jboolean, why two? Fall-through.
75668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'Z':
75768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckBoolean(arg.Z);
75868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'u':  // utf8
75968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if ((flags_ & kFlag_Release) != 0) {
76068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          return CheckNonNull(arg.u);
76168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
76268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
76368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          return CheckUtfString(arg.u, nullable);
76468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
76568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'w':  // jobjectRefType
76668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        switch (arg.w) {
76768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNIInvalidRefType:
76868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNILocalRefType:
76968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNIGlobalRefType:
77068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNIWeakGlobalRefType:
77168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            break;
77268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          default:
77368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            AbortF("Unknown reference type");
77468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            return false;
77568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
77668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
77768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'z':  // jsize
77868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckLengthPositive(arg.z);
77968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      default:
78068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("unknown format specifier: '%c'", fmt);
78168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
78232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
78368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
78432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  }
78532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes
78668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
78768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                              std::string* msg)
78868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
78968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    switch (fmt) {
79068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'L':  // jobject fall-through.
79168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'a':  // jarray fall-through.
79268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 's':  // jstring fall-through.
79368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 't':  // jthrowable fall-through.
79468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (arg.L == nullptr) {
79568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "NULL";
79668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
79768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "%p", arg.L);
79868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
79968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
80068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'c': {  // jclass
80168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        jclass jc = arg.c;
80268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        mirror::Class* c = soa.Decode<mirror::Class*>(jc);
80368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (c == nullptr) {
80468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "NULL";
805c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) {
80668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "INVALID POINTER:%p", jc);
80768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else if (!c->IsClass()) {
80868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c);
80968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
81068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += PrettyClass(c);
81168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (!entry) {
81268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            StringAppendF(msg, " (%p)", jc);
81368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
81468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
81568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
81668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
81768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'f': {  // jfieldID
81868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        jfieldID fid = arg.f;
819c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier        ArtField* f = soa.DecodeField(fid);
82068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        *msg += PrettyField(f);
82168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (!entry) {
82268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, " (%p)", fid);
82368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
82468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
82568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
82668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'm': {  // jmethodID
82768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        jmethodID mid = arg.m;
8283d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        ArtMethod* m = soa.DecodeMethod(mid);
82968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        *msg += PrettyMethod(m);
83068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (!entry) {
83168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, " (%p)", mid);
83268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
83368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
83468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
83568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      default:
83668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        TraceNonHeapValue(fmt, arg, msg);
83768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
83832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
83932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  }
84032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes
84168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
84268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    switch (fmt) {
84368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'B':  // jbyte
84468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (arg.B >= 0 && arg.B < 10) {
84568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "%d", arg.B);
84668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
84768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
84868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
84968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
85068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'C':  // jchar
85168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (arg.C < 0x7f && arg.C >= ' ') {
85268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
85368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
85468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "U+%x", arg.C);
85568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
85668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
85768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'F':  // jfloat
85868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "%g", arg.F);
85968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
86068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'D':  // jdouble
86168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "%g", arg.D);
86268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
86368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'S':  // jshort
86468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "%d", arg.S);
86568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
86668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'i':  // jint - fall-through.
86768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'I':  // jint
86868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "%d", arg.I);
86968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
87068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'J':  // jlong
87168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "%" PRId64, arg.J);
87268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
87368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'Z':  // jboolean
87468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'b':  // jboolean (JNI-style)
87568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        *msg += arg.b == JNI_TRUE ? "true" : "false";
87668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
87768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'V':  // void
87868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        DCHECK(arg.V == nullptr);
87968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        *msg += "void";
88068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
88168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'v':  // JavaVM*
88268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "(JavaVM*)%p", arg.v);
88368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
88468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'E':
88568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "(JNIEnv*)%p", arg.E);
88668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
88768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'z':  // non-negative jsize
88868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        // You might expect jsize to be size_t, but it's not; it's the same as jint.
88968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        // We only treat this specially so we can do the non-negative check.
89068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        // TODO: maybe this wasn't worth it?
89168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "%d", arg.z);
89268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
89368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'p':  // void* ("pointer")
89468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (arg.p == nullptr) {
89568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "NULL";
89668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
89768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "(void*) %p", arg.p);
89868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
89968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
90068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'r': {  // jint (release mode)
90168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        jint releaseMode = arg.r;
90268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (releaseMode == 0) {
90368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "0";
90468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else if (releaseMode == JNI_ABORT) {
90568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "JNI_ABORT";
90668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else if (releaseMode == JNI_COMMIT) {
90768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "JNI_COMMIT";
90868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
90968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "invalid release mode %d", releaseMode);
91068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
91168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
91268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
91368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'u':  // const char* (Modified UTF-8)
91468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (arg.u == nullptr) {
91568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "NULL";
91668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
91768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "\"%s\"", arg.u);
91868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
91968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
92068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'w':  // jobjectRefType
92168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        switch (arg.w) {
92268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNIInvalidRefType:
92368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            *msg += "invalid reference type";
92468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            break;
92568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNILocalRefType:
92668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            *msg += "local ref type";
92768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            break;
92868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNIGlobalRefType:
92968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            *msg += "global ref type";
93068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            break;
93168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNIWeakGlobalRefType:
93268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            *msg += "weak global ref type";
93368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            break;
93468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          default:
93568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            *msg += "unknown ref type";
93668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            break;
93768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
93868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
93968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      default:
94068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
94168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
94268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
943a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
9442cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier   * Verify that "array" is non-null and points to an Array object.
945a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
94668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * Since we're dealing with objects, switch to "running" mode.
947a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
94868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
949b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
95068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (UNLIKELY(java_array == nullptr)) {
95168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("jarray was NULL");
95268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
953a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
954a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
95568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
95668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a))) {
9574c13a3ff475f206c4d0a86ee2595c45392fd942fMathieu Chartier      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
95868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("jarray is an invalid %s: %p (%p)",
95968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(),
96068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             java_array, a);
96168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
96268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    } else if (!a->IsArrayInstance()) {
96368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("jarray argument has non-array type: %s", PrettyTypeOf(a).c_str());
96468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
965a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
96668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
967a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
968a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
96968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckBoolean(jboolean z) {
97068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (z != JNI_TRUE && z != JNI_FALSE) {
97168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("unexpected jboolean value: %d", z);
97268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
97368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
97468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
97568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
97668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
97768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckLengthPositive(jsize length) {
97868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (length < 0) {
97968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("negative jsize: %d", length);
98068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
98168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
98268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
98368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
98468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
985c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  ArtField* CheckFieldID(ScopedObjectAccess& soa, jfieldID fid)
98668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
98768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (fid == nullptr) {
98868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("jfieldID was NULL");
98968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return nullptr;
99068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
991c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    ArtField* f = soa.DecodeField(fid);
992c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    // TODO: Better check here.
993c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass())) {
99468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
99568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("invalid jfieldID: %p", fid);
99668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return nullptr;
99768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
99868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return f;
99968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
100068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
10013d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  ArtMethod* CheckMethodID(ScopedObjectAccess& soa, jmethodID mid)
100268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
100368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (mid == nullptr) {
100468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("jmethodID was NULL");
100568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return nullptr;
100668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
10073d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    ArtMethod* m = soa.DecodeMethod(mid);
10083d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    // TODO: Better check here.
10093d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass())) {
101068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
101168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("invalid jmethodID: %p", mid);
101268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return nullptr;
1013a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
101468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return m;
1015a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1016a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
101768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckThread(JNIEnv* env) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1018a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    Thread* self = Thread::Current();
1019ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (self == nullptr) {
102068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
102168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
1022a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1023a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1024a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // Get the *correct* JNIEnv by going through our TLS pointer.
1025a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    JNIEnvExt* threadEnv = self->GetJniEnv();
1026a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
10273f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Verify that the current thread is (a) attached and (b) associated with
10283f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // this particular instance of JNIEnv.
102968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (env != threadEnv) {
103068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("thread %s using JNIEnv* from thread %s",
103168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             ToStr<Thread>(*self).c_str(), ToStr<Thread>(*self).c_str());
103268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
1033a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1034a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
10353f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Verify that, if this thread previously made a critical "get" call, we
10363f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // do the corresponding "release" call before we try anything else.
103768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    switch (flags_ & kFlag_CritMask) {
1038a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    case kFlag_CritOkay:    // okay to call this method
1039a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      break;
1040a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    case kFlag_CritBad:     // not okay to call
1041a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      if (threadEnv->critical) {
104268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("thread %s using JNI after critical get",
104368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               ToStr<Thread>(*self).c_str());
104468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
1045a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1046a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      break;
1047a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    case kFlag_CritGet:     // this is a "get" call
10483f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      // Don't check here; we allow nested gets.
1049a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      threadEnv->critical++;
1050a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      break;
10517934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    case kFlag_CritRelease:  // this is a "release" call
1052a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      threadEnv->critical--;
1053a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      if (threadEnv->critical < 0) {
105468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("thread %s called too many critical releases",
105568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               ToStr<Thread>(*self).c_str());
105668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
1057a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1058a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      break;
1059a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    default:
106068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      LOG(FATAL) << "Bad flags (internal error): " << flags_;
1061a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1062a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
10633f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Verify that, if an exception has been raised, the native code doesn't
10643f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // make any JNI calls other than the Exception* methods.
106568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
106614691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      mirror::Throwable* exception = self->GetException();
106714691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      AbortF("JNI %s called with pending exception %s",
106814691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray             function_name_,
106914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray             exception->Dump().c_str());
107068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
1071a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
107268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
1073a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1074a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
10753f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes  // Verifies that "bytes" points to valid Modified UTF-8 data.
107668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckUtfString(const char* bytes, bool nullable) {
1077ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (bytes == nullptr) {
1078a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      if (!nullable) {
107968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("non-nullable const char* was NULL");
108068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
1081a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
108268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return true;
1083a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1084a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1085ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const char* errorKind = nullptr;
108632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    uint8_t utf8 = CheckUtfBytes(bytes, &errorKind);
1087ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (errorKind != nullptr) {
108868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
108968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          "    string: '%s'", errorKind, utf8, bytes);
109068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
1091a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
109268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
1093a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1094a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1095a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath  // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1096a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath  // sequences in place of encoded surrogate pairs.
109732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  static uint8_t CheckUtfBytes(const char* bytes, const char** errorKind) {
1098a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    while (*bytes != '\0') {
1099a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      uint8_t utf8 = *(bytes++);
1100a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      // Switch on the high four bits.
1101a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      switch (utf8 >> 4) {
1102a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x00:
1103a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x01:
1104a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x02:
1105a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x03:
1106a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x04:
1107a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x05:
1108a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x06:
1109a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x07:
1110a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        // Bit pattern 0xxx. No need for any extra bytes.
1111a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        break;
1112a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x08:
1113a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x09:
1114a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0a:
1115a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0b:
1116a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath         // Bit patterns 10xx, which are illegal start bytes.
1117a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        *errorKind = "start";
1118a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        return utf8;
1119a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath      case 0x0f:
1120a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath        // Bit pattern 1111, which might be the start of a 4 byte sequence.
1121a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath        if ((utf8 & 0x08) == 0) {
1122a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath          // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1123a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath          // We consume one continuation byte here, and fall through to consume two more.
1124a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath          utf8 = *(bytes++);
1125a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath          if ((utf8 & 0xc0) != 0x80) {
1126a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath            *errorKind = "continuation";
1127a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath            return utf8;
1128a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath          }
1129a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath        } else {
1130a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath          *errorKind = "start";
1131a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath          return utf8;
1132a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath        }
1133a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath
1134a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath        // Fall through to the cases below to consume two more continuation bytes.
1135a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath        FALLTHROUGH_INTENDED;
1136a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0e:
1137a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        // Bit pattern 1110, so there are two additional bytes.
1138a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        utf8 = *(bytes++);
1139a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        if ((utf8 & 0xc0) != 0x80) {
1140a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          *errorKind = "continuation";
1141a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          return utf8;
1142a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
1143a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath
1144a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath        // Fall through to consume one more continuation byte.
1145a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath        FALLTHROUGH_INTENDED;
1146a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0c:
1147a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0d:
1148a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        // Bit pattern 110x, so there is one additional byte.
1149a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        utf8 = *(bytes++);
1150a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        if ((utf8 & 0xc0) != 0x80) {
1151a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          *errorKind = "continuation";
1152a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          return utf8;
1153a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
1154a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        break;
1155a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1156a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1157a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return 0;
1158a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1159a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
116068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
116168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list args;
116268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(args, fmt);
116368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
116468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(args);
116568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
116668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
116768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // The name of the JNI function being checked.
116868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const char* const function_name_;
116968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
117068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const int flags_;
117192cb498ffd2185fc8f8da7cd25fe485d0e7e3355Elliott Hughes  int indent_;
1172a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
117368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const bool has_method_;
117468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
1175a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1176a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
1177a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1178a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/*
1179a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
1180a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *      Guarded arrays
1181a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
1182a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */
1183a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1184a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/* this gets tucked in at the start of the buffer; struct size must be even */
118568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogersclass GuardedCopy {
118668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers public:
1187a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
1188a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Create an over-sized buffer to hold the contents of "buf".  Copy it in,
1189a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * filling in the area around it with guard data.
1190a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
119171e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier  static void* Create(void* original_buf, size_t len, bool mod_okay) {
119268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const size_t new_len = LengthIncludingRedZones(len);
119368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    uint8_t* const new_buf = DebugAlloc(new_len);
1194a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
119568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // If modification is not expected, grab a checksum.
119668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    uLong adler = 0;
119768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!mod_okay) {
119868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
119968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
120068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
120168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
120268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
120368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Fill begin region with canary pattern.
120468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
120568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
120668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
120768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (kCanary[j] == '\0') {
120868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        j = 0;
120968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
1210a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1211a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
12123f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Copy the data in; note "len" could be zero.
121368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1214a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
121568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Fill end region with canary pattern.
121668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
121768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
121868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (kCanary[j] == '\0') {
121968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        j = 0;
122068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
122168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
122268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
122368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return const_cast<uint8_t*>(copy->BufferWithinRedZones());
122468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
122568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
122668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  /*
122768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * Create a guarded copy of a primitive array.  Modifications to the copied
122868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * data are allowed.  Returns a pointer to the copied data.
122968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   */
123071e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier  static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
123171e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier                                   void* original_ptr) {
123268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
123368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
123468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
123568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    size_t component_size = a->GetClass()->GetComponentSize();
123668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    size_t byte_count = a->GetLength() * component_size;
123771e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier    void* result = Create(original_ptr, byte_count, true);
123868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (is_copy != nullptr) {
123968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      *is_copy = JNI_TRUE;
1240a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
124168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result;
124268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
1243a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
124468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  /*
124568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * Perform the array "release" operation, which may or may not copy data
124668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * back into the managed heap, and may or may not release the underlying storage.
124768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   */
124871e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier  static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
124971e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier                                    jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
125071e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier                                    int mode) {
125168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
125268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
125368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return nullptr;
125468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
125571e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier    GuardedCopy* const copy = FromEmbedded(embedded_buf);
125671e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier    void* original_ptr = copy->original_ptr_;
125768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (mode != JNI_ABORT) {
125871e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier      memcpy(original_ptr, embedded_buf, copy->original_length_);
125968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
126068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (mode != JNI_COMMIT) {
126171e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier      Destroy(embedded_buf);
126268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
126371e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier    return original_ptr;
1264a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1265a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
126668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
1267a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
1268a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Free up the guard buffer, scrub it, and return the original pointer.
1269a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
127068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void* Destroy(void* embedded_buf) {
127168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    GuardedCopy* copy = FromEmbedded(embedded_buf);
127268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    void* original_ptr = const_cast<void*>(copy->original_ptr_);
127368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    size_t len = LengthIncludingRedZones(copy->original_length_);
127468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    DebugFree(copy, len);
127532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    return original_ptr;
1276a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1277a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1278a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
1279a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify the guard area and, if "modOkay" is false, that the data itself
1280a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * has not been altered.
1281a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
12822cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier   * The caller has already checked that "dataBuf" is non-null.
1283a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
128468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
128568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const GuardedCopy* copy = FromEmbedded(embedded_buf);
128668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
128768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
128868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
128968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers private:
129071e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier  GuardedCopy(void* original_buf, size_t len, uLong adler) :
129168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
129268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
129368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
129468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static uint8_t* DebugAlloc(size_t len) {
129568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
129668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (result == MAP_FAILED) {
129768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
129868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
129968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<uint8_t*>(result);
130068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
130168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
130268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void DebugFree(void* buf, size_t len) {
130368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (munmap(buf, len) != 0) {
130468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
130568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
130668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
130768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
130868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static size_t LengthIncludingRedZones(size_t len) {
130968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return len + kRedZoneSize;
131068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
131168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
131268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Get the GuardedCopy from the interior pointer.
131368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static GuardedCopy* FromEmbedded(void* embedded_buf) {
131468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<GuardedCopy*>(
131568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
131668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
131768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
131868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
131968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<const GuardedCopy*>(
132068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
132168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
132268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
132368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void AbortF(const char* jni_function_name, const char* fmt, ...) {
132468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list args;
132568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(args, fmt);
132668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
132768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(args);
132868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
132968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
133068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckHeader(const char* function_name, bool mod_okay) const {
1331a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    static const uint32_t kMagicCmp = kGuardMagic;
1332a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
13333f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Before we do anything with "pExtra", check the magic number.  We
13343f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // do the check with memcmp rather than "==" in case the pointer is
13353f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // unaligned.  If it points to completely bogus memory we're going
13363f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // to crash, but there's no easy way around that.
133768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1338a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      uint8_t buf[4];
133968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      memcpy(buf, &magic_, 4);
134068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF(function_name,
134168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
134268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             buf[3], buf[2], buf[1], buf[0], this);  // Assumes little-endian.
134368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
1344a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1345a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
134668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
134768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // told the client that we made a copy, there's no reason they can't alter the buffer.
134868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!mod_okay) {
134968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      uLong computed_adler =
135068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
135168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (computed_adler != adler_) {
135268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
135368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               computed_adler, adler_, this);
135468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
1355a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1356a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
135768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
135868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
1359a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
136068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckRedZones(const char* function_name) const {
136168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Check the begin red zone.
136268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
136368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
136468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
136568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
136668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
1367a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
136868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (kCanary[j] == '\0') {
136968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        j = 0;
1370a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1371a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1372a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
137368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Check end region.
137468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
137568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
137668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        size_t offset_from_buffer_start =
137768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
137868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
137968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               offset_from_buffer_start);
138068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
138168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
138268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (kCanary[j] == '\0') {
138368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        j = 0;
1384a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1385a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
138668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
1387a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1388a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
138968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Location that canary value will be written before the guarded region.
139068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const char* StartRedZone() const {
139168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
139268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1393a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1394a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
139568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Return the interior embedded buffer.
139668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const uint8_t* BufferWithinRedZones() const {
139768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
139868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return embedded_buf;
1399a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1400a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
140168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Location that canary value will be written after the guarded region.
140268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const char* EndRedZone() const {
140368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
140468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    size_t buf_len = LengthIncludingRedZones(original_length_);
140568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1406a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1407a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
140868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static constexpr size_t kRedZoneSize = 512;
140968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1410a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
141168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Value written before and after the guarded array.
141268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const char* const kCanary;
1413a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
141468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1415a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
141668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const uint32_t magic_;
141768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const uLong adler_;
141871e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier  void* const original_ptr_;
141968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const size_t original_length_;
142068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers};
142168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogersconst char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
1422a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1423a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/*
1424a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
1425a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *      JNI functions
1426a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
1427a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */
1428a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1429a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesclass CheckJNI {
1430a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes public:
1431a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint GetVersion(JNIEnv* env) {
143268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
143368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
143468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.E = env }};
143568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "E", args)) {
143668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
143768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.I = baseEnv(env)->GetVersion(env);
143868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "I", &result)) {
143968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.I;
144068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
144168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
144268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
144368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
144468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
144568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
144668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
144768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
144868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env }, {.p = vm}};
144968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ep", args)) {
145068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
145168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->GetJavaVM(env, vm);
145268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
145368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
145468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
145568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
145668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
145768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
145868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
145968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
146068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
146168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
146268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
146368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EcpI", args)) {
146468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
146568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
146668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
146768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
146868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
146968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
147068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
147168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
147268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
147368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jint UnregisterNatives(JNIEnv* env, jclass c) {
147468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
147568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
147668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env }, {.c = c}};
147768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ec", args)) {
147868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
147968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->UnregisterNatives(env, c);
148068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
148168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
148268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
148368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
148468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
148568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
148668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
148768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
1488c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1489c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    // know the object is invalid. The spec says that passing invalid objects or even ones that
1490c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    // are deleted isn't supported.
149168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
149268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1493c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    JniValueType args[2] = {{.E = env }, {.L = obj}};
1494c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    if (sc.Check(soa, true, "EL", args)) {
149568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
149668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.w = baseEnv(env)->GetObjectRefType(env, obj);
149768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "w", &result)) {
149868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.w;
149968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
150068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
150168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNIInvalidRefType;
1502a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1503a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
150468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
150568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                            jsize bufLen) {
150668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
150768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
150868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
150968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
151068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
151168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
151268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "c", &result)) {
151368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.c;
151468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
151568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
151668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1517a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1518a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1519a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jclass FindClass(JNIEnv* env, const char* name) {
152068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
152168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
152268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.u = name}};
152368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
152468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
152568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.c = baseEnv(env)->FindClass(env, name);
152668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "c", &result)) {
152768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.c;
152868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
152968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
153068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1531a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1532a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1533e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jclass GetSuperclass(JNIEnv* env, jclass c) {
153468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
153568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
153668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.c = c}};
153768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ec", args)) {
153868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
153968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.c = baseEnv(env)->GetSuperclass(env, c);
154068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "c", &result)) {
154168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.c;
154268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
154368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
154468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1545a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1546a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1547e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
154868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
154968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
155068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
155168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecc", args)) {
155268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
155368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
155468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "b", &result)) {
155568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.b;
155668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
155768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
155868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_FALSE;
1559a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1560a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1561a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
156268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
156368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
156468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = method}};
156568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
156668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
156768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.m = baseEnv(env)->FromReflectedMethod(env, method);
156868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "m", &result)) {
156968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.m;
157068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
157168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
157268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1573a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1574a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1575a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
157668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
157768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
157868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = field}};
157968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
158068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
158168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.f = baseEnv(env)->FromReflectedField(env, field);
158268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "f", &result)) {
158368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.f;
158468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
158568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
158668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1587a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1588a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1589a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
159068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
159168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
159268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
159368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecmb", args)) {
159468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
159568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
159668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
159768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        DCHECK(sc.CheckReflectedMethod(soa, result.L));
159868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
159968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
160068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
160168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1602a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1603a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1604a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
160568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
160668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
160768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
160868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecfb", args)) {
160968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
161068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
161168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
161268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        DCHECK(sc.CheckReflectedField(soa, result.L));
161368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
161468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
161568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
161668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1617a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1618a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1619a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint Throw(JNIEnv* env, jthrowable obj) {
162068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
162168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
162268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.t = obj}};
162368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
162468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
162568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->Throw(env, obj);
162668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
162768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
162868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
162968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
163068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
1631a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1632a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1633e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
163468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
163568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
1636c50358b8947ae4367132dae5987d2e9738e90464Christopher Ferris    JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
163768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
163868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
163968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->ThrowNew(env, c, message);
164068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
164168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
164268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
164368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
164468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
1645a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1646a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1647a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jthrowable ExceptionOccurred(JNIEnv* env) {
164868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
164968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
165068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.E = env}};
165168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "E", args)) {
165268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
165368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.t = baseEnv(env)->ExceptionOccurred(env);
165468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "t", &result)) {
165568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.t;
165668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
165768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
165868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1659a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1660a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1661a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void ExceptionDescribe(JNIEnv* env) {
166268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
166368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
166468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.E = env}};
166568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "E", args)) {
166668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
166768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->ExceptionDescribe(env);
166868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
166968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
167068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
1671a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1672a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1673a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void ExceptionClear(JNIEnv* env) {
167468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
167568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
167668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.E = env}};
167768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "E", args)) {
167868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
167968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->ExceptionClear(env);
168068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
168168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
168268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
168368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
168468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
168568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jboolean ExceptionCheck(JNIEnv* env) {
168668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
168768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
168868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.E = env}};
168968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "E", args)) {
169068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
169168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.b = baseEnv(env)->ExceptionCheck(env);
169268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "b", &result)) {
169368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.b;
169468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
169568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
169668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_FALSE;
1697a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1698a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1699a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void FatalError(JNIEnv* env, const char* msg) {
1700c4378df76edd637273813fef4da7f01c4e637defElliott Hughes    // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1701c4378df76edd637273813fef4da7f01c4e637defElliott Hughes    // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1702c4378df76edd637273813fef4da7f01c4e637defElliott Hughes    // and it's not unimaginable that you don't know that you do. So we allow it.
170368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
170468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
170568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.u = msg}};
170668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eu", args)) {
170768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
170868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->FatalError(env, msg);
170968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // Unreachable.
171068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
171168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
171268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
1713a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1714a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1715a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint PushLocalFrame(JNIEnv* env, jint capacity) {
171668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
171768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
171868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.I = capacity}};
171968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EI", args)) {
172068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
172168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->PushLocalFrame(env, capacity);
172268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
172368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
172468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
172568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
172668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
1727a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1728a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1729a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject PopLocalFrame(JNIEnv* env, jobject res) {
173068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
173168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
173268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = res}};
173368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
173468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
173568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->PopLocalFrame(env, res);
173668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "L", &result);
173768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return result.L;
173868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
173968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1740a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1741a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1742a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
174368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return NewRef(__FUNCTION__, env, obj, kGlobal);
1744a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1745a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
174668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobject NewLocalRef(JNIEnv* env, jobject obj) {
174768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return NewRef(__FUNCTION__, env, obj, kLocal);
1748a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1749a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
175068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
175168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
1752a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1753a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
175468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
175568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    DeleteRef(__FUNCTION__, env, obj, kGlobal);
1756a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1757a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
175868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
175968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
176068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
176168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
176268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void DeleteLocalRef(JNIEnv* env, jobject obj) {
176368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    DeleteRef(__FUNCTION__, env, obj, kLocal);
1764a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1765a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1766a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
176768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
176868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
176968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.I = capacity}};
177068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EI", args)) {
177168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
177268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
177368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
177468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
177568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
177668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
177768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
1778a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1779a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1780a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
178168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
178268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
178368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
178468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "ELL", args)) {
178568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
178668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
178768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "b", &result)) {
178868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.b;
178968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
179068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
179168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_FALSE;
1792a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1793a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1794e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jobject AllocObject(JNIEnv* env, jclass c) {
179568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
179668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
179768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.c = c}};
179868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
179968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
180068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->AllocObject(env, c);
180168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result)) {
180268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
180368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
180468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
180568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
180668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
180768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
180868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
180968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
181068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
181168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
1812c50358b8947ae4367132dae5987d2e9738e90464Christopher Ferris    if (sc.Check(soa, true, "Ecm", args) && sc.CheckInstantiableNonArray(soa, c) &&
181368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.CheckConstructor(soa, mid)) {
181468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
181568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
181668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result)) {
181768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
181868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
181968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
182068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1821a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1822a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1823e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
1824a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    va_list args;
1825a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    va_start(args, mid);
182668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    jobject result = NewObjectV(env, c, mid, args);
1827a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    va_end(args);
182868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result;
1829a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1830a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
183168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
183268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
183368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
183468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
1835c50358b8947ae4367132dae5987d2e9738e90464Christopher Ferris    if (sc.Check(soa, true, "Ecm", args) && sc.CheckInstantiableNonArray(soa, c) &&
183668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.CheckConstructor(soa, mid)) {
183768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
183868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
183968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result)) {
184068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
184168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
184268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
184368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1844a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1845a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1846a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jclass GetObjectClass(JNIEnv* env, jobject obj) {
184768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
184868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
184968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = obj}};
185068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
185168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
185268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.c = baseEnv(env)->GetObjectClass(env, obj);
185368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "c", &result)) {
185468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.c;
185568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
185668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
185768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1858a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1859a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1860e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
186168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
186268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
186368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
186468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "ELc", args)) {
186568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
186668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
186768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "b", &result)) {
186868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.b;
186968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
187068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
187168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_FALSE;
1872a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1873a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1874e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
187568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
1876a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1877a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
187868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
187968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
1880a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1881a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
188268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
188368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
1884a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1885a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1886e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
188768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
188868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
188968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
189068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
189168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
189268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
189368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
189468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
189568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
189668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
189768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
189868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
189968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
190068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType value; \
190168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    value.shorty = v; \
190268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
190368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
190468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
190568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
190668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType value; \
190768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    value.shorty = v; \
190868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
190968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
191068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
191168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
191268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
191368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
191468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
191568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
191668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
191768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
191868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
191968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
192068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#undef FIELD_ACCESSORS
192168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
192268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
192368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
192468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
192568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
192668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
192768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                        jvalue* vargs) {
192868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
192968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
193068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
193168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
193251be0a7158b62d6da6a3ccb6fce9f7f677ec3ce3Marcus Oakland    CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
193368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
193468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
193568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
193668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
193768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
193868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
193968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
194068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                        va_list vargs) {
194168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
194268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
194368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
194468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
194568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
194668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
194768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
194868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
194968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list vargs;
195068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(vargs, mid);
195168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
195268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(vargs);
195368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
195468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
195568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
195668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list vargs;
195768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(vargs, mid);
195868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
195968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(vargs);
196068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
196168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
196268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
196368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list vargs;
196468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(vargs, mid);
196568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
196668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(vargs);
196768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
196868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
196968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#define CALL(rtype, name, ptype, shorty) \
197068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
197168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
197268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
197368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
197468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
197568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                             jvalue* vargs) { \
197668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
197768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
197868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
197968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
198068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
198168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
198268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
198368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
198468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
198568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
198668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
198768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
198868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                             va_list vargs) { \
198968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
199068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
199168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
199268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
199368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
199468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
199568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
199668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
199768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list vargs; \
199868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(vargs, mid); \
199968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    rtype result = \
200068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
200168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(vargs); \
200268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result; \
200368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
200468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
200568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
200668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                            ...) { \
200768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list vargs; \
200868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(vargs, mid); \
200968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    rtype result = \
201068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
201168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(vargs); \
201268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result; \
201368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
201468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
201568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
201668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list vargs; \
201768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(vargs, mid); \
201868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    rtype result = \
201968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
202068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(vargs); \
202168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result; \
202268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
202368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
202468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jobject, Object, Primitive::kPrimNot, L)
202568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
202668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jbyte, Byte, Primitive::kPrimByte, B)
202768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jchar, Char, Primitive::kPrimChar, C)
202868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jshort, Short, Primitive::kPrimShort, S)
202968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jint, Int, Primitive::kPrimInt, I)
203068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jlong, Long, Primitive::kPrimLong, J)
203168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jfloat, Float, Primitive::kPrimFloat, F)
203268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jdouble, Double, Primitive::kPrimDouble, D)
203368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#undef CALL
203468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
203568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
203668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
203768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
203868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
203968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Epz", args)) {
204068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
204168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.s = baseEnv(env)->NewString(env, unicode_chars, len);
204268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "s", &result)) {
204368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.s;
204468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
204568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
204668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2047a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2048a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
204968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jstring NewStringUTF(JNIEnv* env, const char* chars) {
205068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
205168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
205268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.u = chars}};
205368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eu", args)) {
205468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
205568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // TODO: stale? show pointer and truncate string.
205668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.s = baseEnv(env)->NewStringUTF(env, chars);
205768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "s", &result)) {
205868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.s;
205968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
206068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
206168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2062a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2063a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
206468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jsize GetStringLength(JNIEnv* env, jstring string) {
206568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
206668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
206768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.s = string}};
206868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Es", args)) {
206968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
207068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.z = baseEnv(env)->GetStringLength(env, string);
207168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "z", &result)) {
207268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.z;
2073a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
2074a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
207568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
2076a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2077a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
207868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
207968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
208068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
208168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.s = string}};
208268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Es", args)) {
208368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
208468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.z = baseEnv(env)->GetStringUTFLength(env, string);
208568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "z", &result)) {
208668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.z;
208768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2088a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
208968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
2090a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2091a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
209268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
209368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
209468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                                 is_copy, false, false));
2095a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2096a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
209768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
209868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
209968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                                is_copy, true, false));
2100a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2101a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
210268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
210368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
210468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                                 is_copy, false, true));
210568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
210668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
210768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
210868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2109a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2110a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2111a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
211268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
211368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
211468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
211568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
211668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
211768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
211868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
211968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
212068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
212168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
212268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
212368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
212468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
212568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EsIIp", args)) {
212668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->GetStringRegion(env, string, start, len, buf);
212768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
212868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
212968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
2130a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
2131a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2132a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
213368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
213468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
213568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
213668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
213768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
213868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
213968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EsIIp", args)) {
214068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
214168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
214268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
214368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
214468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
2145a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2146a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
214768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jsize GetArrayLength(JNIEnv* env, jarray array) {
214868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
214968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
215068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.a = array}};
215168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ea", args)) {
215268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
215368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.z = baseEnv(env)->GetArrayLength(env, array);
215468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "z", &result)) {
215568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.z;
215668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
215768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
215868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
215968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
216068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
216168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
216268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                     jobject initial_element) {
216368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
216468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
216568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] =
216668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
216768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EzcL", args)) {
216868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
216968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // Note: assignability tests of initial_element are done in the base implementation.
217068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
217168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "a", &result)) {
217268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return down_cast<jobjectArray>(result.a);
217368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
217468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
217568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2176a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2177a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2178a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
217968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
218068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
218168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
218268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eaz", args)) {
218368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
218468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
218568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result)) {
218668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
218768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
218868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
218968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2190a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2191a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2192a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
219368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
219468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
219568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
219668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
219768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
219868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // in ArrayStoreExceptions.
219968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EaIL", args)) {
220068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->SetObjectArrayElement(env, array, index, value);
220168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
220268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
220368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
2204a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
2205a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2206a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
220768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
220868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
220968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                      Primitive::kPrimBoolean));
2210a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2211a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
221268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
221368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
221468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                   Primitive::kPrimByte));
221568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
2216a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
221768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jcharArray NewCharArray(JNIEnv* env, jsize length) {
221868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
221968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                   Primitive::kPrimChar));
222068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
2221a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
222268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jshortArray NewShortArray(JNIEnv* env, jsize length) {
222368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
222468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                    Primitive::kPrimShort));
2225a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2226a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
222768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jintArray NewIntArray(JNIEnv* env, jsize length) {
222868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2229a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2230a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
223168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jlongArray NewLongArray(JNIEnv* env, jsize length) {
223268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
223368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                   Primitive::kPrimLong));
223468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
223568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
223668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
223768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
223868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                    Primitive::kPrimFloat));
223968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
224068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
224168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
224268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
224368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                     Primitive::kPrimDouble));
224468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
224568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
224668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
224768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { \
224868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<ctype*>( \
224968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
225068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
225168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
225268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, \
225368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                           jint mode) { \
225468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
225568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
225668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
225768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
225868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                     ctype* buf) { \
225968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
226068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
226168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
226268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
226368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                     const ctype* buf) { \
226468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
226568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
226668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
226768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
226868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
226968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
227068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
227168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
227268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
227368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
227468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
227568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#undef PRIMITIVE_ARRAY_FUNCTIONS
227668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
2277a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint MonitorEnter(JNIEnv* env, jobject obj) {
227868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
227968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
228068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = obj}};
228168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
228268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
228368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->MonitorEnter(env, obj);
228468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
228568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
228668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2287a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
228868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
2289a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2290a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2291a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint MonitorExit(JNIEnv* env, jobject obj) {
229268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
229368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
229468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = obj}};
229568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
229668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
229768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->MonitorExit(env, obj);
229868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
229968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
230068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2301a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
230268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
2303a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2304a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
230568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
230668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
230768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
230868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
230968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eap", args)) {
231068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
231171e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier      void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
231271e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier      if (ptr != nullptr && soa.ForceCopy()) {
231371e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier        ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
231468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
231571e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier      result.p = ptr;
231668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "p", &result)) {
231768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return const_cast<void*>(result.p);
231868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
231968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
232068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2321a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2322a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
232368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
232468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
232568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
232668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonNull(carray);
232768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
232868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eapr", args)) {
232968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (soa.ForceCopy()) {
233071e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier        carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
233168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
233268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
233368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
233468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
233568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
233668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
2337a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2338a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
233968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
234068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
234168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
234268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
234368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EpJ", args)) {
234468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
234568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // Note: the validity of address and capacity are checked in the base implementation.
234668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
234768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result)) {
234868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
234968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
235068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
235168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2352a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2353a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
235468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
235568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
235668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
235768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = buf}};
235868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
235968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
236068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // Note: this is implemented in the base environment by a GetLongField which will sanity
236168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // check the type of buf in GetLongField above.
236268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
236368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "p", &result)) {
236468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return const_cast<void*>(result.p);
236568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2366a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
236768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2368a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2369a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
237068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
237168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
237268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
237368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = buf}};
237468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
237568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
237668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // Note: this is implemented in the base environment by a GetIntField which will sanity
237768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // check the type of buf in GetIntField above.
237868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
237968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "J", &result)) {
238068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.J;
238168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2382a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
238368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
238468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
238568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
238668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers private:
238768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
238868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<JNIEnvExt*>(env)->vm;
2389a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2390a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
239168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const JNINativeInterface* baseEnv(JNIEnv* env) {
239268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
239368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
239468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
239568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
239668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
239768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
239868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = obj}};
239968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
240068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
240168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (kind) {
240268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case kGlobal:
240368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.L = baseEnv(env)->NewGlobalRef(env, obj);
240468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
240568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case kLocal:
240668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.L = baseEnv(env)->NewLocalRef(env, obj);
240768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
240868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case kWeakGlobal:
240968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
241068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
241168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
241268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected reference kind: " << kind;
241368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
241468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result)) {
241568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
24166a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers        DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
241768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
2418a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
2419a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
242068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
242168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
242268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
242368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
242468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
242568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, function_name);
242668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = obj}};
242768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.Check(soa, true, "EL", args);
24286a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
242968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
243068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (kind) {
243168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case kGlobal:
243268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->DeleteGlobalRef(env, obj);
243368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
243468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case kLocal:
243568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->DeleteLocalRef(env, obj);
243668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
243768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case kWeakGlobal:
243868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->DeleteWeakGlobalRef(env, obj);
243968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
244068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
244168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected reference kind: " << kind;
244268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
244368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
244468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
244568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
2446a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2447a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
244868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
244968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                       const char* name, const char* sig, bool is_static) {
245068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
245168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
245268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
245368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecuu", args)) {
245468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
245568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (is_static) {
245668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
245768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      } else {
245868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
245968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
246068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "m", &result)) {
246168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.m;
246268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2463a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
246468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2465a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2466a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
246768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
246868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                     const char* name, const char* sig, bool is_static) {
246968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
247068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
247168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
247268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecuu", args)) {
247368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
247468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (is_static) {
247568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
247668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      } else {
247768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
247868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
247968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "f", &result)) {
248068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.f;
248168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
248268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
248368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
248468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
248568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
248668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
248768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                               bool is_static, Primitive::Type type) {
248868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
248968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
249068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
249168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
249268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
249368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
249468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      const char* result_check = nullptr;
249568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
249668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimNot:
249768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
249868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
249968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
250068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.L = baseEnv(env)->GetObjectField(env, obj, fid);
250168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
250268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "L";
250368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
250468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
250568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
250668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
250768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
250868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
250968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
251068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "Z";
251168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
251268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
251368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
251468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
251568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
251668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.B = baseEnv(env)->GetByteField(env, obj, fid);
251768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
251868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "B";
251968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
252068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
252168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
252268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
252368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
252468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.C = baseEnv(env)->GetCharField(env, obj, fid);
252568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
252668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "C";
252768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
252868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
252968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
253068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
253168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
253268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.S = baseEnv(env)->GetShortField(env, obj, fid);
253368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
253468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "S";
253568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
253668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
253768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
253868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
253968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
254068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.I = baseEnv(env)->GetIntField(env, obj, fid);
254168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
254268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "I";
254368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
254468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
254568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
254668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
254768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
254868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.J = baseEnv(env)->GetLongField(env, obj, fid);
254968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
255068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "J";
255168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
255268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
255368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
255468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
255568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
255668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.F = baseEnv(env)->GetFloatField(env, obj, fid);
255768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
255868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "F";
255968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
256068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
256168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
256268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
256368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
256468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
256568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
256668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "D";
256768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
256868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimVoid:
256968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected type: " << type;
257068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
257168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
257268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, result_check, &result)) {
257368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result;
257468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
257568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
257668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.J = 0;
257768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result;
2578a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2579a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
258068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
258168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                       bool is_static, Primitive::Type type, JniValueType value) {
258268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
258368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
258468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
258568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
258668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
258768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, sig, args) &&
258868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
258968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
259068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimNot:
259168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
259268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
259368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
259468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetObjectField(env, obj, fid, value.L);
259568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
259668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
259768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
259868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
259968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
260068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
260168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
260268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
260368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
260468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
260568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
260668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
260768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
260868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetByteField(env, obj, fid, value.B);
260968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
261068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
261168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
261268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
261368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
261468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
261568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetCharField(env, obj, fid, value.C);
261668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
261768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
261868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
261968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
262068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
262168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
262268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetShortField(env, obj, fid, value.S);
262368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
262468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
262568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
262668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
262768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
262868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
262968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetIntField(env, obj, fid, value.I);
263068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
263168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
263268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
263368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
263468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
263568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
263668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetLongField(env, obj, fid, value.J);
263768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
263868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
263968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
264068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
264168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
264268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
264368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetFloatField(env, obj, fid, value.F);
264468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
264568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
264668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
264768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
264868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
264968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
265068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
265168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
265268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
265368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimVoid:
265468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected type: " << type;
265568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
265668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
265768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
265868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
265968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
266068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
2661a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2662a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
266368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
266468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                            jclass c, jmethodID mid, InvokeType invoke)
266568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
266668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    bool checked;
266768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    switch (invoke) {
266868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case kVirtual: {
266968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        DCHECK(c == nullptr);
267068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        JniValueType args[3] = {{.E = env}, {.L = obj}, {.m = mid}};
2671c50358b8947ae4367132dae5987d2e9738e90464Christopher Ferris        checked = sc.Check(soa, true, "ELm", args);
267268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
267368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
267468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case kDirect: {
267568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        JniValueType args[4] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}};
2676c50358b8947ae4367132dae5987d2e9738e90464Christopher Ferris        checked = sc.Check(soa, true, "ELcm", args);
267768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
267868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
267968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case kStatic: {
268068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        DCHECK(obj == nullptr);
268168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
2682c50358b8947ae4367132dae5987d2e9738e90464Christopher Ferris        checked = sc.Check(soa, true, "Ecm", args);
268368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
268468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
268568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      default:
268668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        LOG(FATAL) << "Unexpected invoke: " << invoke;
268768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        checked = false;
268868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
268968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
269068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return checked;
269168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
269268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
269368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
269468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                  jmethodID mid, jvalue* vargs, Primitive::Type type,
269568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                  InvokeType invoke) {
269668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
269768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
269868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
269968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke) &&
270068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
270168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      const char* result_check;
270268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
270368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimNot:
270468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "L";
270568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
270668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
270768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
270868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
270968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
271068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
271168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
271268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
271368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
271468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
271568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
271668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
271768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
271868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
271968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
272068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "Z";
272168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
272268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
272368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
272468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
272568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
272668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
272768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
272868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
272968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
273068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
273168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
273268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
273368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
273468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
273568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
273668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "B";
273768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
273868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
273968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
274068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
274168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
274268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
274368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
274468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
274568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
274668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
274768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
274868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
274968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
275068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
275168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
275268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "C";
275368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
275468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
275568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
275668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
275768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
275868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
275968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
276068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
276168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
276268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
276368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
276468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
276568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
276668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
276768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
276868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "S";
276968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
277068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
277168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
277268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
277368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
277468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
277568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
277668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
277768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
277868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
277968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
278068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
278168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
278268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
278368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
278468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "I";
278568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
278668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
278768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
278868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
278968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
279068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
279168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
279268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
279368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
279468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
279568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
279668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
279768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
279868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
279968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
280068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "J";
280168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
280268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
280368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
280468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
280568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
280668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
280768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
280868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
280968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
281068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
281168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
281268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
281368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
281468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
281568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
281668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "F";
281768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
281868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
281968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
282068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
282168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
282268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
282368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
282468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
282568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
282668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
282768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
282868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
282968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
283068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
283168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
283268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "D";
283368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
283468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
283568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
283668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
283768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
283868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
283968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
284068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
284168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
284268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
284368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
284468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
284568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
284668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
284768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimVoid:
284868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "V";
284968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.V = nullptr;
285068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
285168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
285268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
285368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
285468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
285568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
285668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
285768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
285868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
285968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
286068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
286168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
286268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
286368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
286468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
286568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected return type: " << type;
286668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = nullptr;
286768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
286868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, result_check, &result)) {
286968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result;
287068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
287168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
287268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.J = 0;
287368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result;
2874a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2875a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
287668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
287768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                  jmethodID mid, va_list vargs, Primitive::Type type,
287868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                  InvokeType invoke) {
287968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
288068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
288168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
288268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke) &&
288368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
288468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      const char* result_check;
288568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
288668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimNot:
288768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "L";
288868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
288968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
289068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
289168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
289268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
289368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
289468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
289568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
289668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
289768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
289868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
289968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
290068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
290168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
290268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
290368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "Z";
290468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
290568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
290668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
290768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
290868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
290968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
291068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
291168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
291268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
291368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
291468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
291568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
291668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
291768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
291868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
291968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "B";
292068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
292168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
292268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
292368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
292468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
292568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
292668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
292768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
292868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
292968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
293068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
293168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
293268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
293368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
293468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
293568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "C";
293668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
293768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
293868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
293968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
294068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
294168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
294268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
294368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
294468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
294568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
294668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
294768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
294868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
294968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
295068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
295168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "S";
295268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
295368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
295468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
295568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
295668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
295768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
295868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
295968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
296068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
296168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
296268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
296368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
296468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
296568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
296668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
296768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "I";
296868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
296968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
297068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
297168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
297268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
297368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
297468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
297568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
297668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
297768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
297868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
297968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
298068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
298168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
298268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
298368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "J";
298468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
298568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
298668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
298768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
298868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
298968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
299068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
299168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
299268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
299368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
299468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
299568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
299668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
299768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
299868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
299968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "F";
300068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
300168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
300268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
300368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
300468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
300568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
300668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
300768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
300868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
300968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
301068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
301168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
301268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
301368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
301468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
301568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "D";
301668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
301768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
301868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
301968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
302068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
302168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
302268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
302368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
302468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
302568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
302668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
302768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
302868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
302968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
303068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimVoid:
303168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "V";
303268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.V = nullptr;
303368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
303468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
303568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
303668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
303768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
303868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
303968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
304068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
304168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
304268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
304368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
304468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
304568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
304668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
304768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
304868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected return type: " << type;
304968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = nullptr;
305068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
305168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, result_check, &result)) {
305268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result;
305368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
3054a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
305568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.J = 0;
305668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result;
3057a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3058a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
305968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
306068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                            jboolean* is_copy, bool utf, bool critical) {
306168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
306268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
306368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(flags, function_name);
306468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
306568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Esp", args)) {
306668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
306771e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier      void* ptr;
306868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (utf) {
306968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        CHECK(!critical);
307071e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier        ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
307171e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier        result.u = reinterpret_cast<char*>(ptr);
307268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      } else {
307371e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier        ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
307471e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier            baseEnv(env)->GetStringChars(env, string, is_copy));
307571e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier        result.p = ptr;
307668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
307768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // TODO: could we be smarter about not copying when local_is_copy?
307871e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier      if (ptr != nullptr && soa.ForceCopy()) {
307968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (utf) {
308068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          size_t length_in_bytes = strlen(result.u) + 1;
308168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.u =
308271e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier              reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
308368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
308468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
308568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.p =
308671e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier              reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
308768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
308868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (is_copy != nullptr) {
308968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *is_copy = JNI_TRUE;
309068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
309168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
309268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
309368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return utf ? result.u : result.p;
309468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
309568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
309668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
3097a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3098a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
309968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
310068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                         const void* chars, bool utf, bool critical) {
310168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
310268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    int flags = kFlag_ExcepOkay | kFlag_Release;
310368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (critical) {
310468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      flags |= kFlag_CritRelease;
310568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
310668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(flags, function_name);
310768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonNull(chars);
310868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
310968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (force_copy_ok && soa.ForceCopy()) {
311068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
311168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
311268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (force_copy_ok) {
311368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
311468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
311568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (utf) {
311668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          CHECK(!critical);
311768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
311868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
311968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (critical) {
312068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
312168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
312268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
312368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
312468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
312568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        JniValueType result;
312668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.Check(soa, false, "V", &result);
312768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
312868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
3129a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3130a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
313168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
313268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                  Primitive::Type type) {
313368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
31346a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
313568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.z = length}};
313668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ez", args)) {
313768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
313868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
313968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
314068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewBooleanArray(env, length);
314168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
314268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
314368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewByteArray(env, length);
314468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
314568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
314668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewCharArray(env, length);
314768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
314868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
314968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewShortArray(env, length);
315068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
315168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
315268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewIntArray(env, length);
315368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
315468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
315568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewLongArray(env, length);
315668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
315768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
315868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewFloatArray(env, length);
315968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
316068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
316168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewDoubleArray(env, length);
316268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
316368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
316468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected primitive type: " << type;
316568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
316668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "a", &result)) {
316768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.a;
316868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
316968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
317068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
317168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
317268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
317368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
317468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                         JNIEnv* env, jarray array, jboolean* is_copy) {
317568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
317668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
317768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
317868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
317968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
318071e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier      void* ptr = nullptr;
318168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
318268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
318371e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier          ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
318471e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier                                                      is_copy);
318568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
318668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
318771e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier          ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
318868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
318968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
319071e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier          ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
319168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
319268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
319371e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier          ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
319468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
319568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
319671e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier          ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
319768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
319868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
319971e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier          ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
320068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
320168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
320271e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier          ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
320368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
320468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
320571e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier          ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
320668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
320768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
320868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected primitive type: " << type;
320968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
321071e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier      if (ptr != nullptr && soa.ForceCopy()) {
321171e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier        ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
321268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (is_copy != nullptr) {
321368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *is_copy = JNI_TRUE;
321468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
321568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
321671e46c1a2e1a8c2ef87b6137e8503dd12e18bb8dMathieu Chartier      result.p = ptr;
321768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "p", &result)) {
321868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return const_cast<void*>(result.p);
321968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
322068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
322168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
322268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
322368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
322468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
322568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                            JNIEnv* env, jarray array, void* elems, jint mode) {
322668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
322768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, function_name);
322868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
322968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (soa.ForceCopy()) {
323068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
323168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
323268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (!soa.ForceCopy() || elems != nullptr) {
323368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
323468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (sc.Check(soa, true, "Eapr", args)) {
323568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (type) {
323668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimBoolean:
323768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
323868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                        reinterpret_cast<jboolean*>(elems), mode);
323968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
324068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimByte:
324168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
324268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                     reinterpret_cast<jbyte*>(elems), mode);
324368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
324468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimChar:
324568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
324668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                     reinterpret_cast<jchar*>(elems), mode);
324768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
324868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimShort:
324968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
325068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                      reinterpret_cast<jshort*>(elems), mode);
325168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
325268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimInt:
325368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
325468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                    reinterpret_cast<jint*>(elems), mode);
325568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
325668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimLong:
325768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
325868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                     reinterpret_cast<jlong*>(elems), mode);
325968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
326068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimFloat:
326168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
326268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                      reinterpret_cast<jfloat*>(elems), mode);
326368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
326468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimDouble:
326568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
326668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                       reinterpret_cast<jdouble*>(elems), mode);
326768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
326868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
326968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected primitive type: " << type;
327068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
327168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          JniValueType result;
327268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.V = nullptr;
327368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          sc.Check(soa, false, "V", &result);
327468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
327568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
327668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
327768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
327868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
327968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
328068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                      jarray array, jsize start, jsize len, void* buf) {
328168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
328268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
328368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
328468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
328568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
328668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
328768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
328868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
328968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
329068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                              reinterpret_cast<jboolean*>(buf));
329168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
329268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
329368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
329468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                           reinterpret_cast<jbyte*>(buf));
329568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
329668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
329768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
329868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                           reinterpret_cast<jchar*>(buf));
329968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
330068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
330168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
330268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                            reinterpret_cast<jshort*>(buf));
330368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
330468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
330568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
330668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                          reinterpret_cast<jint*>(buf));
330768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
330868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
330968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
331068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                           reinterpret_cast<jlong*>(buf));
331168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
331268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
331368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
331468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                            reinterpret_cast<jfloat*>(buf));
331568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
331668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
331768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
331868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                             reinterpret_cast<jdouble*>(buf));
331968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
332068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
332168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected primitive type: " << type;
332268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
332368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
332468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
332568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
332668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
332768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
332868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
332968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
333068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                      jarray array, jsize start, jsize len, const void* buf) {
333168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
333268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
333368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
333468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
333568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
333668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
333768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
333868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
333968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
334068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                              reinterpret_cast<const jboolean*>(buf));
334168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
334268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
334368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
334468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                           reinterpret_cast<const jbyte*>(buf));
334568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
334668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
334768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
334868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                           reinterpret_cast<const jchar*>(buf));
334968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
335068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
335168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
335268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                              reinterpret_cast<const jshort*>(buf));
335368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
335468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
335568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
335668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                          reinterpret_cast<const jint*>(buf));
335768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
335868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
335968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
336068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                              reinterpret_cast<const jlong*>(buf));
336168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
336268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
336368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
336468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                            reinterpret_cast<const jfloat*>(buf));
336568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
336668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
336768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
336868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                             reinterpret_cast<const jdouble*>(buf));
336968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
337068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
337168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected primitive type: " << type;
337268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
337368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
337468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
337568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
337668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
3377a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3378a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
3379a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3380a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNINativeInterface gCheckNativeInterface = {
3381ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved0.
3382ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved1.
3383ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved2.
3384ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved3.
3385a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetVersion,
3386a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::DefineClass,
3387a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::FindClass,
3388a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::FromReflectedMethod,
3389a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::FromReflectedField,
3390a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ToReflectedMethod,
3391a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetSuperclass,
3392a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::IsAssignableFrom,
3393a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ToReflectedField,
3394a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::Throw,
3395a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ThrowNew,
3396a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ExceptionOccurred,
3397a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ExceptionDescribe,
3398a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ExceptionClear,
3399a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::FatalError,
3400a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::PushLocalFrame,
3401a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::PopLocalFrame,
3402a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewGlobalRef,
3403a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::DeleteGlobalRef,
3404a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::DeleteLocalRef,
3405a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::IsSameObject,
3406a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewLocalRef,
3407a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::EnsureLocalCapacity,
3408a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::AllocObject,
3409a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewObject,
3410a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewObjectV,
3411a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewObjectA,
3412a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetObjectClass,
3413a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::IsInstanceOf,
3414a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetMethodID,
3415a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallObjectMethod,
3416a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallObjectMethodV,
3417a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallObjectMethodA,
3418a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallBooleanMethod,
3419a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallBooleanMethodV,
3420a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallBooleanMethodA,
3421a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallByteMethod,
3422a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallByteMethodV,
3423a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallByteMethodA,
3424a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallCharMethod,
3425a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallCharMethodV,
3426a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallCharMethodA,
3427a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallShortMethod,
3428a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallShortMethodV,
3429a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallShortMethodA,
3430a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallIntMethod,
3431a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallIntMethodV,
3432a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallIntMethodA,
3433a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallLongMethod,
3434a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallLongMethodV,
3435a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallLongMethodA,
3436a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallFloatMethod,
3437a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallFloatMethodV,
3438a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallFloatMethodA,
3439a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallDoubleMethod,
3440a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallDoubleMethodV,
3441a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallDoubleMethodA,
3442a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallVoidMethod,
3443a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallVoidMethodV,
3444a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallVoidMethodA,
3445a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualObjectMethod,
3446a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualObjectMethodV,
3447a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualObjectMethodA,
3448a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualBooleanMethod,
3449a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualBooleanMethodV,
3450a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualBooleanMethodA,
3451a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualByteMethod,
3452a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualByteMethodV,
3453a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualByteMethodA,
3454a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualCharMethod,
3455a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualCharMethodV,
3456a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualCharMethodA,
3457a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualShortMethod,
3458a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualShortMethodV,
3459a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualShortMethodA,
3460a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualIntMethod,
3461a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualIntMethodV,
3462a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualIntMethodA,
3463a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualLongMethod,
3464a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualLongMethodV,
3465a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualLongMethodA,
3466a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualFloatMethod,
3467a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualFloatMethodV,
3468a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualFloatMethodA,
3469a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualDoubleMethod,
3470a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualDoubleMethodV,
3471a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualDoubleMethodA,
3472a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualVoidMethod,
3473a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualVoidMethodV,
3474a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualVoidMethodA,
3475a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetFieldID,
3476a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetObjectField,
3477a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetBooleanField,
3478a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetByteField,
3479a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetCharField,
3480a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetShortField,
3481a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetIntField,
3482a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetLongField,
3483a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetFloatField,
3484a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDoubleField,
3485a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetObjectField,
3486a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetBooleanField,
3487a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetByteField,
3488a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetCharField,
3489a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetShortField,
3490a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetIntField,
3491a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetLongField,
3492a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetFloatField,
3493a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetDoubleField,
3494a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticMethodID,
3495a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticObjectMethod,
3496a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticObjectMethodV,
3497a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticObjectMethodA,
3498a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticBooleanMethod,
3499a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticBooleanMethodV,
3500a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticBooleanMethodA,
3501a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticByteMethod,
3502a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticByteMethodV,
3503a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticByteMethodA,
3504a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticCharMethod,
3505a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticCharMethodV,
3506a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticCharMethodA,
3507a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticShortMethod,
3508a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticShortMethodV,
3509a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticShortMethodA,
3510a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticIntMethod,
3511a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticIntMethodV,
3512a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticIntMethodA,
3513a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticLongMethod,
3514a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticLongMethodV,
3515a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticLongMethodA,
3516a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticFloatMethod,
3517a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticFloatMethodV,
3518a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticFloatMethodA,
3519a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticDoubleMethod,
3520a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticDoubleMethodV,
3521a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticDoubleMethodA,
3522a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticVoidMethod,
3523a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticVoidMethodV,
3524a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticVoidMethodA,
3525a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticFieldID,
3526a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticObjectField,
3527a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticBooleanField,
3528a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticByteField,
3529a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticCharField,
3530a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticShortField,
3531a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticIntField,
3532a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticLongField,
3533a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticFloatField,
3534a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticDoubleField,
3535a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticObjectField,
3536a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticBooleanField,
3537a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticByteField,
3538a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticCharField,
3539a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticShortField,
3540a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticIntField,
3541a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticLongField,
3542a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticFloatField,
3543a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticDoubleField,
3544a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewString,
3545a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringLength,
3546a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringChars,
3547a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseStringChars,
3548a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewStringUTF,
3549a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringUTFLength,
3550a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringUTFChars,
3551a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseStringUTFChars,
3552a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetArrayLength,
3553a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewObjectArray,
3554a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetObjectArrayElement,
3555a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetObjectArrayElement,
3556a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewBooleanArray,
3557a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewByteArray,
3558a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewCharArray,
3559a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewShortArray,
3560a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewIntArray,
3561a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewLongArray,
3562a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewFloatArray,
3563a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewDoubleArray,
3564a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetBooleanArrayElements,
3565a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetByteArrayElements,
3566a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetCharArrayElements,
3567a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetShortArrayElements,
3568a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetIntArrayElements,
3569a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetLongArrayElements,
3570a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetFloatArrayElements,
3571a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDoubleArrayElements,
3572a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseBooleanArrayElements,
3573a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseByteArrayElements,
3574a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseCharArrayElements,
3575a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseShortArrayElements,
3576a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseIntArrayElements,
3577a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseLongArrayElements,
3578a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseFloatArrayElements,
3579a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseDoubleArrayElements,
3580a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetBooleanArrayRegion,
3581a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetByteArrayRegion,
3582a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetCharArrayRegion,
3583a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetShortArrayRegion,
3584a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetIntArrayRegion,
3585a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetLongArrayRegion,
3586a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetFloatArrayRegion,
3587a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDoubleArrayRegion,
3588a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetBooleanArrayRegion,
3589a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetByteArrayRegion,
3590a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetCharArrayRegion,
3591a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetShortArrayRegion,
3592a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetIntArrayRegion,
3593a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetLongArrayRegion,
3594a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetFloatArrayRegion,
3595a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetDoubleArrayRegion,
3596a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::RegisterNatives,
3597a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::UnregisterNatives,
3598a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::MonitorEnter,
3599a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::MonitorExit,
3600a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetJavaVM,
3601a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringRegion,
3602a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringUTFRegion,
3603a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetPrimitiveArrayCritical,
3604a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleasePrimitiveArrayCritical,
3605a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringCritical,
3606a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseStringCritical,
3607a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewWeakGlobalRef,
3608a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::DeleteWeakGlobalRef,
3609a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ExceptionCheck,
3610a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewDirectByteBuffer,
3611a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDirectBufferAddress,
3612a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDirectBufferCapacity,
3613a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetObjectRefType,
3614a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
3615a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3616a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNINativeInterface* GetCheckJniNativeInterface() {
3617a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  return &gCheckNativeInterface;
3618a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}
3619a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3620a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesclass CheckJII {
3621ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes public:
3622a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint DestroyJavaVM(JavaVM* vm) {
362368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
362468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.v = vm}};
362568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
362668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
362768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.i = BaseVm(vm)->DestroyJavaVM(vm);
3628def194e182ce703077e20bb59025998039fadb75Andreas Gampe    // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
3629def194e182ce703077e20bb59025998039fadb75Andreas Gampe    // which will delete the JavaVMExt.
3630def194e182ce703077e20bb59025998039fadb75Andreas Gampe    sc.CheckNonHeap(nullptr, false, "i", &result);
363168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result.i;
3632a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3633a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3634a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
363568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
363668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
363768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
363868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
363968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
364068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
364168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result.i;
3642a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3643a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3644a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
364568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
364668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
364768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
364868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
364968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
365068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
365168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result.i;
3652a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3653a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3654a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint DetachCurrentThread(JavaVM* vm) {
365568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
365668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.v = vm}};
365768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
365868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
365968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.i = BaseVm(vm)->DetachCurrentThread(vm);
366068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
366168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result.i;
3662a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3663a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
366468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
366568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
366668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
366768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
366868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
366968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
367068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
367168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result.i;
3672a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3673a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3674a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes private:
367568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
367668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
3677a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3678a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
3679a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3680a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNIInvokeInterface gCheckInvokeInterface = {
3681ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved0
3682ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved1
3683ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved2
3684a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::DestroyJavaVM,
3685a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::AttachCurrentThread,
3686a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::DetachCurrentThread,
3687a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::GetEnv,
3688a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::AttachCurrentThreadAsDaemon
3689a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
3690a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3691a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNIInvokeInterface* GetCheckJniInvokeInterface() {
3692a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  return &gCheckInvokeInterface;
3693a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}
3694a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3695a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}  // namespace art
3696