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
19ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe#include <iomanip>
20a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include <sys/mman.h>
21a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include <zlib.h>
22a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
23c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier#include "art_field-inl.h"
24e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "art_method-inl.h"
2507ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
26c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers#include "base/to_str.h"
27a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include "class_linker.h"
282dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "class_linker-inl.h"
294f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h"
301d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/space.h"
3168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#include "java_vm_ext.h"
32277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#include "jni_internal.h"
332dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h"
342dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h"
352dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h"
36b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers#include "mirror/string-inl.h"
372dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/throwable.h"
3858df32711162823647356afe25ae2cde04133563Jeff Hao#include "runtime.h"
3900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h"
40a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include "thread.h"
4168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#include "well_known_classes.h"
42a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
43a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesnamespace art {
44a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
45a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/*
46a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
47a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *      JNI function helpers
48a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
49a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */
50a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
513f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes// Flags passed into ScopedCheck.
52a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define kFlag_Default       0x0000
53a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
543f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritBad       0x0000      // Calling while in critical is not allowed.
553f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritOkay      0x0001      // Calling while in critical is allowed.
563f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritGet       0x0002      // This is a critical "get".
573f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritRelease   0x0003      // This is a critical "release".
583f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritMask      0x0003      // Bit mask to get "crit" value.
59a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
603f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_ExcepBad      0x0000      // Raised exceptions are not allowed.
613f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_ExcepOkay     0x0004      // Raised exceptions are allowed.
62a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
633f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_Release       0x0010      // Are we in a non-critical release function?
643f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_NullableUtf   0x0020      // Are our UTF parameters nullable?
65a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
663f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_Invocation    0x8000      // Part of the invocation interface (JavaVM*).
67a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
68485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes#define kFlag_ForceTrace    0x80000000  // Add this to a JNI function's flags if you want to trace every call.
6948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light
7048ffe0653c51c0785c8bd260fef486922ba00e4eAlex Lightclass VarArgs;
7168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers/*
7268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Java primitive types:
7368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * B - jbyte
7468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * C - jchar
7568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * D - jdouble
7668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * F - jfloat
7768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * I - jint
7868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * J - jlong
7968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * S - jshort
8068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Z - jboolean (shown as true and false)
8168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * V - void
8268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *
8368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Java reference types:
8468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * L - jobject
8568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * a - jarray
8668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * c - jclass
8768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * s - jstring
8868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * t - jthrowable
8968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *
9068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * JNI types:
9168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
9268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * f - jfieldID
9368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION)
9468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * m - jmethodID
9568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * p - void*
9668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * r - jint (for release mode arguments)
9768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * u - const char* (Modified UTF-8)
9868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * z - jsize (for lengths; use i if negative values are okay)
9968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * v - JavaVM*
10068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * w - jobjectRefType
10168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * E - JNIEnv*
10268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * . - no argument; just print "..." (used for varargs JNI calls)
10368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *
10468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers */
10568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogersunion JniValueType {
10668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jarray a;
10768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jboolean b;
10868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jclass c;
10968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jfieldID f;
11068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jint i;
11168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jmethodID m;
11268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const void* p;  // Pointer.
11368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jint r;  // Release mode.
11468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jstring s;
11568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jthrowable t;
11668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const char* u;  // Modified UTF-8.
11768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  JavaVM* v;
11868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jobjectRefType w;
11968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jsize z;
12068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jbyte B;
12168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jchar C;
12268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jdouble D;
12368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  JNIEnv* E;
12468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jfloat F;
12568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jint I;
12668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jlong J;
12768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jobject L;
12868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jshort S;
12968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const void* V;  // void
13068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  jboolean Z;
13148ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  const VarArgs* va;
13248ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light};
13348ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light
13448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light/*
13548ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light * A structure containing all the information needed to validate varargs arguments.
13648ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light *
13748ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light * Note that actually getting the arguments from this structure mutates it so should only be done on
13848ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light * owned copies.
13948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light */
14048ffe0653c51c0785c8bd260fef486922ba00e4eAlex Lightclass VarArgs {
14148ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light public:
14248ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  VarArgs(jmethodID m, va_list var) : m_(m), type_(kTypeVaList), cnt_(0) {
14348ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    va_copy(vargs_, var);
14448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  }
14548ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light
14648ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  VarArgs(jmethodID m, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(0), ptr_(vals) {}
14748ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light
14848ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  ~VarArgs() {
14948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    if (type_ == kTypeVaList) {
15048ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      va_end(vargs_);
15148ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    }
15248ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  }
15348ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light
15448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  VarArgs(VarArgs&& other) {
15548ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    m_ = other.m_;
15648ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    cnt_ = other.cnt_;
15748ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    type_ = other.type_;
15848ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    if (other.type_ == kTypeVaList) {
15948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      va_copy(vargs_, other.vargs_);
16048ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    } else {
16148ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      ptr_ = other.ptr_;
16248ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    }
16348ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  }
16448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light
16548ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  // This method is const because we need to ensure that one only uses the GetValue method on an
16648ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  // owned copy of the VarArgs. This is because getting the next argument from a va_list is a
16748ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  // mutating operation. Therefore we pass around these VarArgs with the 'const' qualifier and when
16848ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  // we want to use one we need to Clone() it.
16948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  VarArgs Clone() const {
17048ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    if (type_ == kTypeVaList) {
17148ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      // const_cast needed to make sure the compiler is okay with va_copy, which (being a macro) is
17248ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      // messed up if the source argument is not the exact type 'va_list'.
17348ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      return VarArgs(m_, cnt_, const_cast<VarArgs*>(this)->vargs_);
17448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    } else {
17548ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      return VarArgs(m_, cnt_, ptr_);
17648ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    }
17748ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  }
17848ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light
17948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  jmethodID GetMethodID() const {
18048ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    return m_;
18148ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  }
18248ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light
18348ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  JniValueType GetValue(char fmt) {
18448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    JniValueType o;
18548ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    if (type_ == kTypeVaList) {
18648ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      switch (fmt) {
18748ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        case 'Z': o.Z = static_cast<jboolean>(va_arg(vargs_, jint)); break;
18848ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        case 'B': o.B = static_cast<jbyte>(va_arg(vargs_, jint)); break;
18948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        case 'C': o.C = static_cast<jchar>(va_arg(vargs_, jint)); break;
19048ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        case 'S': o.S = static_cast<jshort>(va_arg(vargs_, jint)); break;
19148ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        case 'I': o.I = va_arg(vargs_, jint); break;
19248ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        case 'J': o.J = va_arg(vargs_, jlong); break;
19348ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        case 'F': o.F = static_cast<jfloat>(va_arg(vargs_, jdouble)); break;
19448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        case 'D': o.D = va_arg(vargs_, jdouble); break;
19548ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        case 'L': o.L = va_arg(vargs_, jobject); break;
19648ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        default:
19748ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light          LOG(FATAL) << "Illegal type format char " << fmt;
19848ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light          UNREACHABLE();
19948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      }
20048ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    } else {
20148ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      CHECK(type_ == kTypePtr);
20248ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      jvalue v = ptr_[cnt_];
20348ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      cnt_++;
20448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      switch (fmt) {
20548ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        case 'Z': o.Z = v.z; break;
20648ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        case 'B': o.B = v.b; break;
20748ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        case 'C': o.C = v.c; break;
20848ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        case 'S': o.S = v.s; break;
20948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        case 'I': o.I = v.i; break;
21048ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        case 'J': o.J = v.j; break;
21148ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        case 'F': o.F = v.f; break;
21248ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        case 'D': o.D = v.d; break;
21348ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        case 'L': o.L = v.l; break;
21448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        default:
21548ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light          LOG(FATAL) << "Illegal type format char " << fmt;
21648ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light          UNREACHABLE();
21748ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      }
21848ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    }
21948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    return o;
22048ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  }
22148ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light
22248ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light private:
22348ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  VarArgs(jmethodID m, uint32_t cnt, va_list var) : m_(m), type_(kTypeVaList), cnt_(cnt) {
22448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    va_copy(vargs_, var);
22548ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  }
22648ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light
22748ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  VarArgs(jmethodID m, uint32_t cnt, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(cnt), ptr_(vals) {}
22848ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light
22948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  enum VarArgsType {
23048ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    kTypeVaList,
23148ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    kTypePtr,
23248ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  };
23348ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light
23448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  jmethodID m_;
23548ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  VarArgsType type_;
23648ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  uint32_t cnt_;
23748ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  union {
23848ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    va_list vargs_;
23948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    const jvalue* ptr_;
24048ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  };
241a09576416788b916095739e43a16917e7948f3a4Elliott Hughes};
242a09576416788b916095739e43a16917e7948f3a4Elliott Hughes
243a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesclass ScopedCheck {
244ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes public:
2453887c468d731420e929e6ad3acf190d5431e94fcRoland Levillain  ScopedCheck(int flags, const char* functionName, bool has_method = true)
24668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      : function_name_(functionName), flags_(flags), indent_(0), has_method_(has_method) {
24700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
24800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
24968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  ~ScopedCheck() {}
250a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
25181ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
25281ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
25381ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
25481ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes  // circumstances, but this is incorrect.
25568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckClassName(const char* class_name) {
2562d10b206f9d0b97396b7dadb9a6415cd39efd341Ian Rogers    if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
25768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("illegal class name '%s'\n"
25868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             "    (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
25968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             class_name);
26068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
261a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
26268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
263a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
264a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
265a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
266a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that this instance field ID is valid for this object.
267a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
268a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Assumes "jobj" has already been validated.
269a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
27068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
27190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
27268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
27368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (o == nullptr) {
27468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("field operation on NULL object: %p", java_object);
27568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
27668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
27768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
2784c13a3ff475f206c4d0a86ee2595c45392fd942fMathieu Chartier      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
27968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("field operation on invalid %s: %p",
28068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
28168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             java_object);
28268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
283a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
284a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
285c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    ArtField* f = CheckFieldID(soa, fid);
286ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (f == nullptr) {
28768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
28832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
2892dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Class* c = o->GetClass();
29061c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier    if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
29168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("jfieldID %s not valid for an object of class %s",
29268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             PrettyField(f).c_str(), PrettyTypeOf(o).c_str());
29368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
294a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
29568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
296a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
297a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
298a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
2992cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier   * Verify that the pointer value is non-null.
300a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
30168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckNonNull(const void* ptr) {
30268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (UNLIKELY(ptr == nullptr)) {
30368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("non-nullable argument was NULL");
30468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
305a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
30668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
307a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
308a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
309a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
310a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that the method's return type matches the type of call.
311a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * 'expectedType' will be "L" for all objects, including arrays.
312a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
31368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
31468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                         jmethodID mid, Primitive::Type type, InvokeType invoke)
31590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
316e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    ArtMethod* m = CheckMethodID(soa, mid);
317ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (m == nullptr) {
31868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
31932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
32068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (type != Primitive::GetType(m->GetShorty()[0])) {
32168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("the return type of %s does not match %s", function_name_, PrettyMethod(m).c_str());
32268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
3233f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    }
32468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    bool is_static = (invoke == kStatic);
32568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (is_static != m->IsStatic()) {
32668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (is_static) {
32768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("calling non-static method %s with %s",
32868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               PrettyMethod(m).c_str(), function_name_);
329a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      } else {
33068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("calling static method %s with %s",
33168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               PrettyMethod(m).c_str(), function_name_);
33268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
33368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
33468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
33568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (invoke != kVirtual) {
33668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      mirror::Class* c = soa.Decode<mirror::Class*>(jc);
33768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
33868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
33968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            PrettyMethod(m).c_str(), PrettyClass(c).c_str());
34068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
34168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
34268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
34368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (invoke != kStatic) {
34468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      mirror::Object* o = soa.Decode<mirror::Object*>(jobj);
345a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier      if (o == nullptr) {
346a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier        AbortF("can't call %s on null object", PrettyMethod(m).c_str());
347a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier        return false;
348a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier      } else if (!o->InstanceOf(m->GetDeclaringClass())) {
34968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
35068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
351a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
352a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
35368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
354a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
355a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
356a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
357a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that this static field ID is valid for this class.
358a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
359a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Assumes "java_class" has already been validated.
360a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
36168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
36290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
36368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
364c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    ArtField* f = CheckFieldID(soa, fid);
365ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (f == nullptr) {
36668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
36732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
368a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    if (f->GetDeclaringClass() != c) {
36968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("static jfieldID %p not valid for class %s", fid, PrettyClass(c).c_str());
37068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
371a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
37268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
373a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
374a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
375a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
376e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes   * Verify that "mid" is appropriate for "java_class".
377a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
378a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * A mismatch isn't dangerous, because the jmethodID defines the class.  In
379e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes   * fact, java_class is unused in the implementation.  It's best if we don't
380a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * allow bad code in the system though.
381a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
382e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes   * Instances of "java_class" must be instances of the method's declaring class.
383a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
38468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
38590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
386e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    ArtMethod* m = CheckMethodID(soa, mid);
387ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (m == nullptr) {
38868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
38932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
39068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
39167fe2b41a6afccf6ab1a58879eae3e0e8f3d6c7aBrian Carlstrom    if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
39268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("can't call static %s on class %s", PrettyMethod(m).c_str(), PrettyClass(c).c_str());
39368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
394a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
39568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
396a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
397a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
398a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
399a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify that "mid" is appropriate for "jobj".
400a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
401a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Make sure the object is an instance of the method's declaring class.
402a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * (Note the mid might point to a declaration in an interface; this
403a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * will be handled automatically by the instanceof check.)
404a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
40568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
40690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
407e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    ArtMethod* m = CheckMethodID(soa, mid);
408ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (m == nullptr) {
40968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
41032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
41168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
412a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier    if (o == nullptr) {
413a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier      AbortF("can't call %s on null object", PrettyMethod(m).c_str());
414a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier      return false;
415a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier    } else if (!o->InstanceOf(m->GetDeclaringClass())) {
41668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
41768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
418a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
41968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
420a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
421a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
422a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /**
423a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * The format string is a sequence of the following characters,
424a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * and must be followed by arguments of the corresponding types
425a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * in the same order.
426a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
427a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Java primitive types:
428a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * B - jbyte
429a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * C - jchar
430a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * D - jdouble
431a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * F - jfloat
432a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * I - jint
433a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * J - jlong
434a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * S - jshort
435a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Z - jboolean (shown as true and false)
436a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * V - void
437a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
438a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Java reference types:
439a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * L - jobject
440a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * a - jarray
441a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * c - jclass
442a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * s - jstring
443a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
444a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * JNI types:
445a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
446a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * f - jfieldID
447a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * m - jmethodID
448a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * p - void*
449a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * r - jint (for release mode arguments)
45078090d119d5e23ff35ecddac1f4a98e4c050bb07Elliott Hughes   * u - const char* (Modified UTF-8)
451a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * z - jsize (for lengths; use i if negative values are okay)
452a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * v - JavaVM*
453a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * E - JNIEnv*
45448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light   * . - VarArgs* for Jni calls with variable length arguments
455a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
456a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
457a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
45868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
45990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
460e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    ArtMethod* traceMethod = nullptr;
46168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (has_method_ && soa.Vm()->IsTracingEnabled()) {
462a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      // We need to guard some of the invocation interface's calls: a bad caller might
463a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
464a09576416788b916095739e43a16917e7948f3a4Elliott Hughes      Thread* self = Thread::Current();
465ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
466ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        traceMethod = self->GetCurrentMethod(nullptr);
467a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
468a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
469a09576416788b916095739e43a16917e7948f3a4Elliott Hughes
470ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (((flags_ & kFlag_ForceTrace) != 0) ||
47168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
472a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      std::string msg;
47368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      for (size_t i = 0; fmt[i] != '\0'; ++i) {
47468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
47568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (fmt[i + 1] != '\0') {
47668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(&msg, ", ");
47768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
47868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
47968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
48068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if ((flags_ & kFlag_ForceTrace) != 0) {
48168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
48268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      } else if (entry) {
48368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (has_method_) {
48468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          std::string methodName(PrettyMethod(traceMethod, false));
48568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
48668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          indent_ = methodName.size() + 1;
487a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else {
48868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
48968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          indent_ = 0;
49068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
49168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      } else {
49268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
49368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
49468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
49568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
49668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // We always do the thorough checks on entry, and never on exit...
49768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (entry) {
49868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      for (size_t i = 0; fmt[i] != '\0'; ++i) {
49968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
50068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          return false;
501a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
50268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
50368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
50468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
50568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
50668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
50768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
50868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
509def194e182ce703077e20bb59025998039fadb75Andreas Gampe    if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
51068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // We need to guard some of the invocation interface's calls: a bad caller might
51168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
51268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      Thread* self = Thread::Current();
51368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
51468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        ScopedObjectAccess soa(self);
515e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier        ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
51668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
51768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
51868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
51968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (should_trace) {
52068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      std::string msg;
52168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      for (size_t i = 0; fmt[i] != '\0'; ++i) {
52268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        TraceNonHeapValue(fmt[i], args[i], &msg);
52368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (fmt[i + 1] != '\0') {
524a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          StringAppendF(&msg, ", ");
525a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
526a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
527a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
528485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes      if ((flags_ & kFlag_ForceTrace) != 0) {
529485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes        LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
530485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes      } else if (entry) {
53132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        if (has_method_) {
53268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          Thread* self = Thread::Current();
53368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          ScopedObjectAccess soa(self);
534e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier          ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
535a09576416788b916095739e43a16917e7948f3a4Elliott Hughes          std::string methodName(PrettyMethod(traceMethod, false));
53632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
53732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          indent_ = methodName.size() + 1;
538a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        } else {
53932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
54032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes          indent_ = 0;
541a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
542a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      } else {
54332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes        LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
544a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
545a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
546a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
547a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // We always do the thorough checks on entry, and never on exit...
548a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    if (entry) {
54968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      for (size_t i = 0; fmt[i] != '\0'; ++i) {
55068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (!CheckNonHeapValue(fmt[i], args[i])) {
55168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          return false;
552a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
553a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
554a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
55568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
55668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
55768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
55868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
55990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
56068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Object* method = soa.Decode<mirror::Object*>(jmethod);
56168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (method == nullptr) {
56268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected non-null method");
56368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
56468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
56568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Class* c = method->GetClass();
56668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Method) != c &&
56768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
56868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected java.lang.reflect.Method or "
56968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          "java.lang.reflect.Constructor but got object of type %s: %p",
57068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          PrettyTypeOf(method).c_str(), jmethod);
57168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
57268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
57368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
57468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
57568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
57668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckConstructor(ScopedObjectAccess& soa, jmethodID mid)
57790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
578e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    ArtMethod* method = soa.DecodeMethod(mid);
57968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (method == nullptr) {
58068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected non-null constructor");
58168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
58268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
58368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!method->IsConstructor() || method->IsStatic()) {
584e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier      AbortF("expected a constructor but %s: %p", PrettyMethod(method).c_str(), mid);
58568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
58668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
58768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
58868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
58968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
59068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
59190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
59268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Object* field = soa.Decode<mirror::Object*>(jfield);
59368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (field == nullptr) {
59468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected non-null java.lang.reflect.Field");
59568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
59668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
59768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Class* c = field->GetClass();
59868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Field) != c) {
59968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
60068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             PrettyTypeOf(field).c_str(), jfield);
60168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
60268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
60368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
60468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
60568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
60668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
60790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
60868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Object* obj = soa.Decode<mirror::Object*>(jobj);
60968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!obj->GetClass()->IsThrowableClass()) {
61068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected java.lang.Throwable but got object of type "
61168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             "%s: %p", PrettyTypeOf(obj).c_str(), obj);
61268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
61368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
61468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
61568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
61668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
61768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
61890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
61968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Class* c = soa.Decode<mirror::Class*>(jc);
62068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!c->IsThrowableClass()) {
62168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected java.lang.Throwable class but got object of "
62268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             "type %s: %p", PrettyDescriptor(c).c_str(), c);
62368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
62468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
62568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
62668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
62768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
6286a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
62968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    IndirectRefKind found_kind;
63068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (expected_kind == kLocal) {
63168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      found_kind = GetIndirectRefKind(obj);
63268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
63368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        found_kind = kLocal;
63468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
63568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    } else {
63668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      found_kind = GetIndirectRefKind(obj);
63768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
63868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (obj != nullptr && found_kind != expected_kind) {
63968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("expected reference of kind %s but found %s: %p",
64068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             ToStr<IndirectRefKind>(expected_kind).c_str(),
64168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             ToStr<IndirectRefKind>(GetIndirectRefKind(obj)).c_str(),
64268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             obj);
64368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
64468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
64568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
64668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
64768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
64868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
64990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
65068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Class* c = soa.Decode<mirror::Class*>(jc);
65168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!c->IsInstantiableNonArray()) {
65268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("can't make objects of type %s: %p", PrettyDescriptor(c).c_str(), c);
65368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
65468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
65568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
65668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
65768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
65868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
65990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
66068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!CheckArray(soa, array)) {
66168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
66268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
66368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Array* a = soa.Decode<mirror::Array*>(array);
66468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
66568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("incompatible array type %s expected %s[]: %p",
66668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             PrettyDescriptor(a->GetClass()).c_str(), PrettyDescriptor(type).c_str(), array);
66768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
66868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
66968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
67068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
67168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
67268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
67368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                        Primitive::Type type)
67490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
67568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
67668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
67768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
67868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
67968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
68068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
681c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    ArtField* field = soa.DecodeField(fid);
68268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    DCHECK(field != nullptr);  // Already checked by Check.
68368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (is_static != field->IsStatic()) {
68468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("attempt to access %s field %s: %p",
68568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             field->IsStatic() ? "static" : "non-static", PrettyField(field).c_str(), fid);
68668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
68768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
68868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (type != field->GetTypeAsPrimitiveType()) {
68968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
69068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             PrettyField(field).c_str(), PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
69168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             PrettyDescriptor(type).c_str(), fid);
69268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
69368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
69468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (is_static) {
69568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      mirror::Object* o = soa.Decode<mirror::Object*>(obj);
69668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (o == nullptr || !o->IsClass()) {
69768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("attempt to access static field %s with a class argument of type %s: %p",
69868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid);
69968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
70068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
70168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      mirror::Class* c = o->AsClass();
70268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (field->GetDeclaringClass() != c) {
70368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
70468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               PrettyField(field).c_str(), PrettyDescriptor(c).c_str(), fid);
70568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
70668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
70768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    } else {
70868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      mirror::Object* o = soa.Decode<mirror::Object*>(obj);
70968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
71068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("attempt to access field %s from an object argument of type %s: %p",
71168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid);
71268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
71368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
71468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
71568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
716a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
717a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
71868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers private:
719a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes  enum InstanceKind {
720a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    kClass,
7210f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes    kDirectByteBuffer,
7220f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes    kObject,
7230f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes    kString,
7240f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes    kThrowable,
725a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes  };
726a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
727a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes  /*
7282cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier   * Verify that "jobj" is a valid non-null object reference, and points to
729a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   * an instance of expectedClass.
730a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   *
731a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   * Because we're looking at an object on the GC heap, we have to switch
732a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   * to "running" mode before doing the checks.
733a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes   */
73468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
73590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
736ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const char* what = nullptr;
737a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    switch (kind) {
738a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kClass:
739a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "jclass";
740a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
741a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kDirectByteBuffer:
742a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "direct ByteBuffer";
743a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
744a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kObject:
745a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "jobject";
746a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
747a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kString:
748a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "jstring";
749a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
750a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kThrowable:
751a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      what = "jthrowable";
752a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
753a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    default:
7547b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes      LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
755a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
756a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
757ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (java_object == nullptr) {
75868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (null_ok) {
75968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return true;
76068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      } else {
76168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("%s received NULL %s", function_name_, what);
76268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
76368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
764a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
765a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
76668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Object* obj = soa.Decode<mirror::Object*>(java_object);
767c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    if (obj == nullptr) {
768c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      // Either java_object is invalid or is a cleared weak.
769c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
770c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      bool okay;
771c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      if (GetIndirectRefKind(ref) != kWeakGlobal) {
772c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        okay = false;
773c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      } else {
774c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
775c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
776c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      }
777c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      if (!okay) {
778c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        AbortF("%s is an invalid %s: %p (%p)",
779c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers               what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
780c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers               java_object, obj);
781c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        return false;
782c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers      }
783c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    }
784c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers
785590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) {
7864c13a3ff475f206c4d0a86ee2595c45392fd942fMathieu Chartier      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
78768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("%s is an invalid %s: %p (%p)",
78868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
78968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             java_object, obj);
790a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      return false;
791a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
792a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
793a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    bool okay = true;
794a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    switch (kind) {
795a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kClass:
796a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      okay = obj->IsClass();
797a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
798a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kDirectByteBuffer:
799a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      UNIMPLEMENTED(FATAL);
800a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
801a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kString:
802a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      okay = obj->GetClass()->IsStringClass();
803a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
804a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kThrowable:
805a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      okay = obj->GetClass()->IsThrowableClass();
806a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
807a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    case kObject:
808a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      break;
809a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
810a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    if (!okay) {
81168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("%s has wrong type: %s", what, PrettyTypeOf(obj).c_str());
812a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes      return false;
813a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
814a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
815a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    return true;
816a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes  }
817a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes
818a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
81968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * Verify that the "mode" argument passed to a primitive array Release
82068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * function is one of the valid values.
821a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
82268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckReleaseMode(jint mode) {
82368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
82468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("unknown value for release mode: %d", mode);
82568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
826a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
82768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
828a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
829a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
83068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
83190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
83268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    switch (fmt) {
83368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'a':  // jarray
83468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckArray(soa, arg.a);
83568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'c':  // jclass
83668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckInstance(soa, kClass, arg.c, false);
83768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'f':  // jfieldID
83868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckFieldID(soa, arg.f) != nullptr;
83968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'm':  // jmethodID
84068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckMethodID(soa, arg.m) != nullptr;
84168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'r':  // release int
84268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckReleaseMode(arg.r);
84368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 's':  // jstring
84468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckInstance(soa, kString, arg.s, false);
84568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 't':  // jthrowable
84668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckInstance(soa, kThrowable, arg.t, false);
84768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'E':  // JNIEnv*
84868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckThread(arg.E);
84968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'L':  // jobject
85068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckInstance(soa, kObject, arg.L, true);
85148ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      case '.':  // A VarArgs list
85248ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        return CheckVarArgs(soa, arg.va);
85368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      default:
85468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckNonHeapValue(fmt, arg);
85568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
85668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
85768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
85848ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  bool CheckVarArgs(ScopedObjectAccess& soa, const VarArgs* args_p)
85948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      SHARED_REQUIRES(Locks::mutator_lock_) {
86048ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    CHECK(args_p != nullptr);
86148ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    VarArgs args(args_p->Clone());
86248ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    ArtMethod* m = CheckMethodID(soa, args.GetMethodID());
86348ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    if (m == nullptr) {
86448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      return false;
86548ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    }
86648ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    uint32_t len = 0;
86748ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    const char* shorty = m->GetShorty(&len);
86848ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    // Skip the return type
86948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    CHECK_GE(len, 1u);
87048ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    len--;
87148ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    shorty++;
87248ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    for (uint32_t i = 0; i < len; i++) {
87348ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      if (!CheckPossibleHeapValue(soa, shorty[i], args.GetValue(shorty[i]))) {
87448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        return false;
87548ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      }
87648ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    }
87748ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    return true;
87848ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light  }
87948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light
88068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckNonHeapValue(char fmt, JniValueType arg) {
88168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    switch (fmt) {
88268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'p':  // TODO: pointer - null or readable?
88368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'v':  // JavaVM*
88468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'B':  // jbyte
88568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'C':  // jchar
88668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'D':  // jdouble
88768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'F':  // jfloat
88868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'I':  // jint
88968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'J':  // jlong
89068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'S':  // jshort
89168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;  // Ignored.
89268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'b':  // jboolean, why two? Fall-through.
89368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'Z':
89468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckBoolean(arg.Z);
89568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'u':  // utf8
89668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if ((flags_ & kFlag_Release) != 0) {
89768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          return CheckNonNull(arg.u);
89868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
89968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
90068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          return CheckUtfString(arg.u, nullable);
90168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
90268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'w':  // jobjectRefType
90368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        switch (arg.w) {
90468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNIInvalidRefType:
90568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNILocalRefType:
90668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNIGlobalRefType:
90768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNIWeakGlobalRefType:
90868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            break;
90968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          default:
91068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            AbortF("Unknown reference type");
91168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            return false;
91268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
91368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
91468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'z':  // jsize
91568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return CheckLengthPositive(arg.z);
91668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      default:
91768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("unknown format specifier: '%c'", fmt);
91868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
91932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
92068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
92132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  }
92232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes
92368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
92468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                              std::string* msg)
92590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
92668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    switch (fmt) {
92768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'L':  // jobject fall-through.
92868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'a':  // jarray fall-through.
92968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 's':  // jstring fall-through.
93068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 't':  // jthrowable fall-through.
93168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (arg.L == nullptr) {
93268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "NULL";
93368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
93468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "%p", arg.L);
93568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
93668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
93768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'c': {  // jclass
93868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        jclass jc = arg.c;
93968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        mirror::Class* c = soa.Decode<mirror::Class*>(jc);
94068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (c == nullptr) {
94168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "NULL";
942c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers        } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) {
94368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "INVALID POINTER:%p", jc);
94468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else if (!c->IsClass()) {
94568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c);
94668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
94768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += PrettyClass(c);
94868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (!entry) {
94968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            StringAppendF(msg, " (%p)", jc);
95068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
95168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
95268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
95368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
95468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'f': {  // jfieldID
95568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        jfieldID fid = arg.f;
956c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier        ArtField* f = soa.DecodeField(fid);
95768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        *msg += PrettyField(f);
95868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (!entry) {
95968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, " (%p)", fid);
96068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
96168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
96268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
96368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'm': {  // jmethodID
96468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        jmethodID mid = arg.m;
965e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier        ArtMethod* m = soa.DecodeMethod(mid);
96668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        *msg += PrettyMethod(m);
96768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (!entry) {
96868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, " (%p)", mid);
96968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
97068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
97168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
97248ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      case '.': {
97348ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        const VarArgs* va = arg.va;
97448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        VarArgs args(va->Clone());
97548ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        ArtMethod* m = soa.DecodeMethod(args.GetMethodID());
97648ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        uint32_t len;
97748ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        const char* shorty = m->GetShorty(&len);
97848ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        CHECK_GE(len, 1u);
97948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        // Skip past return value.
98048ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        len--;
98148ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        shorty++;
98248ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        // Remove the previous ', ' from the message.
98348ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        msg->erase(msg->length() - 2);
98448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        for (uint32_t i = 0; i < len; i++) {
98548ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light          *msg += ", ";
98648ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light          TracePossibleHeapValue(soa, entry, shorty[i], args.GetValue(shorty[i]), msg);
98748ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        }
98848ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        break;
98948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light      }
99068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      default:
99168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        TraceNonHeapValue(fmt, arg, msg);
99268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
99332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    }
99432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes  }
99532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes
99668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
99768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    switch (fmt) {
99868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'B':  // jbyte
99968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (arg.B >= 0 && arg.B < 10) {
100068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "%d", arg.B);
100168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
100268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
100368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
100468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
100568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'C':  // jchar
100668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (arg.C < 0x7f && arg.C >= ' ') {
100768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
100868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
100968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "U+%x", arg.C);
101068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
101168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
101268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'F':  // jfloat
101368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "%g", arg.F);
101468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
101568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'D':  // jdouble
101668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "%g", arg.D);
101768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
101868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'S':  // jshort
101968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "%d", arg.S);
102068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
102168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'i':  // jint - fall-through.
102268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'I':  // jint
102368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "%d", arg.I);
102468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
102568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'J':  // jlong
102668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "%" PRId64, arg.J);
102768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
102868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'Z':  // jboolean
102968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'b':  // jboolean (JNI-style)
103068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        *msg += arg.b == JNI_TRUE ? "true" : "false";
103168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
103268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'V':  // void
103368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        DCHECK(arg.V == nullptr);
103468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        *msg += "void";
103568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
103668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'v':  // JavaVM*
103768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "(JavaVM*)%p", arg.v);
103868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
103968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'E':
104068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "(JNIEnv*)%p", arg.E);
104168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
104268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'z':  // non-negative jsize
104368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        // You might expect jsize to be size_t, but it's not; it's the same as jint.
104468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        // We only treat this specially so we can do the non-negative check.
104568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        // TODO: maybe this wasn't worth it?
104668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        StringAppendF(msg, "%d", arg.z);
104768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
104868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'p':  // void* ("pointer")
104968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (arg.p == nullptr) {
105068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "NULL";
105168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
105268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "(void*) %p", arg.p);
105368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
105468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
105568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'r': {  // jint (release mode)
105668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        jint releaseMode = arg.r;
105768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (releaseMode == 0) {
105868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "0";
105968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else if (releaseMode == JNI_ABORT) {
106068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "JNI_ABORT";
106168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else if (releaseMode == JNI_COMMIT) {
106268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "JNI_COMMIT";
106368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
106468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "invalid release mode %d", releaseMode);
106568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
106668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
106768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
106868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'u':  // const char* (Modified UTF-8)
106968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (arg.u == nullptr) {
107068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *msg += "NULL";
107168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
107268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          StringAppendF(msg, "\"%s\"", arg.u);
107368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
107468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
107568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case 'w':  // jobjectRefType
107668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        switch (arg.w) {
107768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNIInvalidRefType:
107868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            *msg += "invalid reference type";
107968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            break;
108068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNILocalRefType:
108168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            *msg += "local ref type";
108268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            break;
108368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNIGlobalRefType:
108468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            *msg += "global ref type";
108568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            break;
108668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          case JNIWeakGlobalRefType:
108768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            *msg += "weak global ref type";
108868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            break;
108968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          default:
109068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            *msg += "unknown ref type";
109168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            break;
109268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
109368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
109468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      default:
109568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
109668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
109768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
1098a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
10992cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier   * Verify that "array" is non-null and points to an Array object.
1100a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
110168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * Since we're dealing with objects, switch to "running" mode.
1102a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
110368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
110490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
110568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (UNLIKELY(java_array == nullptr)) {
110668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("jarray was NULL");
110768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
1108a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1109a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
111068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
111168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a))) {
11124c13a3ff475f206c4d0a86ee2595c45392fd942fMathieu Chartier      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
111368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("jarray is an invalid %s: %p (%p)",
111468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(),
111568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             java_array, a);
111668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
111768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    } else if (!a->IsArrayInstance()) {
111868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("jarray argument has non-array type: %s", PrettyTypeOf(a).c_str());
111968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
1120a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
112168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
1122a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1123a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
112468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckBoolean(jboolean z) {
112568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (z != JNI_TRUE && z != JNI_FALSE) {
112668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("unexpected jboolean value: %d", z);
112768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
112868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
112968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
113068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
113168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
113268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckLengthPositive(jsize length) {
113368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (length < 0) {
113468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("negative jsize: %d", length);
113568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
113668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
113768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
113868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
113968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
1140c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  ArtField* CheckFieldID(ScopedObjectAccess& soa, jfieldID fid)
114190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
114268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (fid == nullptr) {
114368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("jfieldID was NULL");
114468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return nullptr;
114568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
1146c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    ArtField* f = soa.DecodeField(fid);
1147c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    // TODO: Better check here.
1148c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass())) {
114968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
115068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("invalid jfieldID: %p", fid);
115168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return nullptr;
115268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
115368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return f;
115468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
115568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
1156e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  ArtMethod* CheckMethodID(ScopedObjectAccess& soa, jmethodID mid)
115790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
115868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (mid == nullptr) {
115968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("jmethodID was NULL");
116068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return nullptr;
116168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
1162e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    ArtMethod* m = soa.DecodeMethod(mid);
1163e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    // TODO: Better check here.
1164e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass())) {
116568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
116668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("invalid jmethodID: %p", mid);
116768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return nullptr;
1168a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
116968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return m;
1170a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1171a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
117290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  bool CheckThread(JNIEnv* env) SHARED_REQUIRES(Locks::mutator_lock_) {
1173a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    Thread* self = Thread::Current();
1174ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (self == nullptr) {
117568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
117668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
1177a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1178a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1179a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    // Get the *correct* JNIEnv by going through our TLS pointer.
1180a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    JNIEnvExt* threadEnv = self->GetJniEnv();
1181a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
11823f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Verify that the current thread is (a) attached and (b) associated with
11833f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // this particular instance of JNIEnv.
118468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (env != threadEnv) {
118568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("thread %s using JNIEnv* from thread %s",
118668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             ToStr<Thread>(*self).c_str(), ToStr<Thread>(*self).c_str());
118768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
1188a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1189a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
11903f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Verify that, if this thread previously made a critical "get" call, we
11913f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // do the corresponding "release" call before we try anything else.
119268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    switch (flags_ & kFlag_CritMask) {
1193a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    case kFlag_CritOkay:    // okay to call this method
1194a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      break;
1195a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    case kFlag_CritBad:     // not okay to call
1196a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      if (threadEnv->critical) {
119768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("thread %s using JNI after critical get",
119868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               ToStr<Thread>(*self).c_str());
119968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
1200a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1201a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      break;
1202a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    case kFlag_CritGet:     // this is a "get" call
12033f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes      // Don't check here; we allow nested gets.
1204a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      threadEnv->critical++;
1205a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      break;
12067934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    case kFlag_CritRelease:  // this is a "release" call
1207a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      threadEnv->critical--;
1208a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      if (threadEnv->critical < 0) {
120968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("thread %s called too many critical releases",
121068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               ToStr<Thread>(*self).c_str());
121168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
1212a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1213a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      break;
1214a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    default:
121568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      LOG(FATAL) << "Bad flags (internal error): " << flags_;
1216a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1217a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
12183f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Verify that, if an exception has been raised, the native code doesn't
12193f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // make any JNI calls other than the Exception* methods.
122068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
122114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      mirror::Throwable* exception = self->GetException();
122214691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray      AbortF("JNI %s called with pending exception %s",
122314691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray             function_name_,
122414691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray             exception->Dump().c_str());
122568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
1226a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
122768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
1228a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1229a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
12303f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes  // Verifies that "bytes" points to valid Modified UTF-8 data.
123168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckUtfString(const char* bytes, bool nullable) {
1232ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (bytes == nullptr) {
1233a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      if (!nullable) {
123468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF("non-nullable const char* was NULL");
123568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
1236a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
123768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return true;
1238a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1239a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1240ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const char* errorKind = nullptr;
1241ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe    const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind);
1242ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (errorKind != nullptr) {
1243ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe      // This is an expensive loop that will resize often, but this isn't supposed to hit in
1244ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe      // practice anyways.
1245ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe      std::ostringstream oss;
1246ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe      oss << std::hex;
1247ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe      const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes);
1248ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe      while (*tmp != 0) {
1249ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe        if (tmp == utf8) {
1250ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe          oss << "<";
1251ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe        }
1252ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe        oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp);
1253ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe        if (tmp == utf8) {
1254ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe          oss << '>';
1255ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe        }
1256ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe        tmp++;
1257ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe        if (*tmp != 0) {
1258ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe          oss << ' ';
1259ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe        }
1260ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe      }
1261ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe
126268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
1263ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe          "    string: '%s'\n    input: '%s'", errorKind, *utf8, bytes, oss.str().c_str());
126468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
1265a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
126668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
1267a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1268a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1269a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath  // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1270a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath  // sequences in place of encoded surrogate pairs.
1271ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe  static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) {
1272a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    while (*bytes != '\0') {
1273ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe      const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1274a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      // Switch on the high four bits.
1275ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe      switch (*utf8 >> 4) {
1276a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x00:
1277a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x01:
1278a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x02:
1279a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x03:
1280a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x04:
1281a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x05:
1282a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x06:
1283a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x07:
1284a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        // Bit pattern 0xxx. No need for any extra bytes.
1285a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        break;
1286a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x08:
1287a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x09:
1288a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0a:
1289a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0b:
1290a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath         // Bit patterns 10xx, which are illegal start bytes.
1291a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        *errorKind = "start";
1292a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        return utf8;
1293a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath      case 0x0f:
1294a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath        // Bit pattern 1111, which might be the start of a 4 byte sequence.
1295ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe        if ((*utf8 & 0x08) == 0) {
1296a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath          // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1297a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath          // We consume one continuation byte here, and fall through to consume two more.
1298ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe          utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1299ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe          if ((*utf8 & 0xc0) != 0x80) {
1300a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath            *errorKind = "continuation";
1301a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath            return utf8;
1302a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath          }
1303a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath        } else {
1304a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath          *errorKind = "start";
1305a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath          return utf8;
1306a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath        }
1307a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath
1308a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath        // Fall through to the cases below to consume two more continuation bytes.
1309a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath        FALLTHROUGH_INTENDED;
1310a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0e:
1311a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        // Bit pattern 1110, so there are two additional bytes.
1312ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe        utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1313ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe        if ((*utf8 & 0xc0) != 0x80) {
1314a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          *errorKind = "continuation";
1315a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          return utf8;
1316a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
1317a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath
1318a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath        // Fall through to consume one more continuation byte.
1319a5afcfc73141e5e378d79a326d02c5c2039fb025Narayan Kamath        FALLTHROUGH_INTENDED;
1320a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0c:
1321a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      case 0x0d:
1322a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        // Bit pattern 110x, so there is one additional byte.
1323ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe        utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1324ef4afe9dc2e13500c3057aaf7f697e654b0b2782Andreas Gampe        if ((*utf8 & 0xc0) != 0x80) {
1325a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          *errorKind = "continuation";
1326a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes          return utf8;
1327a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        }
1328a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes        break;
1329a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1330a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1331a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    return 0;
1332a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1333a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
133468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
133568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list args;
133668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(args, fmt);
133768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
133868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(args);
133968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
134068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
134168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // The name of the JNI function being checked.
134268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const char* const function_name_;
134368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
134468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const int flags_;
134592cb498ffd2185fc8f8da7cd25fe485d0e7e3355Elliott Hughes  int indent_;
1346a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
134768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const bool has_method_;
134868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
1349a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1350a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
1351a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1352a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/*
1353a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
1354a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *      Guarded arrays
1355a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
1356a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */
1357a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1358a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/* this gets tucked in at the start of the buffer; struct size must be even */
135968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogersclass GuardedCopy {
136068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers public:
1361a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
1362a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Create an over-sized buffer to hold the contents of "buf".  Copy it in,
1363a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * filling in the area around it with guard data.
1364a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
1365b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier  static void* Create(void* original_buf, size_t len, bool mod_okay) {
136668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const size_t new_len = LengthIncludingRedZones(len);
136768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    uint8_t* const new_buf = DebugAlloc(new_len);
1368a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
136968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // If modification is not expected, grab a checksum.
137068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    uLong adler = 0;
137168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!mod_okay) {
137268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
137368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
137468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
137568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
137668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
137768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Fill begin region with canary pattern.
137868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
137968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
138068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
138168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (kCanary[j] == '\0') {
138268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        j = 0;
1383068361a555f7d8cfd5602abb1faf087aa88bfa49tony.ys_liu      } else {
1384068361a555f7d8cfd5602abb1faf087aa88bfa49tony.ys_liu        j++;
138568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
1386a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1387a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
13883f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Copy the data in; note "len" could be zero.
138968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1390a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
139168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Fill end region with canary pattern.
139268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
139368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
139468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (kCanary[j] == '\0') {
139568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        j = 0;
1396068361a555f7d8cfd5602abb1faf087aa88bfa49tony.ys_liu      } else {
1397068361a555f7d8cfd5602abb1faf087aa88bfa49tony.ys_liu        j++;
139868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
139968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
140068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
140168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return const_cast<uint8_t*>(copy->BufferWithinRedZones());
140268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
140368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
140468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  /*
140568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * Create a guarded copy of a primitive array.  Modifications to the copied
140668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * data are allowed.  Returns a pointer to the copied data.
140768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   */
1408b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier  static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
1409b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier                                   void* original_ptr) {
141068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
141168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
141268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
141368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    size_t component_size = a->GetClass()->GetComponentSize();
141468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    size_t byte_count = a->GetLength() * component_size;
1415b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier    void* result = Create(original_ptr, byte_count, true);
141668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (is_copy != nullptr) {
141768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      *is_copy = JNI_TRUE;
1418a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
141968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result;
142068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
1421a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
142268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  /*
142368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * Perform the array "release" operation, which may or may not copy data
142468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   * back into the managed heap, and may or may not release the underlying storage.
142568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers   */
1426b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier  static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
1427b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier                                    jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
1428b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier                                    int mode) {
142968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
143068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
143168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return nullptr;
143268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
1433b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier    GuardedCopy* const copy = FromEmbedded(embedded_buf);
1434b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier    void* original_ptr = copy->original_ptr_;
143568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (mode != JNI_ABORT) {
1436b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier      memcpy(original_ptr, embedded_buf, copy->original_length_);
143768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
143868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (mode != JNI_COMMIT) {
1439b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier      Destroy(embedded_buf);
144068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
1441b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier    return original_ptr;
1442a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1443a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
144468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
1445a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
1446a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Free up the guard buffer, scrub it, and return the original pointer.
1447a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
144868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void* Destroy(void* embedded_buf) {
144968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    GuardedCopy* copy = FromEmbedded(embedded_buf);
145068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    void* original_ptr = const_cast<void*>(copy->original_ptr_);
145168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    size_t len = LengthIncludingRedZones(copy->original_length_);
145268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    DebugFree(copy, len);
145332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes    return original_ptr;
1454a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1455a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1456a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  /*
1457a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * Verify the guard area and, if "modOkay" is false, that the data itself
1458a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   * has not been altered.
1459a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   *
14602cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier   * The caller has already checked that "dataBuf" is non-null.
1461a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes   */
146268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
146368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const GuardedCopy* copy = FromEmbedded(embedded_buf);
146468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
146568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
146668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
146768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers private:
1468b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier  GuardedCopy(void* original_buf, size_t len, uLong adler) :
146968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
147068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
147168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
147268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static uint8_t* DebugAlloc(size_t len) {
147368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
147468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (result == MAP_FAILED) {
147568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
147668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
147768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<uint8_t*>(result);
147868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
147968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
148068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void DebugFree(void* buf, size_t len) {
148168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (munmap(buf, len) != 0) {
148268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
148368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
148468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
148568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
148668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static size_t LengthIncludingRedZones(size_t len) {
148768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return len + kRedZoneSize;
148868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
148968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
149068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Get the GuardedCopy from the interior pointer.
149168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static GuardedCopy* FromEmbedded(void* embedded_buf) {
149268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<GuardedCopy*>(
149368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
149468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
149568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
149668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
149768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<const GuardedCopy*>(
149868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
149968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
150068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
150168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void AbortF(const char* jni_function_name, const char* fmt, ...) {
150268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list args;
150368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(args, fmt);
150468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
150568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(args);
150668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
150768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
150868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckHeader(const char* function_name, bool mod_okay) const {
1509a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    static const uint32_t kMagicCmp = kGuardMagic;
1510a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
15113f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // Before we do anything with "pExtra", check the magic number.  We
15123f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // do the check with memcmp rather than "==" in case the pointer is
15133f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // unaligned.  If it points to completely bogus memory we're going
15143f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // to crash, but there's no easy way around that.
151568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1516a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      uint8_t buf[4];
151768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      memcpy(buf, &magic_, 4);
151868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      AbortF(function_name,
151968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
152068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers             buf[3], buf[2], buf[1], buf[0], this);  // Assumes little-endian.
152168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return false;
1522a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1523a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
152468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
152568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // told the client that we made a copy, there's no reason they can't alter the buffer.
152668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (!mod_okay) {
152768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      uLong computed_adler =
152868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
152968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (computed_adler != adler_) {
153068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
153168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               computed_adler, adler_, this);
153268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
1533a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1534a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
153568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
153668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
1537a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
153868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  bool CheckRedZones(const char* function_name) const {
153968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Check the begin red zone.
154068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
154168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
154268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
154368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
154468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
1545a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
154668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (kCanary[j] == '\0') {
154768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        j = 0;
1548068361a555f7d8cfd5602abb1faf087aa88bfa49tony.ys_liu      } else {
1549068361a555f7d8cfd5602abb1faf087aa88bfa49tony.ys_liu        j++;
1550a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1551a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
1552a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
155368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Check end region.
155468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
155568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
155668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        size_t offset_from_buffer_start =
155768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
155868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
155968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers               offset_from_buffer_start);
156068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return false;
156168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
156268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (kCanary[j] == '\0') {
156368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        j = 0;
1564068361a555f7d8cfd5602abb1faf087aa88bfa49tony.ys_liu      } else {
1565068361a555f7d8cfd5602abb1faf087aa88bfa49tony.ys_liu        j++;
1566a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
1567a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
156868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return true;
1569a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1570a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
157168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Location that canary value will be written before the guarded region.
157268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const char* StartRedZone() const {
157368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
157468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1575a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1576a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
157768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Return the interior embedded buffer.
157868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const uint8_t* BufferWithinRedZones() const {
157968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
158068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return embedded_buf;
1581a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1582a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
158368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Location that canary value will be written after the guarded region.
158468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const char* EndRedZone() const {
158568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
158668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    size_t buf_len = LengthIncludingRedZones(original_length_);
158768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1588a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1589a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
159068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static constexpr size_t kRedZoneSize = 512;
159168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1592a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
159368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  // Value written before and after the guarded array.
159468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const char* const kCanary;
1595a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
159668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1597a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
159868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const uint32_t magic_;
159968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const uLong adler_;
1600b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier  void* const original_ptr_;
160168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  const size_t original_length_;
160268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers};
160368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogersconst char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
1604a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1605a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/*
1606a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
1607a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *      JNI functions
1608a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * ===========================================================================
1609a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */
1610a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1611a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesclass CheckJNI {
1612a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes public:
1613a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint GetVersion(JNIEnv* env) {
161468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
161568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
161668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.E = env }};
161768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "E", args)) {
161868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
161968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.I = baseEnv(env)->GetVersion(env);
162068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "I", &result)) {
162168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.I;
162268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
162368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
162468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
162568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
162668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
162768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
162868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
162968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
163068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env }, {.p = vm}};
163168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ep", args)) {
163268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
163368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->GetJavaVM(env, vm);
163468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
163568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
163668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
163768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
163868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
163968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
164068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
164168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
164268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
164368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
164468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
164568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EcpI", args)) {
164668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
164768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
164868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
164968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
165068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
165168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
165268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
165368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
165468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
165568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jint UnregisterNatives(JNIEnv* env, jclass c) {
165668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
165768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
165868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env }, {.c = c}};
165968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ec", args)) {
166068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
166168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->UnregisterNatives(env, c);
166268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
166368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
166468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
166568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
166668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
166768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
166868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
166968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
1670c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1671c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    // know the object is invalid. The spec says that passing invalid objects or even ones that
1672c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    // are deleted isn't supported.
167368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
167468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
1675c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    JniValueType args[2] = {{.E = env }, {.L = obj}};
1676c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    if (sc.Check(soa, true, "EL", args)) {
167768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
167868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.w = baseEnv(env)->GetObjectRefType(env, obj);
167968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "w", &result)) {
168068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.w;
168168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
168268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
168368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNIInvalidRefType;
1684a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1685a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
168668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
168768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                            jsize bufLen) {
168868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
168968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
169068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
169168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
169268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
169368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
169468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "c", &result)) {
169568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.c;
169668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
169768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
169868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1699a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1700a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1701a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jclass FindClass(JNIEnv* env, const char* name) {
170268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
170368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
170468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.u = name}};
170568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
170668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
170768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.c = baseEnv(env)->FindClass(env, name);
170868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "c", &result)) {
170968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.c;
171068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
171168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
171268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1713a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1714a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1715e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jclass GetSuperclass(JNIEnv* env, jclass c) {
171668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
171768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
171868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.c = c}};
171968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ec", args)) {
172068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
172168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.c = baseEnv(env)->GetSuperclass(env, c);
172268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "c", &result)) {
172368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.c;
172468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
172568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
172668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1727a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1728a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1729e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
173068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
173168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
173268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
173368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecc", args)) {
173468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
173568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
173668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "b", &result)) {
173768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.b;
173868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
173968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
174068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_FALSE;
1741a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1742a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1743a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
174468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
174568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
174668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = method}};
174768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
174868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
174968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.m = baseEnv(env)->FromReflectedMethod(env, method);
175068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "m", &result)) {
175168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.m;
175268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
175368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
175468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1755a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1756a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1757a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
175868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
175968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
176068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = field}};
176168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
176268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
176368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.f = baseEnv(env)->FromReflectedField(env, field);
176468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "f", &result)) {
176568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.f;
176668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
176768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
176868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1769a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1770a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1771a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
177268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
177368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
177468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
177568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecmb", args)) {
177668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
177768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
177868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
177968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        DCHECK(sc.CheckReflectedMethod(soa, result.L));
178068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
178168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
178268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
178368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1784a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1785a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1786a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
178768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
178868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
178968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
179068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecfb", args)) {
179168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
179268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
179368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
179468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        DCHECK(sc.CheckReflectedField(soa, result.L));
179568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
179668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
179768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
179868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1799a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1800a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1801a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint Throw(JNIEnv* env, jthrowable obj) {
180268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
180368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
180468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.t = obj}};
180568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
180668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
180768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->Throw(env, obj);
180868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
180968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
181068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
181168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
181268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
1813a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1814a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1815e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
181668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
181768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
1818c50358b8947ae4367132dae5987d2e9738e90464Christopher Ferris    JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
181968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
182068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
182168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->ThrowNew(env, c, message);
182268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
182368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
182468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
182568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
182668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
1827a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1828a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1829a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jthrowable ExceptionOccurred(JNIEnv* env) {
183068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
183168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
183268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.E = env}};
183368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "E", args)) {
183468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
183568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.t = baseEnv(env)->ExceptionOccurred(env);
183668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "t", &result)) {
183768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.t;
183868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
183968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
184068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1841a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1842a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1843a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void ExceptionDescribe(JNIEnv* env) {
184468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
184568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
184668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.E = env}};
184768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "E", args)) {
184868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
184968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->ExceptionDescribe(env);
185068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
185168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
185268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
1853a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1854a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1855a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void ExceptionClear(JNIEnv* env) {
185668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
185768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
185868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.E = env}};
185968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "E", args)) {
186068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
186168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->ExceptionClear(env);
186268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
186368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
186468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
186568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
186668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
186768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jboolean ExceptionCheck(JNIEnv* env) {
186868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
186968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
187068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.E = env}};
187168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "E", args)) {
187268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
187368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.b = baseEnv(env)->ExceptionCheck(env);
187468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "b", &result)) {
187568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.b;
187668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
187768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
187868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_FALSE;
1879a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1880a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1881a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void FatalError(JNIEnv* env, const char* msg) {
1882c4378df76edd637273813fef4da7f01c4e637defElliott Hughes    // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1883c4378df76edd637273813fef4da7f01c4e637defElliott Hughes    // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1884c4378df76edd637273813fef4da7f01c4e637defElliott Hughes    // and it's not unimaginable that you don't know that you do. So we allow it.
188568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
188668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
188768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.u = msg}};
188868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eu", args)) {
188968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
189068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->FatalError(env, msg);
189168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // Unreachable.
189268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
189368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
189468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
1895a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1896a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1897a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint PushLocalFrame(JNIEnv* env, jint capacity) {
189868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
189968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
190068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.I = capacity}};
190168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EI", args)) {
190268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
190368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->PushLocalFrame(env, capacity);
190468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
190568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
190668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
190768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
190868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
1909a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1910a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1911a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject PopLocalFrame(JNIEnv* env, jobject res) {
191268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
191368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
191468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = res}};
191568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
191668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
191768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->PopLocalFrame(env, res);
191868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "L", &result);
191968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      return result.L;
192068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
192168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
1922a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1923a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1924a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
192568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return NewRef(__FUNCTION__, env, obj, kGlobal);
1926a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1927a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
192868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobject NewLocalRef(JNIEnv* env, jobject obj) {
192968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return NewRef(__FUNCTION__, env, obj, kLocal);
1930a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1931a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
193268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
193368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
1934a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1935a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
193668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
193768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    DeleteRef(__FUNCTION__, env, obj, kGlobal);
1938a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1939a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
194068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
194168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
194268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
194368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
194468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void DeleteLocalRef(JNIEnv* env, jobject obj) {
194568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    DeleteRef(__FUNCTION__, env, obj, kLocal);
1946a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1947a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1948a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
194968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
195068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
195168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.I = capacity}};
195268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EI", args)) {
195368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
195468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
195568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
195668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
195768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
195868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
195968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
1960a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1961a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1962a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
196368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
196468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
196568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
196668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "ELL", args)) {
196768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
196868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
196968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "b", &result)) {
197068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.b;
197168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
197268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
197368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_FALSE;
1974a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
1975a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
1976e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jobject AllocObject(JNIEnv* env, jclass c) {
197768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
197868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
197968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.c = c}};
198068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
198168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
198268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->AllocObject(env, c);
198368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result)) {
198468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
198568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
198668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
198768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
198868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
198968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
199068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
199168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
199268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
199348ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    VarArgs rest(mid, vargs);
199448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
199548ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
199668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.CheckConstructor(soa, mid)) {
199768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
199868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
199968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result)) {
200068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
200168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
200268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
200368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2004a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2005a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2006e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
2007a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    va_list args;
2008a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    va_start(args, mid);
200968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    jobject result = NewObjectV(env, c, mid, args);
2010a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    va_end(args);
201168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result;
2012a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2013a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
201468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
201568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
201668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
201748ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    VarArgs rest(mid, vargs);
201848ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
201948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
202068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.CheckConstructor(soa, mid)) {
202168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
202268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
202368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result)) {
202468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
202568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
202668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
202768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2028a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2029a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2030a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jclass GetObjectClass(JNIEnv* env, jobject obj) {
203168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
203268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
203368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = obj}};
203468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
203568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
203668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.c = baseEnv(env)->GetObjectClass(env, obj);
203768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "c", &result)) {
203868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.c;
203968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
204068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
204168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2042a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2043a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2044e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
204568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
204668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
204768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
204868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "ELc", args)) {
204968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
205068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
205168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "b", &result)) {
205268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.b;
205368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
205468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
205568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_FALSE;
2056a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2057a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2058e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
205968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
2060a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2061a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
206268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
206368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
2064a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2065a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
206668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
206768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
2068a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2069a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2070e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes  static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
207168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
207268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
207368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
207468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
207568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
207668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
207768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
207868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
207968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
208068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
208168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
208268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
208368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
208468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType value; \
208568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    value.shorty = v; \
208668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
208768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
208868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
208968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
209068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType value; \
209168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    value.shorty = v; \
209268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
209368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
209468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
209568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
209668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
209768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
209868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
209968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
210068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
210168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
210268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
210368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
210468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#undef FIELD_ACCESSORS
210568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
210668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
210768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
210868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
210968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
211068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
211168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                        jvalue* vargs) {
211268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
211368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
211468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
211568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
211651be0a7158b62d6da6a3ccb6fce9f7f677ec3ce3Marcus Oakland    CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
211768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
211868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
211968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
212068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
212168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
212268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
212368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
212468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                        va_list vargs) {
212568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
212668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
212768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
212868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
212968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
213068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
213168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
213268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
213368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list vargs;
213468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(vargs, mid);
213568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
213668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(vargs);
213768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
213868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
213968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
214068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list vargs;
214168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(vargs, mid);
214268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
214368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(vargs);
214468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
214568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
214668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
214768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list vargs;
214868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(vargs, mid);
214968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
215068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(vargs);
215168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
215268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
215368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#define CALL(rtype, name, ptype, shorty) \
215468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
215568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
215668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
215768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
215868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
215968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                             jvalue* vargs) { \
216068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
216168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
216268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
216368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
216468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
216568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
216668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
216768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
216868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
216968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
217068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
217168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
217268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                             va_list vargs) { \
217368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
217468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
217568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
217668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
217768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
217868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
217968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
218068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
218168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list vargs; \
218268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(vargs, mid); \
218368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    rtype result = \
218468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
218568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(vargs); \
218668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result; \
218768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
218868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
218968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
219068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                            ...) { \
219168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list vargs; \
219268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(vargs, mid); \
219368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    rtype result = \
219468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
219568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(vargs); \
219668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result; \
219768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
219868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
219968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
220068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_list vargs; \
220168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_start(vargs, mid); \
220268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    rtype result = \
220368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
220468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    va_end(vargs); \
220568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result; \
220668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
220768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
220868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jobject, Object, Primitive::kPrimNot, L)
220968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
221068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jbyte, Byte, Primitive::kPrimByte, B)
221168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jchar, Char, Primitive::kPrimChar, C)
221268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jshort, Short, Primitive::kPrimShort, S)
221368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jint, Int, Primitive::kPrimInt, I)
221468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jlong, Long, Primitive::kPrimLong, J)
221568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jfloat, Float, Primitive::kPrimFloat, F)
221668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  CALL(jdouble, Double, Primitive::kPrimDouble, D)
221768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#undef CALL
221868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
221968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
222068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
222168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
222268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
222368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Epz", args)) {
222468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
222568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.s = baseEnv(env)->NewString(env, unicode_chars, len);
222668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "s", &result)) {
222768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.s;
222868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
222968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
223068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2231a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2232a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
223368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jstring NewStringUTF(JNIEnv* env, const char* chars) {
223468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
223568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
223668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.u = chars}};
223768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eu", args)) {
223868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
223968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // TODO: stale? show pointer and truncate string.
224068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.s = baseEnv(env)->NewStringUTF(env, chars);
224168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "s", &result)) {
224268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.s;
224368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
224468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
224568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2246a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2247a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
224868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jsize GetStringLength(JNIEnv* env, jstring string) {
224968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
225068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
225168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.s = string}};
225268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Es", args)) {
225368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
225468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.z = baseEnv(env)->GetStringLength(env, string);
225568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "z", &result)) {
225668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.z;
2257a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
2258a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
225968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
2260a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2261a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
226268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
226368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
226468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
226568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.s = string}};
226668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Es", args)) {
226768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
226868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.z = baseEnv(env)->GetStringUTFLength(env, string);
226968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "z", &result)) {
227068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.z;
227168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2272a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
227368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
2274a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2275a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
227668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
227768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
227868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                                 is_copy, false, false));
2279a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2280a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
228168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
228268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
228368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                                is_copy, true, false));
2284a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2285a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
228668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
228768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
228868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                                 is_copy, false, true));
228968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
229068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
229168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
229268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2293a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2294a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2295a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
229668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
229768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
229868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
229968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
230068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
230168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
230268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
230368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
230468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
230568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
230668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
230768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
230868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
230968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EsIIp", args)) {
231068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->GetStringRegion(env, string, start, len, buf);
231168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
231268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
231368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
2314a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
2315a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2316a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
231768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
231868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
231968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
232068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
232168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
232268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
232368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EsIIp", args)) {
232468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
232568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
232668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
232768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
232868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
2329a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2330a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
233168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jsize GetArrayLength(JNIEnv* env, jarray array) {
233268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
233368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
233468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.a = array}};
233568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ea", args)) {
233668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
233768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.z = baseEnv(env)->GetArrayLength(env, array);
233868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "z", &result)) {
233968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.z;
234068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
234168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
234268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
234368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
234468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
234568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
234668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                     jobject initial_element) {
234768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
234868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
234968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] =
235068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
235168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EzcL", args)) {
235268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
235368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // Note: assignability tests of initial_element are done in the base implementation.
235468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
235568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "a", &result)) {
235668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return down_cast<jobjectArray>(result.a);
235768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
235868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
235968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2360a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2361a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2362a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
236368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
236468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
236568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
236668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eaz", args)) {
236768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
236868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
236968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result)) {
237068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
237168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
237268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
237368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2374a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2375a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2376a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
237768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
237868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
237968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
238068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
238168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
238268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // in ArrayStoreExceptions.
238368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EaIL", args)) {
238468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->SetObjectArrayElement(env, array, index, value);
238568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
238668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
238768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
2388a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
2389a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2390a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
239168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
239268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
239368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                      Primitive::kPrimBoolean));
2394a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2395a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
239668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
239768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
239868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                   Primitive::kPrimByte));
239968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
2400a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
240168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jcharArray NewCharArray(JNIEnv* env, jsize length) {
240268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
240368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                   Primitive::kPrimChar));
240468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
2405a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
240668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jshortArray NewShortArray(JNIEnv* env, jsize length) {
240768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
240868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                    Primitive::kPrimShort));
2409a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2410a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
241168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jintArray NewIntArray(JNIEnv* env, jsize length) {
241268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2413a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2414a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
241568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jlongArray NewLongArray(JNIEnv* env, jsize length) {
241668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
241768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                   Primitive::kPrimLong));
241868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
241968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
242068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
242168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
242268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                    Primitive::kPrimFloat));
242368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
242468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
242568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
242668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
242768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                     Primitive::kPrimDouble));
242868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
242968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
243068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
243168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { \
243268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<ctype*>( \
243368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
243468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
243568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
243668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, \
243768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                           jint mode) { \
243868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
243968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
244068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
244168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
244268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                     ctype* buf) { \
244368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
244468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  } \
244568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  \
244668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
244768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                     const ctype* buf) { \
244868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
244968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
245068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
245168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
245268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
245368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
245468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
245568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
245668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
245768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
245868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
245968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#undef PRIMITIVE_ARRAY_FUNCTIONS
246068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
2461a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint MonitorEnter(JNIEnv* env, jobject obj) {
246268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
246368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
246468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = obj}};
246568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
24665f4a09a54eed55de89e194780214a2acfd2cb431Andreas Gampe      if (obj != nullptr) {
24675f4a09a54eed55de89e194780214a2acfd2cb431Andreas Gampe        down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj);
24685f4a09a54eed55de89e194780214a2acfd2cb431Andreas Gampe      }
246968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
247068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->MonitorEnter(env, obj);
247168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
247268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
247368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2474a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
247568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
2476a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2477a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
2478a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint MonitorExit(JNIEnv* env, jobject obj) {
247968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
248068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
248168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = obj}};
248268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
24835f4a09a54eed55de89e194780214a2acfd2cb431Andreas Gampe      if (obj != nullptr) {
24845f4a09a54eed55de89e194780214a2acfd2cb431Andreas Gampe        down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj);
24855f4a09a54eed55de89e194780214a2acfd2cb431Andreas Gampe      }
248668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
248768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.i = baseEnv(env)->MonitorExit(env, obj);
248868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "i", &result)) {
248968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.i;
249068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2491a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes    }
249268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
2493a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2494a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
249568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
249668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
249768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
249868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
249968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eap", args)) {
250068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
2501b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier      void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2502b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier      if (ptr != nullptr && soa.ForceCopy()) {
2503b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier        ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
250468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2505b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier      result.p = ptr;
250668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "p", &result)) {
250768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return const_cast<void*>(result.p);
250868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
250968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
251068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2511a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2512a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
251368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
251468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
251568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
251668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonNull(carray);
251768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
251868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eapr", args)) {
251968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (soa.ForceCopy()) {
2520b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier        carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
252168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
252268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
252368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
252468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
252568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
252668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
2527a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2528a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
252968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
253068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
253168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
253268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
253368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EpJ", args)) {
253468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
253568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // Note: the validity of address and capacity are checked in the base implementation.
253668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
253768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result)) {
253868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
253968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
254068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
254168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2542a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2543a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
254468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
254568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
254668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
254768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = buf}};
254868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
254968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
255068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // Note: this is implemented in the base environment by a GetLongField which will sanity
255168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // check the type of buf in GetLongField above.
255268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
255368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "p", &result)) {
255468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return const_cast<void*>(result.p);
255568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2556a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
255768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2558a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2559a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
256068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
256168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
256268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, __FUNCTION__);
256368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = buf}};
256468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
256568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
256668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // Note: this is implemented in the base environment by a GetIntField which will sanity
256768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // check the type of buf in GetIntField above.
256868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
256968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "J", &result)) {
257068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.J;
257168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2572a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
257368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return JNI_ERR;
257468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
257568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
257668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers private:
257768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
257868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<JNIEnvExt*>(env)->vm;
2579a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2580a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
258168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const JNINativeInterface* baseEnv(JNIEnv* env) {
258268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
258368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
258468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
258568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
258668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
258768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
258868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = obj}};
258968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EL", args)) {
259068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
259168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (kind) {
259268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case kGlobal:
259368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.L = baseEnv(env)->NewGlobalRef(env, obj);
259468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
259568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case kLocal:
259668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.L = baseEnv(env)->NewLocalRef(env, obj);
259768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
259868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case kWeakGlobal:
259968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
260068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
260168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
260268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected reference kind: " << kind;
260368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
260468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "L", &result)) {
260568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
26066a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers        DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
260768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.L;
2608a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes      }
2609a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
261068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
261168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
261268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
261368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
261468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
261568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, function_name);
261668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.L = obj}};
261768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.Check(soa, true, "EL", args);
26186a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
261968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
262068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (kind) {
262168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case kGlobal:
262268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->DeleteGlobalRef(env, obj);
262368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
262468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case kLocal:
262568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->DeleteLocalRef(env, obj);
262668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
262768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case kWeakGlobal:
262868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->DeleteWeakGlobalRef(env, obj);
262968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
263068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
263168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected reference kind: " << kind;
263268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
263368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
263468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
263568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
2636a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2637a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
263868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
263968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                       const char* name, const char* sig, bool is_static) {
264068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
264168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
264268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
264368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecuu", args)) {
264468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
264568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (is_static) {
264668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
264768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      } else {
264868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
264968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
265068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "m", &result)) {
265168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.m;
265268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
2653a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
265468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
2655a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2656a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
265768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
265868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                     const char* name, const char* sig, bool is_static) {
265968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
266068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
266168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
266268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ecuu", args)) {
266368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
266468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (is_static) {
266568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
266668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      } else {
266768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
266868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
266968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "f", &result)) {
267068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.f;
267168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
267268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
267368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
267468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
267568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
267668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
267768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                               bool is_static, Primitive::Type type) {
267868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
267968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
268068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
268168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
268268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
268368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
268468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      const char* result_check = nullptr;
268568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
268668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimNot:
268768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
268868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
268968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
269068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.L = baseEnv(env)->GetObjectField(env, obj, fid);
269168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
269268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "L";
269368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
269468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
269568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
269668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
269768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
269868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
269968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
270068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "Z";
270168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
270268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
270368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
270468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
270568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
270668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.B = baseEnv(env)->GetByteField(env, obj, fid);
270768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
270868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "B";
270968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
271068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
271168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
271268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
271368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
271468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.C = baseEnv(env)->GetCharField(env, obj, fid);
271568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
271668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "C";
271768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
271868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
271968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
272068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
272168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
272268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.S = baseEnv(env)->GetShortField(env, obj, fid);
272368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
272468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "S";
272568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
272668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
272768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
272868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
272968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
273068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.I = baseEnv(env)->GetIntField(env, obj, fid);
273168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
273268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "I";
273368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
273468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
273568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
273668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
273768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
273868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.J = baseEnv(env)->GetLongField(env, obj, fid);
273968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
274068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "J";
274168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
274268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
274368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
274468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
274568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
274668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.F = baseEnv(env)->GetFloatField(env, obj, fid);
274768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
274868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "F";
274968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
275068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
275168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
275268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
275368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
275468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
275568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
275668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "D";
275768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
275868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimVoid:
275968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected type: " << type;
276068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
276168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
276268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, result_check, &result)) {
276368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result;
276468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
276568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
276668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.J = 0;
276768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result;
2768a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2769a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
277068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
277168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                       bool is_static, Primitive::Type type, JniValueType value) {
277268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
277368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
277468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
277568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
277668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
277768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, sig, args) &&
277868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
277968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
278068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimNot:
278168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
278268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
278368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
278468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetObjectField(env, obj, fid, value.L);
278568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
278668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
278768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
278868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
278968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
279068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
279168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
279268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
279368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
279468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
279568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
279668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
279768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
279868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetByteField(env, obj, fid, value.B);
279968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
280068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
280168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
280268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
280368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
280468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
280568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetCharField(env, obj, fid, value.C);
280668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
280768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
280868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
280968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
281068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
281168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
281268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetShortField(env, obj, fid, value.S);
281368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
281468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
281568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
281668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
281768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
281868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
281968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetIntField(env, obj, fid, value.I);
282068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
282168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
282268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
282368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
282468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
282568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
282668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetLongField(env, obj, fid, value.J);
282768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
282868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
282968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
283068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
283168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
283268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
283368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetFloatField(env, obj, fid, value.F);
283468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
283568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
283668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
283768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (is_static) {
283868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
283968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
284068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
284168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
284268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
284368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimVoid:
284468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected type: " << type;
284568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
284668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
284768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
284868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
284968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
285068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
2851a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
2852a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
285368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
285448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light                            jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs)
285590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
285668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    bool checked;
285768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    switch (invoke) {
285868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case kVirtual: {
285968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        DCHECK(c == nullptr);
286048ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}};
286148ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        checked = sc.Check(soa, true, "ELm.", args);
286268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
286368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
286468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case kDirect: {
286548ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}};
286648ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        checked = sc.Check(soa, true, "ELcm.", args);
286768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
286868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
286968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      case kStatic: {
287068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        DCHECK(obj == nullptr);
287148ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}};
287248ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light        checked = sc.Check(soa, true, "Ecm.", args);
287368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
287468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
287568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      default:
287668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        LOG(FATAL) << "Unexpected invoke: " << invoke;
287768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        checked = false;
287868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        break;
287968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
288068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return checked;
288168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
288268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
288368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
288468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                  jmethodID mid, jvalue* vargs, Primitive::Type type,
288568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                  InvokeType invoke) {
288668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
288768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
288868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
288948ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    VarArgs rest(mid, vargs);
289048ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
289168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
289268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      const char* result_check;
289368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
289468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimNot:
289568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "L";
289668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
289768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
289868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
289968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
290068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
290168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
290268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
290368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
290468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
290568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
290668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
290768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
290868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
290968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
291068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
291168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "Z";
291268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
291368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
291468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
291568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
291668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
291768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
291868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
291968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
292068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
292168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
292268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
292368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
292468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
292568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
292668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
292768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "B";
292868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
292968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
293068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
293168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
293268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
293368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
293468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
293568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
293668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
293768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
293868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
293968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
294068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
294168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
294268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
294368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "C";
294468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
294568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
294668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
294768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
294868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
294968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
295068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
295168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
295268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
295368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
295468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
295568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
295668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
295768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
295868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
295968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "S";
296068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
296168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
296268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
296368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
296468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
296568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
296668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
296768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
296868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
296968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
297068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
297168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
297268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
297368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
297468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
297568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "I";
297668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
297768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
297868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
297968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
298068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
298168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
298268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
298368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
298468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
298568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
298668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
298768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
298868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
298968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
299068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
299168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "J";
299268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
299368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
299468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
299568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
299668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
299768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
299868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
299968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
300068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
300168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
300268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
300368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
300468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
300568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
300668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
300768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "F";
300868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
300968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
301068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
301168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
301268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
301368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
301468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
301568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
301668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
301768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
301868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
301968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
302068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
302168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
302268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
302368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "D";
302468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
302568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
302668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
302768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
302868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
302968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
303068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
303168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
303268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
303368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
303468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
303568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
303668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
303768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
303868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimVoid:
303968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "V";
304068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.V = nullptr;
304168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
304268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
304368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
304468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
304568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
304668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
304768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
304868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
304968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
305068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
305168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
305268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
305368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
305468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
305568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
305668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected return type: " << type;
305768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = nullptr;
305868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
305968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, result_check, &result)) {
306068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result;
306168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
306268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
306368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.J = 0;
306468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result;
3065a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3066a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
306768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
306868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                  jmethodID mid, va_list vargs, Primitive::Type type,
306968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                  InvokeType invoke) {
307068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
307168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
307268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
307348ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    VarArgs rest(mid, vargs);
307448ffe0653c51c0785c8bd260fef486922ba00e4eAlex Light    if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
307568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
307668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      const char* result_check;
307768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
307868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimNot:
307968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "L";
308068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
308168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
308268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
308368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
308468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
308568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
308668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
308768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
308868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
308968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
309068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
309168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
309268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
309368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
309468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
309568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "Z";
309668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
309768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
309868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
309968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
310068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
310168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
310268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
310368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
310468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
310568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
310668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
310768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
310868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
310968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
311068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
311168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "B";
311268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
311368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
311468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
311568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
311668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
311768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
311868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
311968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
312068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
312168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
312268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
312368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
312468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
312568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
312668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
312768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "C";
312868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
312968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
313068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
313168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
313268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
313368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
313468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
313568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
313668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
313768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
313868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
313968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
314068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
314168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
314268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
314368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "S";
314468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
314568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
314668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
314768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
314868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
314968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
315068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
315168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
315268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
315368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
315468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
315568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
315668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
315768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
315868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
315968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "I";
316068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
316168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
316268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
316368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
316468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
316568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
316668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
316768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
316868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
316968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
317068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
317168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
317268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
317368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
317468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
317568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "J";
317668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
317768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
317868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
317968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
318068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
318168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
318268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
318368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
318468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
318568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
318668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
318768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
318868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
318968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
319068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
319168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "F";
319268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
319368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
319468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
319568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
319668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
319768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
319868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
319968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
320068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
320168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
320268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
320368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
320468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
320568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
320668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
320768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "D";
320868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
320968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
321068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
321168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
321268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
321368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
321468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
321568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
321668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
321768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
321868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
321968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
322068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
322168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
322268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimVoid:
322368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = "V";
322468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.V = nullptr;
322568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (invoke) {
322668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kVirtual:
322768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
322868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
322968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kDirect:
323068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
323168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
323268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case kStatic:
323368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
323468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
323568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
323668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected invoke: " << invoke;
323768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
323868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
323968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
324068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected return type: " << type;
324168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result_check = nullptr;
324268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
324368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, result_check, &result)) {
324468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result;
324568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
3246a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes    }
324768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.J = 0;
324868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result;
3249a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3250a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
325168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
325268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                            jboolean* is_copy, bool utf, bool critical) {
325368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
325468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
325568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(flags, function_name);
325668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
325768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Esp", args)) {
325868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
3259b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier      void* ptr;
326068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (utf) {
326168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        CHECK(!critical);
3262b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier        ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
3263b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier        result.u = reinterpret_cast<char*>(ptr);
326468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      } else {
3265b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier        ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
3266b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier            baseEnv(env)->GetStringChars(env, string, is_copy));
3267b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier        result.p = ptr;
326868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
326968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      // TODO: could we be smarter about not copying when local_is_copy?
3270b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier      if (ptr != nullptr && soa.ForceCopy()) {
327168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (utf) {
327268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          size_t length_in_bytes = strlen(result.u) + 1;
327368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.u =
3274b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier              reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
327568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
327668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
327768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.p =
3278b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier              reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
327968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
328068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (is_copy != nullptr) {
328168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *is_copy = JNI_TRUE;
328268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
328368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
328468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
328568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return utf ? result.u : result.p;
328668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
328768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
328868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
3289a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3290a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
329168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
329268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                         const void* chars, bool utf, bool critical) {
329368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
329468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    int flags = kFlag_ExcepOkay | kFlag_Release;
329568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (critical) {
329668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      flags |= kFlag_CritRelease;
329768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
329868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(flags, function_name);
329968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonNull(chars);
330068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
330168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (force_copy_ok && soa.ForceCopy()) {
330268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
330368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
330468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (force_copy_ok) {
330568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
330668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
330768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (utf) {
330868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          CHECK(!critical);
330968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
331068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        } else {
331168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          if (critical) {
331268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
331368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          } else {
331468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
331568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
331668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
331768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        JniValueType result;
331868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        sc.Check(soa, false, "V", &result);
331968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
332068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
3321a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3322a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
332368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
332468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                  Primitive::Type type) {
332568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
33266a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
332768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[2] = {{.E = env}, {.z = length}};
332868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Ez", args)) {
332968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
333068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
333168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
333268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewBooleanArray(env, length);
333368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
333468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
333568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewByteArray(env, length);
333668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
333768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
333868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewCharArray(env, length);
333968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
334068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
334168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewShortArray(env, length);
334268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
334368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
334468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewIntArray(env, length);
334568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
334668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
334768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewLongArray(env, length);
334868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
334968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
335068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewFloatArray(env, length);
335168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
335268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
335368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.a = baseEnv(env)->NewDoubleArray(env, length);
335468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
335568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
335668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected primitive type: " << type;
335768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
335868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "a", &result)) {
335968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return result.a;
336068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
336168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
336268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
336368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
336468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
336568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
336668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                         JNIEnv* env, jarray array, jboolean* is_copy) {
336768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
336868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
336968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
337068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
337168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
3372b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier      void* ptr = nullptr;
337368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
337468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
3375b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier          ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3376b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier                                                      is_copy);
337768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
337868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
3379b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier          ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
338068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
338168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
3382b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier          ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
338368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
338468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
3385b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier          ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
338668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
338768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
3388b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier          ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
338968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
339068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
3391b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier          ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
339268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
339368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
3394b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier          ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
339568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
339668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
3397b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier          ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
339868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
339968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
340068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected primitive type: " << type;
340168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
3402b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier      if (ptr != nullptr && soa.ForceCopy()) {
3403b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier        ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
340468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (is_copy != nullptr) {
340568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          *is_copy = JNI_TRUE;
340668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
340768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
3408b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596Mathieu Chartier      result.p = ptr;
340968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (sc.Check(soa, false, "p", &result)) {
341068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        return const_cast<void*>(result.p);
341168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
341268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
341368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return nullptr;
341468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
341568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
341668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
341768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                            JNIEnv* env, jarray array, void* elems, jint mode) {
341868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
341968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_ExcepOkay, function_name);
342068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
342168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (soa.ForceCopy()) {
342268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
342368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
342468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      if (!soa.ForceCopy() || elems != nullptr) {
342568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
342668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        if (sc.Check(soa, true, "Eapr", args)) {
342768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          switch (type) {
342868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimBoolean:
342968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
343068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                        reinterpret_cast<jboolean*>(elems), mode);
343168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
343268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimByte:
343368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
343468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                     reinterpret_cast<jbyte*>(elems), mode);
343568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
343668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimChar:
343768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
343868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                     reinterpret_cast<jchar*>(elems), mode);
343968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
344068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimShort:
344168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
344268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                      reinterpret_cast<jshort*>(elems), mode);
344368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
344468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimInt:
344568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
344668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                    reinterpret_cast<jint*>(elems), mode);
344768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
344868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimLong:
344968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
345068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                     reinterpret_cast<jlong*>(elems), mode);
345168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
345268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimFloat:
345368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
345468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                      reinterpret_cast<jfloat*>(elems), mode);
345568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
345668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            case Primitive::kPrimDouble:
345768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
345868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                                       reinterpret_cast<jdouble*>(elems), mode);
345968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              break;
346068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers            default:
346168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers              LOG(FATAL) << "Unexpected primitive type: " << type;
346268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          }
346368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          JniValueType result;
346468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          result.V = nullptr;
346568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          sc.Check(soa, false, "V", &result);
346668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        }
346768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
346868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
346968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
347068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
347168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
347268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                      jarray array, jsize start, jsize len, void* buf) {
347368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
347468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
347568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
347668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
347768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
347868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
347968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
348068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
348168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
348268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                              reinterpret_cast<jboolean*>(buf));
348368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
348468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
348568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
348668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                           reinterpret_cast<jbyte*>(buf));
348768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
348868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
348968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
349068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                           reinterpret_cast<jchar*>(buf));
349168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
349268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
349368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
349468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                            reinterpret_cast<jshort*>(buf));
349568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
349668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
349768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
349868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                          reinterpret_cast<jint*>(buf));
349968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
350068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
350168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
350268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                           reinterpret_cast<jlong*>(buf));
350368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
350468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
350568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
350668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                            reinterpret_cast<jfloat*>(buf));
350768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
350868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
350968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
351068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                             reinterpret_cast<jdouble*>(buf));
351168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
351268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
351368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected primitive type: " << type;
351468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
351568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
351668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
351768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
351868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
351968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  }
352068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers
352168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
352268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                      jarray array, jsize start, jsize len, const void* buf) {
352368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedObjectAccess soa(env);
352468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Default, function_name);
352568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
352668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
352768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
352868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
352968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      switch (type) {
353068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimBoolean:
353168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
353268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                              reinterpret_cast<const jboolean*>(buf));
353368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
353468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimByte:
353568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
353668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                           reinterpret_cast<const jbyte*>(buf));
353768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
353868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimChar:
353968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
354068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                           reinterpret_cast<const jchar*>(buf));
354168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
354268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimShort:
354368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
354468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                              reinterpret_cast<const jshort*>(buf));
354568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
354668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimInt:
354768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
354868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                          reinterpret_cast<const jint*>(buf));
354968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
355068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimLong:
355168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
355268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                              reinterpret_cast<const jlong*>(buf));
355368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
355468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimFloat:
355568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
355668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                            reinterpret_cast<const jfloat*>(buf));
355768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
355868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        case Primitive::kPrimDouble:
355968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
356068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers                                             reinterpret_cast<const jdouble*>(buf));
356168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          break;
356268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers        default:
356368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers          LOG(FATAL) << "Unexpected primitive type: " << type;
356468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      }
356568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      JniValueType result;
356668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      result.V = nullptr;
356768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers      sc.Check(soa, false, "V", &result);
356868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    }
3569a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3570a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
3571a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3572a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNINativeInterface gCheckNativeInterface = {
3573ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved0.
3574ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved1.
3575ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved2.
3576ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved3.
3577a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetVersion,
3578a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::DefineClass,
3579a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::FindClass,
3580a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::FromReflectedMethod,
3581a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::FromReflectedField,
3582a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ToReflectedMethod,
3583a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetSuperclass,
3584a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::IsAssignableFrom,
3585a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ToReflectedField,
3586a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::Throw,
3587a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ThrowNew,
3588a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ExceptionOccurred,
3589a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ExceptionDescribe,
3590a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ExceptionClear,
3591a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::FatalError,
3592a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::PushLocalFrame,
3593a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::PopLocalFrame,
3594a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewGlobalRef,
3595a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::DeleteGlobalRef,
3596a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::DeleteLocalRef,
3597a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::IsSameObject,
3598a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewLocalRef,
3599a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::EnsureLocalCapacity,
3600a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::AllocObject,
3601a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewObject,
3602a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewObjectV,
3603a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewObjectA,
3604a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetObjectClass,
3605a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::IsInstanceOf,
3606a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetMethodID,
3607a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallObjectMethod,
3608a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallObjectMethodV,
3609a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallObjectMethodA,
3610a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallBooleanMethod,
3611a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallBooleanMethodV,
3612a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallBooleanMethodA,
3613a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallByteMethod,
3614a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallByteMethodV,
3615a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallByteMethodA,
3616a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallCharMethod,
3617a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallCharMethodV,
3618a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallCharMethodA,
3619a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallShortMethod,
3620a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallShortMethodV,
3621a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallShortMethodA,
3622a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallIntMethod,
3623a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallIntMethodV,
3624a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallIntMethodA,
3625a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallLongMethod,
3626a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallLongMethodV,
3627a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallLongMethodA,
3628a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallFloatMethod,
3629a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallFloatMethodV,
3630a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallFloatMethodA,
3631a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallDoubleMethod,
3632a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallDoubleMethodV,
3633a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallDoubleMethodA,
3634a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallVoidMethod,
3635a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallVoidMethodV,
3636a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallVoidMethodA,
3637a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualObjectMethod,
3638a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualObjectMethodV,
3639a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualObjectMethodA,
3640a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualBooleanMethod,
3641a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualBooleanMethodV,
3642a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualBooleanMethodA,
3643a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualByteMethod,
3644a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualByteMethodV,
3645a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualByteMethodA,
3646a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualCharMethod,
3647a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualCharMethodV,
3648a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualCharMethodA,
3649a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualShortMethod,
3650a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualShortMethodV,
3651a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualShortMethodA,
3652a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualIntMethod,
3653a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualIntMethodV,
3654a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualIntMethodA,
3655a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualLongMethod,
3656a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualLongMethodV,
3657a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualLongMethodA,
3658a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualFloatMethod,
3659a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualFloatMethodV,
3660a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualFloatMethodA,
3661a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualDoubleMethod,
3662a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualDoubleMethodV,
3663a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualDoubleMethodA,
3664a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualVoidMethod,
3665a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualVoidMethodV,
3666a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallNonvirtualVoidMethodA,
3667a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetFieldID,
3668a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetObjectField,
3669a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetBooleanField,
3670a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetByteField,
3671a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetCharField,
3672a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetShortField,
3673a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetIntField,
3674a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetLongField,
3675a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetFloatField,
3676a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDoubleField,
3677a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetObjectField,
3678a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetBooleanField,
3679a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetByteField,
3680a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetCharField,
3681a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetShortField,
3682a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetIntField,
3683a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetLongField,
3684a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetFloatField,
3685a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetDoubleField,
3686a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticMethodID,
3687a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticObjectMethod,
3688a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticObjectMethodV,
3689a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticObjectMethodA,
3690a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticBooleanMethod,
3691a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticBooleanMethodV,
3692a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticBooleanMethodA,
3693a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticByteMethod,
3694a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticByteMethodV,
3695a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticByteMethodA,
3696a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticCharMethod,
3697a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticCharMethodV,
3698a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticCharMethodA,
3699a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticShortMethod,
3700a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticShortMethodV,
3701a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticShortMethodA,
3702a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticIntMethod,
3703a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticIntMethodV,
3704a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticIntMethodA,
3705a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticLongMethod,
3706a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticLongMethodV,
3707a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticLongMethodA,
3708a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticFloatMethod,
3709a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticFloatMethodV,
3710a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticFloatMethodA,
3711a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticDoubleMethod,
3712a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticDoubleMethodV,
3713a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticDoubleMethodA,
3714a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticVoidMethod,
3715a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticVoidMethodV,
3716a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::CallStaticVoidMethodA,
3717a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticFieldID,
3718a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticObjectField,
3719a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticBooleanField,
3720a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticByteField,
3721a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticCharField,
3722a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticShortField,
3723a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticIntField,
3724a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticLongField,
3725a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticFloatField,
3726a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStaticDoubleField,
3727a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticObjectField,
3728a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticBooleanField,
3729a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticByteField,
3730a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticCharField,
3731a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticShortField,
3732a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticIntField,
3733a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticLongField,
3734a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticFloatField,
3735a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetStaticDoubleField,
3736a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewString,
3737a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringLength,
3738a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringChars,
3739a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseStringChars,
3740a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewStringUTF,
3741a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringUTFLength,
3742a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringUTFChars,
3743a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseStringUTFChars,
3744a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetArrayLength,
3745a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewObjectArray,
3746a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetObjectArrayElement,
3747a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetObjectArrayElement,
3748a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewBooleanArray,
3749a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewByteArray,
3750a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewCharArray,
3751a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewShortArray,
3752a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewIntArray,
3753a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewLongArray,
3754a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewFloatArray,
3755a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewDoubleArray,
3756a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetBooleanArrayElements,
3757a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetByteArrayElements,
3758a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetCharArrayElements,
3759a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetShortArrayElements,
3760a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetIntArrayElements,
3761a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetLongArrayElements,
3762a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetFloatArrayElements,
3763a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDoubleArrayElements,
3764a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseBooleanArrayElements,
3765a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseByteArrayElements,
3766a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseCharArrayElements,
3767a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseShortArrayElements,
3768a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseIntArrayElements,
3769a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseLongArrayElements,
3770a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseFloatArrayElements,
3771a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseDoubleArrayElements,
3772a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetBooleanArrayRegion,
3773a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetByteArrayRegion,
3774a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetCharArrayRegion,
3775a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetShortArrayRegion,
3776a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetIntArrayRegion,
3777a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetLongArrayRegion,
3778a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetFloatArrayRegion,
3779a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDoubleArrayRegion,
3780a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetBooleanArrayRegion,
3781a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetByteArrayRegion,
3782a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetCharArrayRegion,
3783a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetShortArrayRegion,
3784a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetIntArrayRegion,
3785a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetLongArrayRegion,
3786a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetFloatArrayRegion,
3787a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::SetDoubleArrayRegion,
3788a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::RegisterNatives,
3789a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::UnregisterNatives,
3790a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::MonitorEnter,
3791a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::MonitorExit,
3792a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetJavaVM,
3793a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringRegion,
3794a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringUTFRegion,
3795a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetPrimitiveArrayCritical,
3796a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleasePrimitiveArrayCritical,
3797a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetStringCritical,
3798a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ReleaseStringCritical,
3799a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewWeakGlobalRef,
3800a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::DeleteWeakGlobalRef,
3801a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::ExceptionCheck,
3802a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::NewDirectByteBuffer,
3803a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDirectBufferAddress,
3804a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetDirectBufferCapacity,
3805a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJNI::GetObjectRefType,
3806a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
3807a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3808a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNINativeInterface* GetCheckJniNativeInterface() {
3809a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  return &gCheckNativeInterface;
3810a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}
3811a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3812a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesclass CheckJII {
3813ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes public:
3814a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint DestroyJavaVM(JavaVM* vm) {
381568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
381668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.v = vm}};
381768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
381868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
381968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.i = BaseVm(vm)->DestroyJavaVM(vm);
3820def194e182ce703077e20bb59025998039fadb75Andreas Gampe    // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
3821def194e182ce703077e20bb59025998039fadb75Andreas Gampe    // which will delete the JavaVMExt.
3822def194e182ce703077e20bb59025998039fadb75Andreas Gampe    sc.CheckNonHeap(nullptr, false, "i", &result);
382368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result.i;
3824a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3825a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3826a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
382768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
382868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
382968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
383068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
383168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
383268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
383368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result.i;
3834a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3835a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3836a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
383768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
383868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
383968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
384068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
384168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
384268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
384368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result.i;
3844a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3845a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3846a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  static jint DetachCurrentThread(JavaVM* vm) {
384768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
384868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[1] = {{.v = vm}};
384968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
385068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
385168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.i = BaseVm(vm)->DetachCurrentThread(vm);
385268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
385368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result.i;
3854a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3855a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
385668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
385768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
385868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
385968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
386068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    JniValueType result;
386168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
386268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
386368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return result.i;
3864a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3865a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3866a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes private:
386768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers  static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
386868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers    return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
3869a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  }
3870a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
3871a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3872a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNIInvokeInterface gCheckInvokeInterface = {
3873ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved0
3874ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved1
3875ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  nullptr,  // reserved2
3876a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::DestroyJavaVM,
3877a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::AttachCurrentThread,
3878a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::DetachCurrentThread,
3879a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::GetEnv,
3880a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  CheckJII::AttachCurrentThreadAsDaemon
3881a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes};
3882a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3883a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNIInvokeInterface* GetCheckJniInvokeInterface() {
3884a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes  return &gCheckInvokeInterface;
3885a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}
3886a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes
3887a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}  // namespace art
3888