xref: /aosp_15_r20/art/runtime/jni/check_jni.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2008 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "check_jni.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <sys/mman.h>
20*795d594fSAndroid Build Coastguard Worker #include <zlib.h>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include <iomanip>
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
25*795d594fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
26*795d594fSAndroid Build Coastguard Worker 
27*795d594fSAndroid Build Coastguard Worker #include "art_field-inl.h"
28*795d594fSAndroid Build Coastguard Worker #include "art_method-inl.h"
29*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
30*795d594fSAndroid Build Coastguard Worker #include "base/to_str.h"
31*795d594fSAndroid Build Coastguard Worker #include "base/time_utils.h"
32*795d594fSAndroid Build Coastguard Worker #include "class_linker-inl.h"
33*795d594fSAndroid Build Coastguard Worker #include "class_linker.h"
34*795d594fSAndroid Build Coastguard Worker #include "class_root-inl.h"
35*795d594fSAndroid Build Coastguard Worker #include "dex/descriptors_names.h"
36*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file-inl.h"
37*795d594fSAndroid Build Coastguard Worker #include "gc/space/space.h"
38*795d594fSAndroid Build Coastguard Worker #include "indirect_reference_table-inl.h"
39*795d594fSAndroid Build Coastguard Worker #include "java_vm_ext.h"
40*795d594fSAndroid Build Coastguard Worker #include "jni_internal.h"
41*795d594fSAndroid Build Coastguard Worker #include "local_reference_table-inl.h"
42*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
43*795d594fSAndroid Build Coastguard Worker #include "mirror/field.h"
44*795d594fSAndroid Build Coastguard Worker #include "mirror/method.h"
45*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
46*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array-inl.h"
47*795d594fSAndroid Build Coastguard Worker #include "mirror/string-inl.h"
48*795d594fSAndroid Build Coastguard Worker #include "mirror/throwable.h"
49*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
50*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
51*795d594fSAndroid Build Coastguard Worker #include "thread.h"
52*795d594fSAndroid Build Coastguard Worker #include "well_known_classes.h"
53*795d594fSAndroid Build Coastguard Worker 
54*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
55*795d594fSAndroid Build Coastguard Worker 
56*795d594fSAndroid Build Coastguard Worker // This helper cannot be in the anonymous namespace because it needs to be
57*795d594fSAndroid Build Coastguard Worker // declared as a friend by JniVmExt and JniEnvExt.
GetIndirectReferenceTable(ScopedObjectAccess & soa,IndirectRefKind kind)58*795d594fSAndroid Build Coastguard Worker inline IndirectReferenceTable* GetIndirectReferenceTable(ScopedObjectAccess& soa,
59*795d594fSAndroid Build Coastguard Worker                                                          IndirectRefKind kind) {
60*795d594fSAndroid Build Coastguard Worker   DCHECK_NE(kind, kJniTransition);
61*795d594fSAndroid Build Coastguard Worker   DCHECK_NE(kind, kLocal);
62*795d594fSAndroid Build Coastguard Worker   JavaVMExt* vm = soa.Env()->GetVm();
63*795d594fSAndroid Build Coastguard Worker   IndirectReferenceTable* irt = (kind == kGlobal) ? &vm->globals_ : &vm->weak_globals_;
64*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(irt->GetKind(), kind);
65*795d594fSAndroid Build Coastguard Worker   return irt;
66*795d594fSAndroid Build Coastguard Worker }
67*795d594fSAndroid Build Coastguard Worker 
68*795d594fSAndroid Build Coastguard Worker // This helper cannot be in the anonymous namespace because it needs to be
69*795d594fSAndroid Build Coastguard Worker // declared as a friend by JniEnvExt.
GetLocalReferenceTable(ScopedObjectAccess & soa)70*795d594fSAndroid Build Coastguard Worker inline jni::LocalReferenceTable* GetLocalReferenceTable(ScopedObjectAccess& soa) {
71*795d594fSAndroid Build Coastguard Worker   return &soa.Env()->locals_;
72*795d594fSAndroid Build Coastguard Worker }
73*795d594fSAndroid Build Coastguard Worker 
74*795d594fSAndroid Build Coastguard Worker namespace {
75*795d594fSAndroid Build Coastguard Worker 
76*795d594fSAndroid Build Coastguard Worker using android::base::StringAppendF;
77*795d594fSAndroid Build Coastguard Worker using android::base::StringPrintf;
78*795d594fSAndroid Build Coastguard Worker 
79*795d594fSAndroid Build Coastguard Worker /*
80*795d594fSAndroid Build Coastguard Worker  * ===========================================================================
81*795d594fSAndroid Build Coastguard Worker  *      JNI function helpers
82*795d594fSAndroid Build Coastguard Worker  * ===========================================================================
83*795d594fSAndroid Build Coastguard Worker  */
84*795d594fSAndroid Build Coastguard Worker 
85*795d594fSAndroid Build Coastguard Worker // Warn if a JNI critical is held for longer than 16ms.
86*795d594fSAndroid Build Coastguard Worker static constexpr uint64_t kCriticalWarnTimeUs = MsToUs(16);
87*795d594fSAndroid Build Coastguard Worker static_assert(kCriticalWarnTimeUs > 0, "No JNI critical warn time set");
88*795d594fSAndroid Build Coastguard Worker 
89*795d594fSAndroid Build Coastguard Worker // True if primitives within specific ranges cause a fatal error,
90*795d594fSAndroid Build Coastguard Worker // otherwise just warn.
91*795d594fSAndroid Build Coastguard Worker static constexpr bool kBrokenPrimitivesAreFatal = kIsDebugBuild;
92*795d594fSAndroid Build Coastguard Worker 
93*795d594fSAndroid Build Coastguard Worker // Flags passed into ScopedCheck.
94*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_Default = 0x0000;
95*795d594fSAndroid Build Coastguard Worker 
96*795d594fSAndroid Build Coastguard Worker // Calling while in critical is not allowed.
97*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_CritBad = 0x0000;
98*795d594fSAndroid Build Coastguard Worker // Calling while in critical is allowed.
99*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_CritOkay = 0x0001;
100*795d594fSAndroid Build Coastguard Worker // This is a critical "get".
101*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_CritGet = 0x0002;
102*795d594fSAndroid Build Coastguard Worker // This is a critical "release".
103*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_CritRelease = 0x0003;
104*795d594fSAndroid Build Coastguard Worker // Bit mask to get "crit" value.
105*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_CritMask = 0x0003;
106*795d594fSAndroid Build Coastguard Worker 
107*795d594fSAndroid Build Coastguard Worker // Raised exceptions are allowed.
108*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_ExcepOkay = 0x0004;
109*795d594fSAndroid Build Coastguard Worker 
110*795d594fSAndroid Build Coastguard Worker // Are we in a non-critical release function?
111*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_Release = 0x0010;
112*795d594fSAndroid Build Coastguard Worker // Are our UTF parameters nullable?
113*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_NullableUtf = 0x0020;
114*795d594fSAndroid Build Coastguard Worker 
115*795d594fSAndroid Build Coastguard Worker // Part of the invocation interface (JavaVM*).
116*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_Invocation = 0x0100;
117*795d594fSAndroid Build Coastguard Worker 
118*795d594fSAndroid Build Coastguard Worker // Add this to a JNI function's flags if you want to trace every call.
119*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_ForceTrace = 0x8000;
120*795d594fSAndroid Build Coastguard Worker 
121*795d594fSAndroid Build Coastguard Worker class VarArgs;
122*795d594fSAndroid Build Coastguard Worker /*
123*795d594fSAndroid Build Coastguard Worker  * Java primitive types:
124*795d594fSAndroid Build Coastguard Worker  * B - jbyte
125*795d594fSAndroid Build Coastguard Worker  * C - jchar
126*795d594fSAndroid Build Coastguard Worker  * D - jdouble
127*795d594fSAndroid Build Coastguard Worker  * F - jfloat
128*795d594fSAndroid Build Coastguard Worker  * I - jint
129*795d594fSAndroid Build Coastguard Worker  * J - jlong
130*795d594fSAndroid Build Coastguard Worker  * S - jshort
131*795d594fSAndroid Build Coastguard Worker  * Z - jboolean (shown as true and false)
132*795d594fSAndroid Build Coastguard Worker  * V - void
133*795d594fSAndroid Build Coastguard Worker  *
134*795d594fSAndroid Build Coastguard Worker  * Java reference types:
135*795d594fSAndroid Build Coastguard Worker  * L - jobject
136*795d594fSAndroid Build Coastguard Worker  * a - jarray
137*795d594fSAndroid Build Coastguard Worker  * c - jclass
138*795d594fSAndroid Build Coastguard Worker  * s - jstring
139*795d594fSAndroid Build Coastguard Worker  * t - jthrowable
140*795d594fSAndroid Build Coastguard Worker  *
141*795d594fSAndroid Build Coastguard Worker  * JNI types:
142*795d594fSAndroid Build Coastguard Worker  * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
143*795d594fSAndroid Build Coastguard Worker  * f - jfieldID
144*795d594fSAndroid Build Coastguard Worker  * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION)
145*795d594fSAndroid Build Coastguard Worker  * m - jmethodID
146*795d594fSAndroid Build Coastguard Worker  * p - void*
147*795d594fSAndroid Build Coastguard Worker  * r - jint (for release mode arguments)
148*795d594fSAndroid Build Coastguard Worker  * u - const char* (Modified UTF-8)
149*795d594fSAndroid Build Coastguard Worker  * z - jsize (for lengths; use i if negative values are okay)
150*795d594fSAndroid Build Coastguard Worker  * v - JavaVM*
151*795d594fSAndroid Build Coastguard Worker  * w - jobjectRefType
152*795d594fSAndroid Build Coastguard Worker  * E - JNIEnv*
153*795d594fSAndroid Build Coastguard Worker  * . - no argument; just print "..." (used for varargs JNI calls)
154*795d594fSAndroid Build Coastguard Worker  *
155*795d594fSAndroid Build Coastguard Worker  */
156*795d594fSAndroid Build Coastguard Worker union JniValueType {
157*795d594fSAndroid Build Coastguard Worker   jarray a;
158*795d594fSAndroid Build Coastguard Worker   jboolean b;
159*795d594fSAndroid Build Coastguard Worker   jclass c;
160*795d594fSAndroid Build Coastguard Worker   jfieldID f;
161*795d594fSAndroid Build Coastguard Worker   jint i;
162*795d594fSAndroid Build Coastguard Worker   jmethodID m;
163*795d594fSAndroid Build Coastguard Worker   const void* p;  // Pointer.
164*795d594fSAndroid Build Coastguard Worker   jint r;  // Release mode.
165*795d594fSAndroid Build Coastguard Worker   jstring s;
166*795d594fSAndroid Build Coastguard Worker   jthrowable t;
167*795d594fSAndroid Build Coastguard Worker   const char* u;  // Modified UTF-8.
168*795d594fSAndroid Build Coastguard Worker   JavaVM* v;
169*795d594fSAndroid Build Coastguard Worker   jobjectRefType w;
170*795d594fSAndroid Build Coastguard Worker   jsize z;
171*795d594fSAndroid Build Coastguard Worker   jbyte B;
172*795d594fSAndroid Build Coastguard Worker   jchar C;
173*795d594fSAndroid Build Coastguard Worker   jdouble D;
174*795d594fSAndroid Build Coastguard Worker   JNIEnv* E;
175*795d594fSAndroid Build Coastguard Worker   jfloat F;
176*795d594fSAndroid Build Coastguard Worker   jint I;
177*795d594fSAndroid Build Coastguard Worker   jlong J;
178*795d594fSAndroid Build Coastguard Worker   jobject L;
179*795d594fSAndroid Build Coastguard Worker   jshort S;
180*795d594fSAndroid Build Coastguard Worker   const void* V;  // void
181*795d594fSAndroid Build Coastguard Worker   jboolean Z;
182*795d594fSAndroid Build Coastguard Worker   const VarArgs* va;
183*795d594fSAndroid Build Coastguard Worker };
184*795d594fSAndroid Build Coastguard Worker 
185*795d594fSAndroid Build Coastguard Worker /*
186*795d594fSAndroid Build Coastguard Worker  * A structure containing all the information needed to validate varargs arguments.
187*795d594fSAndroid Build Coastguard Worker  *
188*795d594fSAndroid Build Coastguard Worker  * Note that actually getting the arguments from this structure mutates it so should only be done on
189*795d594fSAndroid Build Coastguard Worker  * owned copies.
190*795d594fSAndroid Build Coastguard Worker  */
191*795d594fSAndroid Build Coastguard Worker class VarArgs {
192*795d594fSAndroid Build Coastguard Worker  public:
VarArgs(jmethodID m,va_list var)193*795d594fSAndroid Build Coastguard Worker   VarArgs(jmethodID m, va_list var) : m_(m), type_(kTypeVaList), cnt_(0) {
194*795d594fSAndroid Build Coastguard Worker     va_copy(vargs_, var);
195*795d594fSAndroid Build Coastguard Worker   }
196*795d594fSAndroid Build Coastguard Worker 
VarArgs(jmethodID m,const jvalue * vals)197*795d594fSAndroid Build Coastguard Worker   VarArgs(jmethodID m, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(0), ptr_(vals) {}
198*795d594fSAndroid Build Coastguard Worker 
~VarArgs()199*795d594fSAndroid Build Coastguard Worker   ~VarArgs() {
200*795d594fSAndroid Build Coastguard Worker     if (type_ == kTypeVaList) {
201*795d594fSAndroid Build Coastguard Worker       va_end(vargs_);
202*795d594fSAndroid Build Coastguard Worker     }
203*795d594fSAndroid Build Coastguard Worker   }
204*795d594fSAndroid Build Coastguard Worker 
VarArgs(VarArgs && other)205*795d594fSAndroid Build Coastguard Worker   VarArgs(VarArgs&& other) noexcept {
206*795d594fSAndroid Build Coastguard Worker     m_ = other.m_;
207*795d594fSAndroid Build Coastguard Worker     cnt_ = other.cnt_;
208*795d594fSAndroid Build Coastguard Worker     type_ = other.type_;
209*795d594fSAndroid Build Coastguard Worker     if (other.type_ == kTypeVaList) {
210*795d594fSAndroid Build Coastguard Worker       va_copy(vargs_, other.vargs_);
211*795d594fSAndroid Build Coastguard Worker     } else {
212*795d594fSAndroid Build Coastguard Worker       ptr_ = other.ptr_;
213*795d594fSAndroid Build Coastguard Worker     }
214*795d594fSAndroid Build Coastguard Worker   }
215*795d594fSAndroid Build Coastguard Worker 
216*795d594fSAndroid Build Coastguard Worker   // This method is const because we need to ensure that one only uses the GetValue method on an
217*795d594fSAndroid Build Coastguard Worker   // owned copy of the VarArgs. This is because getting the next argument from a va_list is a
218*795d594fSAndroid Build Coastguard Worker   // mutating operation. Therefore we pass around these VarArgs with the 'const' qualifier and when
219*795d594fSAndroid Build Coastguard Worker   // we want to use one we need to Clone() it.
Clone() const220*795d594fSAndroid Build Coastguard Worker   VarArgs Clone() const {
221*795d594fSAndroid Build Coastguard Worker     if (type_ == kTypeVaList) {
222*795d594fSAndroid Build Coastguard Worker       // const_cast needed to make sure the compiler is okay with va_copy, which (being a macro) is
223*795d594fSAndroid Build Coastguard Worker       // messed up if the source argument is not the exact type 'va_list'.
224*795d594fSAndroid Build Coastguard Worker       return VarArgs(m_, cnt_, const_cast<VarArgs*>(this)->vargs_);
225*795d594fSAndroid Build Coastguard Worker     } else {
226*795d594fSAndroid Build Coastguard Worker       return VarArgs(m_, cnt_, ptr_);
227*795d594fSAndroid Build Coastguard Worker     }
228*795d594fSAndroid Build Coastguard Worker   }
229*795d594fSAndroid Build Coastguard Worker 
GetMethodID() const230*795d594fSAndroid Build Coastguard Worker   jmethodID GetMethodID() const {
231*795d594fSAndroid Build Coastguard Worker     return m_;
232*795d594fSAndroid Build Coastguard Worker   }
233*795d594fSAndroid Build Coastguard Worker 
GetValue(char fmt)234*795d594fSAndroid Build Coastguard Worker   JniValueType GetValue(char fmt) {
235*795d594fSAndroid Build Coastguard Worker     JniValueType o;
236*795d594fSAndroid Build Coastguard Worker     if (type_ == kTypeVaList) {
237*795d594fSAndroid Build Coastguard Worker       switch (fmt) {
238*795d594fSAndroid Build Coastguard Worker         // Assign a full int for va_list values as this is what is done in reflection.cc.
239*795d594fSAndroid Build Coastguard Worker         // TODO(b/73656264): avoid undefined behavior.
240*795d594fSAndroid Build Coastguard Worker         case 'Z': FALLTHROUGH_INTENDED;
241*795d594fSAndroid Build Coastguard Worker         case 'B': FALLTHROUGH_INTENDED;
242*795d594fSAndroid Build Coastguard Worker         case 'C': FALLTHROUGH_INTENDED;
243*795d594fSAndroid Build Coastguard Worker         case 'S': FALLTHROUGH_INTENDED;
244*795d594fSAndroid Build Coastguard Worker         case 'I': o.I = va_arg(vargs_, jint); break;
245*795d594fSAndroid Build Coastguard Worker         case 'J': o.J = va_arg(vargs_, jlong); break;
246*795d594fSAndroid Build Coastguard Worker         case 'F': o.F = static_cast<jfloat>(va_arg(vargs_, jdouble)); break;
247*795d594fSAndroid Build Coastguard Worker         case 'D': o.D = va_arg(vargs_, jdouble); break;
248*795d594fSAndroid Build Coastguard Worker         case 'L': o.L = va_arg(vargs_, jobject); break;
249*795d594fSAndroid Build Coastguard Worker         default:
250*795d594fSAndroid Build Coastguard Worker           LOG(FATAL) << "Illegal type format char " << fmt;
251*795d594fSAndroid Build Coastguard Worker           UNREACHABLE();
252*795d594fSAndroid Build Coastguard Worker       }
253*795d594fSAndroid Build Coastguard Worker     } else {
254*795d594fSAndroid Build Coastguard Worker       CHECK(type_ == kTypePtr);
255*795d594fSAndroid Build Coastguard Worker       jvalue v = ptr_[cnt_];
256*795d594fSAndroid Build Coastguard Worker       cnt_++;
257*795d594fSAndroid Build Coastguard Worker       switch (fmt) {
258*795d594fSAndroid Build Coastguard Worker         // Copy just the amount of the jvalue necessary, as done in
259*795d594fSAndroid Build Coastguard Worker         // reflection.cc, but extend to an int to be consistent with
260*795d594fSAndroid Build Coastguard Worker         // var args in CheckNonHeapValue.
261*795d594fSAndroid Build Coastguard Worker         // TODO(b/73656264): avoid undefined behavior.
262*795d594fSAndroid Build Coastguard Worker         case 'Z': o.I = v.z; break;
263*795d594fSAndroid Build Coastguard Worker         case 'B': o.I = v.b; break;
264*795d594fSAndroid Build Coastguard Worker         case 'C': o.I = v.c; break;
265*795d594fSAndroid Build Coastguard Worker         case 'S': o.I = v.s; break;
266*795d594fSAndroid Build Coastguard Worker         case 'I': o.I = v.i; break;
267*795d594fSAndroid Build Coastguard Worker         case 'J': o.J = v.j; break;
268*795d594fSAndroid Build Coastguard Worker         case 'F': o.F = v.f; break;
269*795d594fSAndroid Build Coastguard Worker         case 'D': o.D = v.d; break;
270*795d594fSAndroid Build Coastguard Worker         case 'L': o.L = v.l; break;
271*795d594fSAndroid Build Coastguard Worker         default:
272*795d594fSAndroid Build Coastguard Worker           LOG(FATAL) << "Illegal type format char " << fmt;
273*795d594fSAndroid Build Coastguard Worker           UNREACHABLE();
274*795d594fSAndroid Build Coastguard Worker       }
275*795d594fSAndroid Build Coastguard Worker     }
276*795d594fSAndroid Build Coastguard Worker     return o;
277*795d594fSAndroid Build Coastguard Worker   }
278*795d594fSAndroid Build Coastguard Worker 
279*795d594fSAndroid Build Coastguard Worker  private:
VarArgs(jmethodID m,uint32_t cnt,va_list var)280*795d594fSAndroid Build Coastguard Worker   VarArgs(jmethodID m, uint32_t cnt, va_list var) : m_(m), type_(kTypeVaList), cnt_(cnt) {
281*795d594fSAndroid Build Coastguard Worker     va_copy(vargs_, var);
282*795d594fSAndroid Build Coastguard Worker   }
283*795d594fSAndroid Build Coastguard Worker 
VarArgs(jmethodID m,uint32_t cnt,const jvalue * vals)284*795d594fSAndroid Build Coastguard Worker   VarArgs(jmethodID m, uint32_t cnt, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(cnt), ptr_(vals) {}
285*795d594fSAndroid Build Coastguard Worker 
286*795d594fSAndroid Build Coastguard Worker   enum VarArgsType {
287*795d594fSAndroid Build Coastguard Worker     kTypeVaList,
288*795d594fSAndroid Build Coastguard Worker     kTypePtr,
289*795d594fSAndroid Build Coastguard Worker   };
290*795d594fSAndroid Build Coastguard Worker 
291*795d594fSAndroid Build Coastguard Worker   jmethodID m_;
292*795d594fSAndroid Build Coastguard Worker   VarArgsType type_;
293*795d594fSAndroid Build Coastguard Worker   uint32_t cnt_;
294*795d594fSAndroid Build Coastguard Worker   union {
295*795d594fSAndroid Build Coastguard Worker     va_list vargs_;
296*795d594fSAndroid Build Coastguard Worker     const jvalue* ptr_;
297*795d594fSAndroid Build Coastguard Worker   };
298*795d594fSAndroid Build Coastguard Worker };
299*795d594fSAndroid Build Coastguard Worker 
300*795d594fSAndroid Build Coastguard Worker // Check whether the current thread is attached. This is usually required
301*795d594fSAndroid Build Coastguard Worker // to be the first check, as ScopedCheck needs a ScopedObjectAccess for
302*795d594fSAndroid Build Coastguard Worker // checking heap values (and that will fail with unattached threads).
CheckAttachedThread(const char * function_name)303*795d594fSAndroid Build Coastguard Worker bool CheckAttachedThread(const char* function_name) {
304*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
305*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(self == nullptr)) {
306*795d594fSAndroid Build Coastguard Worker     // Need to attach this thread for a proper abort to work. We prefer this
307*795d594fSAndroid Build Coastguard Worker     // to get reasonable stacks and environment, rather than relying on
308*795d594fSAndroid Build Coastguard Worker     // tombstoned.
309*795d594fSAndroid Build Coastguard Worker     JNIEnv* env;
310*795d594fSAndroid Build Coastguard Worker     Runtime::Current()->GetJavaVM()->AttachCurrentThread(&env, /* thr_args= */ nullptr);
311*795d594fSAndroid Build Coastguard Worker 
312*795d594fSAndroid Build Coastguard Worker     std::string tmp = android::base::StringPrintf(
313*795d594fSAndroid Build Coastguard Worker         "a thread (tid %" PRId64 " is making JNI calls without being attached",
314*795d594fSAndroid Build Coastguard Worker         static_cast<int64_t>(GetTid()));
315*795d594fSAndroid Build Coastguard Worker     Runtime::Current()->GetJavaVM()->JniAbort(function_name, tmp.c_str());
316*795d594fSAndroid Build Coastguard Worker 
317*795d594fSAndroid Build Coastguard Worker     CHECK_NE(Runtime::Current()->GetJavaVM()->DetachCurrentThread(), JNI_ERR);
318*795d594fSAndroid Build Coastguard Worker     return false;
319*795d594fSAndroid Build Coastguard Worker   }
320*795d594fSAndroid Build Coastguard Worker   return true;
321*795d594fSAndroid Build Coastguard Worker }
322*795d594fSAndroid Build Coastguard Worker 
323*795d594fSAndroid Build Coastguard Worker // Macro helpers for the above.
324*795d594fSAndroid Build Coastguard Worker #define CHECK_ATTACHED_THREAD(function_name, fail_val)  \
325*795d594fSAndroid Build Coastguard Worker   do {                                                  \
326*795d594fSAndroid Build Coastguard Worker     if (!CheckAttachedThread((function_name))) {        \
327*795d594fSAndroid Build Coastguard Worker       return fail_val;                                  \
328*795d594fSAndroid Build Coastguard Worker     }                                                   \
329*795d594fSAndroid Build Coastguard Worker   } while (false)
330*795d594fSAndroid Build Coastguard Worker #define CHECK_ATTACHED_THREAD_VOID(function_name)       \
331*795d594fSAndroid Build Coastguard Worker   do {                                                  \
332*795d594fSAndroid Build Coastguard Worker     if (!CheckAttachedThread((function_name))) {        \
333*795d594fSAndroid Build Coastguard Worker       return;                                           \
334*795d594fSAndroid Build Coastguard Worker     }                                                   \
335*795d594fSAndroid Build Coastguard Worker   } while (false)
336*795d594fSAndroid Build Coastguard Worker 
337*795d594fSAndroid Build Coastguard Worker class ScopedCheck {
338*795d594fSAndroid Build Coastguard Worker  public:
ScopedCheck(uint16_t flags,const char * functionName,bool has_method=true)339*795d594fSAndroid Build Coastguard Worker   ScopedCheck(uint16_t flags, const char* functionName, bool has_method = true)
340*795d594fSAndroid Build Coastguard Worker       : function_name_(functionName), indent_(0), flags_(flags), has_method_(has_method) {
341*795d594fSAndroid Build Coastguard Worker   }
342*795d594fSAndroid Build Coastguard Worker 
~ScopedCheck()343*795d594fSAndroid Build Coastguard Worker   ~ScopedCheck() {}
344*795d594fSAndroid Build Coastguard Worker 
345*795d594fSAndroid Build Coastguard Worker   // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
346*795d594fSAndroid Build Coastguard Worker   // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
347*795d594fSAndroid Build Coastguard Worker   // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
348*795d594fSAndroid Build Coastguard Worker   // circumstances, but this is incorrect.
CheckClassName(const char * class_name)349*795d594fSAndroid Build Coastguard Worker   bool CheckClassName(const char* class_name) {
350*795d594fSAndroid Build Coastguard Worker     if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
351*795d594fSAndroid Build Coastguard Worker       AbortF("illegal class name '%s'\n"
352*795d594fSAndroid Build Coastguard Worker              "    (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
353*795d594fSAndroid Build Coastguard Worker              class_name);
354*795d594fSAndroid Build Coastguard Worker       return false;
355*795d594fSAndroid Build Coastguard Worker     }
356*795d594fSAndroid Build Coastguard Worker     return true;
357*795d594fSAndroid Build Coastguard Worker   }
358*795d594fSAndroid Build Coastguard Worker 
359*795d594fSAndroid Build Coastguard Worker   /*
360*795d594fSAndroid Build Coastguard Worker    * Verify that this instance field ID is valid for this object.
361*795d594fSAndroid Build Coastguard Worker    *
362*795d594fSAndroid Build Coastguard Worker    * Assumes "jobj" has already been validated.
363*795d594fSAndroid Build Coastguard Worker    */
CheckInstanceFieldID(ScopedObjectAccess & soa,jobject java_object,jfieldID fid)364*795d594fSAndroid Build Coastguard Worker   bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
365*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
366*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
367*795d594fSAndroid Build Coastguard Worker     if (o == nullptr) {
368*795d594fSAndroid Build Coastguard Worker       AbortF("field operation on NULL object: %p", java_object);
369*795d594fSAndroid Build Coastguard Worker       return false;
370*795d594fSAndroid Build Coastguard Worker     }
371*795d594fSAndroid Build Coastguard Worker     if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o.Ptr())) {
372*795d594fSAndroid Build Coastguard Worker       Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
373*795d594fSAndroid Build Coastguard Worker       AbortF("field operation on invalid %s: %p",
374*795d594fSAndroid Build Coastguard Worker              GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
375*795d594fSAndroid Build Coastguard Worker              java_object);
376*795d594fSAndroid Build Coastguard Worker       return false;
377*795d594fSAndroid Build Coastguard Worker     }
378*795d594fSAndroid Build Coastguard Worker 
379*795d594fSAndroid Build Coastguard Worker     ArtField* f = CheckFieldID(fid);
380*795d594fSAndroid Build Coastguard Worker     if (f == nullptr) {
381*795d594fSAndroid Build Coastguard Worker       return false;
382*795d594fSAndroid Build Coastguard Worker     }
383*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Class> c = o->GetClass();
384*795d594fSAndroid Build Coastguard Worker     if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
385*795d594fSAndroid Build Coastguard Worker       AbortF("jfieldID %s not valid for an object of class %s",
386*795d594fSAndroid Build Coastguard Worker              f->PrettyField().c_str(), o->PrettyTypeOf().c_str());
387*795d594fSAndroid Build Coastguard Worker       return false;
388*795d594fSAndroid Build Coastguard Worker     }
389*795d594fSAndroid Build Coastguard Worker     return true;
390*795d594fSAndroid Build Coastguard Worker   }
391*795d594fSAndroid Build Coastguard Worker 
392*795d594fSAndroid Build Coastguard Worker   /*
393*795d594fSAndroid Build Coastguard Worker    * Verify that the pointer value is non-null.
394*795d594fSAndroid Build Coastguard Worker    */
CheckNonNull(const void * ptr)395*795d594fSAndroid Build Coastguard Worker   bool CheckNonNull(const void* ptr) {
396*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(ptr == nullptr)) {
397*795d594fSAndroid Build Coastguard Worker       AbortF("non-nullable argument was NULL");
398*795d594fSAndroid Build Coastguard Worker       return false;
399*795d594fSAndroid Build Coastguard Worker     }
400*795d594fSAndroid Build Coastguard Worker     return true;
401*795d594fSAndroid Build Coastguard Worker   }
402*795d594fSAndroid Build Coastguard Worker 
403*795d594fSAndroid Build Coastguard Worker   /*
404*795d594fSAndroid Build Coastguard Worker    * Verify that the method's return type matches the type of call.
405*795d594fSAndroid Build Coastguard Worker    * 'expectedType' will be "L" for all objects, including arrays.
406*795d594fSAndroid Build Coastguard Worker    */
CheckMethodAndSig(ScopedObjectAccess & soa,jobject jobj,jclass jc,jmethodID mid,Primitive::Type type,InvokeType invoke)407*795d594fSAndroid Build Coastguard Worker   bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
408*795d594fSAndroid Build Coastguard Worker                          jmethodID mid, Primitive::Type type, InvokeType invoke)
409*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
410*795d594fSAndroid Build Coastguard Worker     ArtMethod* m = CheckMethodID(mid);
411*795d594fSAndroid Build Coastguard Worker     if (m == nullptr) {
412*795d594fSAndroid Build Coastguard Worker       return false;
413*795d594fSAndroid Build Coastguard Worker     }
414*795d594fSAndroid Build Coastguard Worker     if (type != Primitive::GetType(m->GetShorty()[0])) {
415*795d594fSAndroid Build Coastguard Worker       AbortF("the return type of %s does not match %s", function_name_, m->PrettyMethod().c_str());
416*795d594fSAndroid Build Coastguard Worker       return false;
417*795d594fSAndroid Build Coastguard Worker     }
418*795d594fSAndroid Build Coastguard Worker     bool is_static = (invoke == kStatic);
419*795d594fSAndroid Build Coastguard Worker     if (is_static != m->IsStatic()) {
420*795d594fSAndroid Build Coastguard Worker       if (is_static) {
421*795d594fSAndroid Build Coastguard Worker         AbortF("calling non-static method %s with %s",
422*795d594fSAndroid Build Coastguard Worker                m->PrettyMethod().c_str(), function_name_);
423*795d594fSAndroid Build Coastguard Worker       } else {
424*795d594fSAndroid Build Coastguard Worker         AbortF("calling static method %s with %s",
425*795d594fSAndroid Build Coastguard Worker                m->PrettyMethod().c_str(), function_name_);
426*795d594fSAndroid Build Coastguard Worker       }
427*795d594fSAndroid Build Coastguard Worker       return false;
428*795d594fSAndroid Build Coastguard Worker     }
429*795d594fSAndroid Build Coastguard Worker     if (invoke != kVirtual) {
430*795d594fSAndroid Build Coastguard Worker       ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
431*795d594fSAndroid Build Coastguard Worker       if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
432*795d594fSAndroid Build Coastguard Worker         AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
433*795d594fSAndroid Build Coastguard Worker             m->PrettyMethod().c_str(), mirror::Class::PrettyClass(c).c_str());
434*795d594fSAndroid Build Coastguard Worker         return false;
435*795d594fSAndroid Build Coastguard Worker       }
436*795d594fSAndroid Build Coastguard Worker     }
437*795d594fSAndroid Build Coastguard Worker     if (invoke != kStatic) {
438*795d594fSAndroid Build Coastguard Worker       ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(jobj);
439*795d594fSAndroid Build Coastguard Worker       if (o == nullptr) {
440*795d594fSAndroid Build Coastguard Worker         AbortF("can't call %s on null object", m->PrettyMethod().c_str());
441*795d594fSAndroid Build Coastguard Worker         return false;
442*795d594fSAndroid Build Coastguard Worker       } else if (!o->InstanceOf(m->GetDeclaringClass())) {
443*795d594fSAndroid Build Coastguard Worker         AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
444*795d594fSAndroid Build Coastguard Worker                o->PrettyTypeOf().c_str());
445*795d594fSAndroid Build Coastguard Worker         return false;
446*795d594fSAndroid Build Coastguard Worker       }
447*795d594fSAndroid Build Coastguard Worker     }
448*795d594fSAndroid Build Coastguard Worker     return true;
449*795d594fSAndroid Build Coastguard Worker   }
450*795d594fSAndroid Build Coastguard Worker 
451*795d594fSAndroid Build Coastguard Worker   /*
452*795d594fSAndroid Build Coastguard Worker    * Verify that this static field ID is valid for this class.
453*795d594fSAndroid Build Coastguard Worker    *
454*795d594fSAndroid Build Coastguard Worker    * Assumes "java_class" has already been validated.
455*795d594fSAndroid Build Coastguard Worker    */
CheckStaticFieldID(ScopedObjectAccess & soa,jclass java_class,jfieldID fid)456*795d594fSAndroid Build Coastguard Worker   bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
457*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
458*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
459*795d594fSAndroid Build Coastguard Worker     ArtField* f = CheckFieldID(fid);
460*795d594fSAndroid Build Coastguard Worker     if (f == nullptr) {
461*795d594fSAndroid Build Coastguard Worker       return false;
462*795d594fSAndroid Build Coastguard Worker     }
463*795d594fSAndroid Build Coastguard Worker     if (!f->GetDeclaringClass()->IsAssignableFrom(c)) {
464*795d594fSAndroid Build Coastguard Worker       AbortF("static jfieldID %p not valid for class %s", fid,
465*795d594fSAndroid Build Coastguard Worker              mirror::Class::PrettyClass(c).c_str());
466*795d594fSAndroid Build Coastguard Worker       return false;
467*795d594fSAndroid Build Coastguard Worker     }
468*795d594fSAndroid Build Coastguard Worker     return true;
469*795d594fSAndroid Build Coastguard Worker   }
470*795d594fSAndroid Build Coastguard Worker 
471*795d594fSAndroid Build Coastguard Worker   /*
472*795d594fSAndroid Build Coastguard Worker    * Verify that "mid" is appropriate for "java_class".
473*795d594fSAndroid Build Coastguard Worker    *
474*795d594fSAndroid Build Coastguard Worker    * A mismatch isn't dangerous, because the jmethodID defines the class.  In
475*795d594fSAndroid Build Coastguard Worker    * fact, java_class is unused in the implementation.  It's best if we don't
476*795d594fSAndroid Build Coastguard Worker    * allow bad code in the system though.
477*795d594fSAndroid Build Coastguard Worker    *
478*795d594fSAndroid Build Coastguard Worker    * Instances of "java_class" must be instances of the method's declaring class.
479*795d594fSAndroid Build Coastguard Worker    */
CheckStaticMethod(ScopedObjectAccess & soa,jclass java_class,jmethodID mid)480*795d594fSAndroid Build Coastguard Worker   bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
481*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
482*795d594fSAndroid Build Coastguard Worker     ArtMethod* m = CheckMethodID(mid);
483*795d594fSAndroid Build Coastguard Worker     if (m == nullptr) {
484*795d594fSAndroid Build Coastguard Worker       return false;
485*795d594fSAndroid Build Coastguard Worker     }
486*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
487*795d594fSAndroid Build Coastguard Worker     if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
488*795d594fSAndroid Build Coastguard Worker       AbortF("can't call static %s on class %s", m->PrettyMethod().c_str(),
489*795d594fSAndroid Build Coastguard Worker              mirror::Class::PrettyClass(c).c_str());
490*795d594fSAndroid Build Coastguard Worker       return false;
491*795d594fSAndroid Build Coastguard Worker     }
492*795d594fSAndroid Build Coastguard Worker     return true;
493*795d594fSAndroid Build Coastguard Worker   }
494*795d594fSAndroid Build Coastguard Worker 
495*795d594fSAndroid Build Coastguard Worker   /*
496*795d594fSAndroid Build Coastguard Worker    * Verify that "mid" is appropriate for "jobj".
497*795d594fSAndroid Build Coastguard Worker    *
498*795d594fSAndroid Build Coastguard Worker    * Make sure the object is an instance of the method's declaring class.
499*795d594fSAndroid Build Coastguard Worker    * (Note the mid might point to a declaration in an interface; this
500*795d594fSAndroid Build Coastguard Worker    * will be handled automatically by the instanceof check.)
501*795d594fSAndroid Build Coastguard Worker    */
CheckVirtualMethod(ScopedObjectAccess & soa,jobject java_object,jmethodID mid)502*795d594fSAndroid Build Coastguard Worker   bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
503*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
504*795d594fSAndroid Build Coastguard Worker     ArtMethod* m = CheckMethodID(mid);
505*795d594fSAndroid Build Coastguard Worker     if (m == nullptr) {
506*795d594fSAndroid Build Coastguard Worker       return false;
507*795d594fSAndroid Build Coastguard Worker     }
508*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
509*795d594fSAndroid Build Coastguard Worker     if (o == nullptr) {
510*795d594fSAndroid Build Coastguard Worker       AbortF("can't call %s on null object", m->PrettyMethod().c_str());
511*795d594fSAndroid Build Coastguard Worker       return false;
512*795d594fSAndroid Build Coastguard Worker     } else if (!o->InstanceOf(m->GetDeclaringClass())) {
513*795d594fSAndroid Build Coastguard Worker       AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
514*795d594fSAndroid Build Coastguard Worker              o->PrettyTypeOf().c_str());
515*795d594fSAndroid Build Coastguard Worker       return false;
516*795d594fSAndroid Build Coastguard Worker     }
517*795d594fSAndroid Build Coastguard Worker     return true;
518*795d594fSAndroid Build Coastguard Worker   }
519*795d594fSAndroid Build Coastguard Worker 
520*795d594fSAndroid Build Coastguard Worker   /**
521*795d594fSAndroid Build Coastguard Worker    * The format string is a sequence of the following characters,
522*795d594fSAndroid Build Coastguard Worker    * and must be followed by arguments of the corresponding types
523*795d594fSAndroid Build Coastguard Worker    * in the same order.
524*795d594fSAndroid Build Coastguard Worker    *
525*795d594fSAndroid Build Coastguard Worker    * Java primitive types:
526*795d594fSAndroid Build Coastguard Worker    * B - jbyte
527*795d594fSAndroid Build Coastguard Worker    * C - jchar
528*795d594fSAndroid Build Coastguard Worker    * D - jdouble
529*795d594fSAndroid Build Coastguard Worker    * F - jfloat
530*795d594fSAndroid Build Coastguard Worker    * I - jint
531*795d594fSAndroid Build Coastguard Worker    * J - jlong
532*795d594fSAndroid Build Coastguard Worker    * S - jshort
533*795d594fSAndroid Build Coastguard Worker    * Z - jboolean (shown as true and false)
534*795d594fSAndroid Build Coastguard Worker    * V - void
535*795d594fSAndroid Build Coastguard Worker    *
536*795d594fSAndroid Build Coastguard Worker    * Java reference types:
537*795d594fSAndroid Build Coastguard Worker    * L - jobject
538*795d594fSAndroid Build Coastguard Worker    * a - jarray
539*795d594fSAndroid Build Coastguard Worker    * c - jclass
540*795d594fSAndroid Build Coastguard Worker    * s - jstring
541*795d594fSAndroid Build Coastguard Worker    *
542*795d594fSAndroid Build Coastguard Worker    * JNI types:
543*795d594fSAndroid Build Coastguard Worker    * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
544*795d594fSAndroid Build Coastguard Worker    * f - jfieldID
545*795d594fSAndroid Build Coastguard Worker    * m - jmethodID
546*795d594fSAndroid Build Coastguard Worker    * p - void*
547*795d594fSAndroid Build Coastguard Worker    * r - jint (for release mode arguments)
548*795d594fSAndroid Build Coastguard Worker    * u - const char* (Modified UTF-8)
549*795d594fSAndroid Build Coastguard Worker    * z - jsize (for lengths; use i if negative values are okay)
550*795d594fSAndroid Build Coastguard Worker    * v - JavaVM*
551*795d594fSAndroid Build Coastguard Worker    * E - JNIEnv*
552*795d594fSAndroid Build Coastguard Worker    * . - VarArgs* for Jni calls with variable length arguments
553*795d594fSAndroid Build Coastguard Worker    *
554*795d594fSAndroid Build Coastguard Worker    * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
555*795d594fSAndroid Build Coastguard Worker    */
Check(ScopedObjectAccess & soa,bool entry,const char * fmt,JniValueType * args)556*795d594fSAndroid Build Coastguard Worker   bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
557*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
558*795d594fSAndroid Build Coastguard Worker     ArtMethod* traceMethod = nullptr;
559*795d594fSAndroid Build Coastguard Worker     if (has_method_ && soa.Vm()->IsTracingEnabled()) {
560*795d594fSAndroid Build Coastguard Worker       // We need to guard some of the invocation interface's calls: a bad caller might
561*795d594fSAndroid Build Coastguard Worker       // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
562*795d594fSAndroid Build Coastguard Worker       Thread* self = Thread::Current();
563*795d594fSAndroid Build Coastguard Worker       if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
564*795d594fSAndroid Build Coastguard Worker         traceMethod = self->GetCurrentMethod(nullptr);
565*795d594fSAndroid Build Coastguard Worker       }
566*795d594fSAndroid Build Coastguard Worker     }
567*795d594fSAndroid Build Coastguard Worker 
568*795d594fSAndroid Build Coastguard Worker     if (((flags_ & kFlag_ForceTrace) != 0) ||
569*795d594fSAndroid Build Coastguard Worker         (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
570*795d594fSAndroid Build Coastguard Worker       std::string msg;
571*795d594fSAndroid Build Coastguard Worker       for (size_t i = 0; fmt[i] != '\0'; ++i) {
572*795d594fSAndroid Build Coastguard Worker         TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
573*795d594fSAndroid Build Coastguard Worker         if (fmt[i + 1] != '\0') {
574*795d594fSAndroid Build Coastguard Worker           StringAppendF(&msg, ", ");
575*795d594fSAndroid Build Coastguard Worker         }
576*795d594fSAndroid Build Coastguard Worker       }
577*795d594fSAndroid Build Coastguard Worker 
578*795d594fSAndroid Build Coastguard Worker       if ((flags_ & kFlag_ForceTrace) != 0) {
579*795d594fSAndroid Build Coastguard Worker         LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
580*795d594fSAndroid Build Coastguard Worker       } else if (entry) {
581*795d594fSAndroid Build Coastguard Worker         if (has_method_) {
582*795d594fSAndroid Build Coastguard Worker           std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
583*795d594fSAndroid Build Coastguard Worker           LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
584*795d594fSAndroid Build Coastguard Worker           indent_ = methodName.size() + 1;
585*795d594fSAndroid Build Coastguard Worker         } else {
586*795d594fSAndroid Build Coastguard Worker           LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
587*795d594fSAndroid Build Coastguard Worker           indent_ = 0;
588*795d594fSAndroid Build Coastguard Worker         }
589*795d594fSAndroid Build Coastguard Worker       } else {
590*795d594fSAndroid Build Coastguard Worker         LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
591*795d594fSAndroid Build Coastguard Worker       }
592*795d594fSAndroid Build Coastguard Worker     }
593*795d594fSAndroid Build Coastguard Worker 
594*795d594fSAndroid Build Coastguard Worker     // We always do the thorough checks on entry, and never on exit...
595*795d594fSAndroid Build Coastguard Worker     if (entry) {
596*795d594fSAndroid Build Coastguard Worker       for (size_t i = 0; fmt[i] != '\0'; ++i) {
597*795d594fSAndroid Build Coastguard Worker         if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
598*795d594fSAndroid Build Coastguard Worker           return false;
599*795d594fSAndroid Build Coastguard Worker         }
600*795d594fSAndroid Build Coastguard Worker       }
601*795d594fSAndroid Build Coastguard Worker     }
602*795d594fSAndroid Build Coastguard Worker     return true;
603*795d594fSAndroid Build Coastguard Worker   }
604*795d594fSAndroid Build Coastguard Worker 
CheckNonHeap(JavaVMExt * vm,bool entry,const char * fmt,JniValueType * args)605*795d594fSAndroid Build Coastguard Worker   bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
606*795d594fSAndroid Build Coastguard Worker     bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
607*795d594fSAndroid Build Coastguard Worker     if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
608*795d594fSAndroid Build Coastguard Worker       // We need to guard some of the invocation interface's calls: a bad caller might
609*795d594fSAndroid Build Coastguard Worker       // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
610*795d594fSAndroid Build Coastguard Worker       Thread* self = Thread::Current();
611*795d594fSAndroid Build Coastguard Worker       if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
612*795d594fSAndroid Build Coastguard Worker         ScopedObjectAccess soa(self);
613*795d594fSAndroid Build Coastguard Worker         ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
614*795d594fSAndroid Build Coastguard Worker         should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
615*795d594fSAndroid Build Coastguard Worker       }
616*795d594fSAndroid Build Coastguard Worker     }
617*795d594fSAndroid Build Coastguard Worker     if (should_trace) {
618*795d594fSAndroid Build Coastguard Worker       std::string msg;
619*795d594fSAndroid Build Coastguard Worker       for (size_t i = 0; fmt[i] != '\0'; ++i) {
620*795d594fSAndroid Build Coastguard Worker         TraceNonHeapValue(fmt[i], args[i], &msg);
621*795d594fSAndroid Build Coastguard Worker         if (fmt[i + 1] != '\0') {
622*795d594fSAndroid Build Coastguard Worker           StringAppendF(&msg, ", ");
623*795d594fSAndroid Build Coastguard Worker         }
624*795d594fSAndroid Build Coastguard Worker       }
625*795d594fSAndroid Build Coastguard Worker 
626*795d594fSAndroid Build Coastguard Worker       if ((flags_ & kFlag_ForceTrace) != 0) {
627*795d594fSAndroid Build Coastguard Worker         LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
628*795d594fSAndroid Build Coastguard Worker       } else if (entry) {
629*795d594fSAndroid Build Coastguard Worker         if (has_method_) {
630*795d594fSAndroid Build Coastguard Worker           Thread* self = Thread::Current();
631*795d594fSAndroid Build Coastguard Worker           ScopedObjectAccess soa(self);
632*795d594fSAndroid Build Coastguard Worker           ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
633*795d594fSAndroid Build Coastguard Worker           std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
634*795d594fSAndroid Build Coastguard Worker           LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
635*795d594fSAndroid Build Coastguard Worker           indent_ = methodName.size() + 1;
636*795d594fSAndroid Build Coastguard Worker         } else {
637*795d594fSAndroid Build Coastguard Worker           LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
638*795d594fSAndroid Build Coastguard Worker           indent_ = 0;
639*795d594fSAndroid Build Coastguard Worker         }
640*795d594fSAndroid Build Coastguard Worker       } else {
641*795d594fSAndroid Build Coastguard Worker         LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
642*795d594fSAndroid Build Coastguard Worker       }
643*795d594fSAndroid Build Coastguard Worker     }
644*795d594fSAndroid Build Coastguard Worker 
645*795d594fSAndroid Build Coastguard Worker     // We always do the thorough checks on entry, and never on exit...
646*795d594fSAndroid Build Coastguard Worker     if (entry) {
647*795d594fSAndroid Build Coastguard Worker       for (size_t i = 0; fmt[i] != '\0'; ++i) {
648*795d594fSAndroid Build Coastguard Worker         if (!CheckNonHeapValue(fmt[i], args[i])) {
649*795d594fSAndroid Build Coastguard Worker           return false;
650*795d594fSAndroid Build Coastguard Worker         }
651*795d594fSAndroid Build Coastguard Worker       }
652*795d594fSAndroid Build Coastguard Worker     }
653*795d594fSAndroid Build Coastguard Worker     return true;
654*795d594fSAndroid Build Coastguard Worker   }
655*795d594fSAndroid Build Coastguard Worker 
CheckReflectedMethod(ScopedObjectAccess & soa,jobject jmethod)656*795d594fSAndroid Build Coastguard Worker   bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
657*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
658*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Object> method = soa.Decode<mirror::Object>(jmethod);
659*795d594fSAndroid Build Coastguard Worker     if (method == nullptr) {
660*795d594fSAndroid Build Coastguard Worker       AbortF("expected non-null method");
661*795d594fSAndroid Build Coastguard Worker       return false;
662*795d594fSAndroid Build Coastguard Worker     }
663*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
664*795d594fSAndroid Build Coastguard Worker         Runtime::Current()->GetClassLinker()->GetClassRoots();
665*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Class> c = method->GetClass();
666*795d594fSAndroid Build Coastguard Worker     if (c != GetClassRoot<mirror::Method>(class_roots) &&
667*795d594fSAndroid Build Coastguard Worker         c != GetClassRoot<mirror::Constructor>(class_roots)) {
668*795d594fSAndroid Build Coastguard Worker       AbortF("expected java.lang.reflect.Method or "
669*795d594fSAndroid Build Coastguard Worker           "java.lang.reflect.Constructor but got object of type %s: %p",
670*795d594fSAndroid Build Coastguard Worker           method->PrettyTypeOf().c_str(), jmethod);
671*795d594fSAndroid Build Coastguard Worker       return false;
672*795d594fSAndroid Build Coastguard Worker     }
673*795d594fSAndroid Build Coastguard Worker     return true;
674*795d594fSAndroid Build Coastguard Worker   }
675*795d594fSAndroid Build Coastguard Worker 
CheckConstructor(jmethodID mid)676*795d594fSAndroid Build Coastguard Worker   bool CheckConstructor(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
677*795d594fSAndroid Build Coastguard Worker     ArtMethod* method = jni::DecodeArtMethod(mid);
678*795d594fSAndroid Build Coastguard Worker     if (method == nullptr) {
679*795d594fSAndroid Build Coastguard Worker       AbortF("expected non-null constructor");
680*795d594fSAndroid Build Coastguard Worker       return false;
681*795d594fSAndroid Build Coastguard Worker     }
682*795d594fSAndroid Build Coastguard Worker     if (!method->IsConstructor() || method->IsStatic()) {
683*795d594fSAndroid Build Coastguard Worker       AbortF("expected a constructor but %s: %p", method->PrettyMethod().c_str(), mid);
684*795d594fSAndroid Build Coastguard Worker       return false;
685*795d594fSAndroid Build Coastguard Worker     }
686*795d594fSAndroid Build Coastguard Worker     return true;
687*795d594fSAndroid Build Coastguard Worker   }
688*795d594fSAndroid Build Coastguard Worker 
CheckReflectedField(ScopedObjectAccess & soa,jobject jfield)689*795d594fSAndroid Build Coastguard Worker   bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
690*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
691*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Object> field = soa.Decode<mirror::Object>(jfield);
692*795d594fSAndroid Build Coastguard Worker     if (field == nullptr) {
693*795d594fSAndroid Build Coastguard Worker       AbortF("expected non-null java.lang.reflect.Field");
694*795d594fSAndroid Build Coastguard Worker       return false;
695*795d594fSAndroid Build Coastguard Worker     }
696*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Class> c = field->GetClass();
697*795d594fSAndroid Build Coastguard Worker     if (GetClassRoot<mirror::Field>() != c) {
698*795d594fSAndroid Build Coastguard Worker       AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
699*795d594fSAndroid Build Coastguard Worker              field->PrettyTypeOf().c_str(), jfield);
700*795d594fSAndroid Build Coastguard Worker       return false;
701*795d594fSAndroid Build Coastguard Worker     }
702*795d594fSAndroid Build Coastguard Worker     return true;
703*795d594fSAndroid Build Coastguard Worker   }
704*795d594fSAndroid Build Coastguard Worker 
CheckThrowable(ScopedObjectAccess & soa,jthrowable jobj)705*795d594fSAndroid Build Coastguard Worker   bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
706*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
707*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
708*795d594fSAndroid Build Coastguard Worker     if (!obj->GetClass()->IsThrowableClass()) {
709*795d594fSAndroid Build Coastguard Worker       AbortF("expected java.lang.Throwable but got object of type "
710*795d594fSAndroid Build Coastguard Worker              "%s: %p", obj->PrettyTypeOf().c_str(), obj.Ptr());
711*795d594fSAndroid Build Coastguard Worker       return false;
712*795d594fSAndroid Build Coastguard Worker     }
713*795d594fSAndroid Build Coastguard Worker     return true;
714*795d594fSAndroid Build Coastguard Worker   }
715*795d594fSAndroid Build Coastguard Worker 
CheckThrowableClass(ScopedObjectAccess & soa,jclass jc)716*795d594fSAndroid Build Coastguard Worker   bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
717*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
718*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
719*795d594fSAndroid Build Coastguard Worker     if (!c->IsThrowableClass()) {
720*795d594fSAndroid Build Coastguard Worker       AbortF("expected java.lang.Throwable class but got object of "
721*795d594fSAndroid Build Coastguard Worker              "type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
722*795d594fSAndroid Build Coastguard Worker       return false;
723*795d594fSAndroid Build Coastguard Worker     }
724*795d594fSAndroid Build Coastguard Worker     return true;
725*795d594fSAndroid Build Coastguard Worker   }
726*795d594fSAndroid Build Coastguard Worker 
CheckReferenceKind(IndirectRefKind expected_kind,Thread * self,jobject obj)727*795d594fSAndroid Build Coastguard Worker   bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj)
728*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
729*795d594fSAndroid Build Coastguard Worker     IndirectRefKind found_kind;
730*795d594fSAndroid Build Coastguard Worker     if (expected_kind == kLocal) {
731*795d594fSAndroid Build Coastguard Worker       found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
732*795d594fSAndroid Build Coastguard Worker       if (found_kind == kJniTransition &&
733*795d594fSAndroid Build Coastguard Worker           obj != nullptr &&
734*795d594fSAndroid Build Coastguard Worker           self->IsJniTransitionReference(obj)) {
735*795d594fSAndroid Build Coastguard Worker         found_kind = kLocal;
736*795d594fSAndroid Build Coastguard Worker       }
737*795d594fSAndroid Build Coastguard Worker     } else {
738*795d594fSAndroid Build Coastguard Worker       found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
739*795d594fSAndroid Build Coastguard Worker     }
740*795d594fSAndroid Build Coastguard Worker     if (obj != nullptr && found_kind != expected_kind) {
741*795d594fSAndroid Build Coastguard Worker       AbortF("expected reference of kind %s but found %s: %p",
742*795d594fSAndroid Build Coastguard Worker              GetIndirectRefKindString(expected_kind),
743*795d594fSAndroid Build Coastguard Worker              GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(obj)),
744*795d594fSAndroid Build Coastguard Worker              obj);
745*795d594fSAndroid Build Coastguard Worker       return false;
746*795d594fSAndroid Build Coastguard Worker     }
747*795d594fSAndroid Build Coastguard Worker     return true;
748*795d594fSAndroid Build Coastguard Worker   }
749*795d594fSAndroid Build Coastguard Worker 
CheckInstantiableNonArray(ScopedObjectAccess & soa,jclass jc)750*795d594fSAndroid Build Coastguard Worker   bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
751*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
752*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
753*795d594fSAndroid Build Coastguard Worker     if (!c->IsInstantiableNonArray()) {
754*795d594fSAndroid Build Coastguard Worker       AbortF("can't make objects of type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
755*795d594fSAndroid Build Coastguard Worker       return false;
756*795d594fSAndroid Build Coastguard Worker     }
757*795d594fSAndroid Build Coastguard Worker     return true;
758*795d594fSAndroid Build Coastguard Worker   }
759*795d594fSAndroid Build Coastguard Worker 
CheckPrimitiveArrayType(ScopedObjectAccess & soa,jarray array,Primitive::Type type)760*795d594fSAndroid Build Coastguard Worker   bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
761*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
762*795d594fSAndroid Build Coastguard Worker     if (!CheckArray(soa, array)) {
763*795d594fSAndroid Build Coastguard Worker       return false;
764*795d594fSAndroid Build Coastguard Worker     }
765*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(array);
766*795d594fSAndroid Build Coastguard Worker     if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
767*795d594fSAndroid Build Coastguard Worker       AbortF("incompatible array type %s expected %s[]: %p",
768*795d594fSAndroid Build Coastguard Worker              a->GetClass()->PrettyDescriptor().c_str(), PrettyDescriptor(type).c_str(), array);
769*795d594fSAndroid Build Coastguard Worker       return false;
770*795d594fSAndroid Build Coastguard Worker     }
771*795d594fSAndroid Build Coastguard Worker     return true;
772*795d594fSAndroid Build Coastguard Worker   }
773*795d594fSAndroid Build Coastguard Worker 
CheckFieldAccess(ScopedObjectAccess & soa,jobject obj,jfieldID fid,bool is_static,Primitive::Type type)774*795d594fSAndroid Build Coastguard Worker   bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
775*795d594fSAndroid Build Coastguard Worker                         Primitive::Type type)
776*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
777*795d594fSAndroid Build Coastguard Worker     if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
778*795d594fSAndroid Build Coastguard Worker       return false;
779*795d594fSAndroid Build Coastguard Worker     }
780*795d594fSAndroid Build Coastguard Worker     if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
781*795d594fSAndroid Build Coastguard Worker       return false;
782*795d594fSAndroid Build Coastguard Worker     }
783*795d594fSAndroid Build Coastguard Worker     ArtField* field = jni::DecodeArtField(fid);
784*795d594fSAndroid Build Coastguard Worker     DCHECK(field != nullptr);  // Already checked by Check.
785*795d594fSAndroid Build Coastguard Worker     if (is_static != field->IsStatic()) {
786*795d594fSAndroid Build Coastguard Worker       AbortF("attempt to access %s field %s: %p",
787*795d594fSAndroid Build Coastguard Worker              field->IsStatic() ? "static" : "non-static", field->PrettyField().c_str(), fid);
788*795d594fSAndroid Build Coastguard Worker       return false;
789*795d594fSAndroid Build Coastguard Worker     }
790*795d594fSAndroid Build Coastguard Worker     if (type != field->GetTypeAsPrimitiveType()) {
791*795d594fSAndroid Build Coastguard Worker       AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
792*795d594fSAndroid Build Coastguard Worker              field->PrettyField().c_str(),
793*795d594fSAndroid Build Coastguard Worker              PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
794*795d594fSAndroid Build Coastguard Worker              PrettyDescriptor(type).c_str(), fid);
795*795d594fSAndroid Build Coastguard Worker       return false;
796*795d594fSAndroid Build Coastguard Worker     }
797*795d594fSAndroid Build Coastguard Worker     if (is_static) {
798*795d594fSAndroid Build Coastguard Worker       ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
799*795d594fSAndroid Build Coastguard Worker       if (o == nullptr || !o->IsClass()) {
800*795d594fSAndroid Build Coastguard Worker         AbortF("attempt to access static field %s with a class argument of type %s: %p",
801*795d594fSAndroid Build Coastguard Worker                field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
802*795d594fSAndroid Build Coastguard Worker         return false;
803*795d594fSAndroid Build Coastguard Worker       }
804*795d594fSAndroid Build Coastguard Worker       ObjPtr<mirror::Class> c = o->AsClass();
805*795d594fSAndroid Build Coastguard Worker       if (!field->GetDeclaringClass()->IsAssignableFrom(c)) {
806*795d594fSAndroid Build Coastguard Worker         AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
807*795d594fSAndroid Build Coastguard Worker                field->PrettyField().c_str(), mirror::Class::PrettyDescriptor(c).c_str(), fid);
808*795d594fSAndroid Build Coastguard Worker         return false;
809*795d594fSAndroid Build Coastguard Worker       }
810*795d594fSAndroid Build Coastguard Worker     } else {
811*795d594fSAndroid Build Coastguard Worker       ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
812*795d594fSAndroid Build Coastguard Worker       if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
813*795d594fSAndroid Build Coastguard Worker         AbortF("attempt to access field %s from an object argument of type %s: %p",
814*795d594fSAndroid Build Coastguard Worker                field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
815*795d594fSAndroid Build Coastguard Worker         return false;
816*795d594fSAndroid Build Coastguard Worker       }
817*795d594fSAndroid Build Coastguard Worker     }
818*795d594fSAndroid Build Coastguard Worker     return true;
819*795d594fSAndroid Build Coastguard Worker   }
820*795d594fSAndroid Build Coastguard Worker 
821*795d594fSAndroid Build Coastguard Worker  private:
822*795d594fSAndroid Build Coastguard Worker   enum InstanceKind {
823*795d594fSAndroid Build Coastguard Worker     kClass,
824*795d594fSAndroid Build Coastguard Worker     kDirectByteBuffer,
825*795d594fSAndroid Build Coastguard Worker     kObject,
826*795d594fSAndroid Build Coastguard Worker     kString,
827*795d594fSAndroid Build Coastguard Worker     kThrowable,
828*795d594fSAndroid Build Coastguard Worker   };
829*795d594fSAndroid Build Coastguard Worker 
830*795d594fSAndroid Build Coastguard Worker   /*
831*795d594fSAndroid Build Coastguard Worker    * Verify that "jobj" is a valid non-null object reference, and points to
832*795d594fSAndroid Build Coastguard Worker    * an instance of expectedClass.
833*795d594fSAndroid Build Coastguard Worker    *
834*795d594fSAndroid Build Coastguard Worker    * Because we're looking at an object on the GC heap, we have to switch
835*795d594fSAndroid Build Coastguard Worker    * to "running" mode before doing the checks.
836*795d594fSAndroid Build Coastguard Worker    */
CheckInstance(ScopedObjectAccess & soa,InstanceKind kind,jobject java_object,bool null_ok)837*795d594fSAndroid Build Coastguard Worker   bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
838*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
839*795d594fSAndroid Build Coastguard Worker     const char* what = nullptr;
840*795d594fSAndroid Build Coastguard Worker     switch (kind) {
841*795d594fSAndroid Build Coastguard Worker     case kClass:
842*795d594fSAndroid Build Coastguard Worker       what = "jclass";
843*795d594fSAndroid Build Coastguard Worker       break;
844*795d594fSAndroid Build Coastguard Worker     case kDirectByteBuffer:
845*795d594fSAndroid Build Coastguard Worker       what = "direct ByteBuffer";
846*795d594fSAndroid Build Coastguard Worker       break;
847*795d594fSAndroid Build Coastguard Worker     case kObject:
848*795d594fSAndroid Build Coastguard Worker       what = "jobject";
849*795d594fSAndroid Build Coastguard Worker       break;
850*795d594fSAndroid Build Coastguard Worker     case kString:
851*795d594fSAndroid Build Coastguard Worker       what = "jstring";
852*795d594fSAndroid Build Coastguard Worker       break;
853*795d594fSAndroid Build Coastguard Worker     case kThrowable:
854*795d594fSAndroid Build Coastguard Worker       what = "jthrowable";
855*795d594fSAndroid Build Coastguard Worker       break;
856*795d594fSAndroid Build Coastguard Worker     }
857*795d594fSAndroid Build Coastguard Worker 
858*795d594fSAndroid Build Coastguard Worker     if (java_object == nullptr) {
859*795d594fSAndroid Build Coastguard Worker       if (null_ok) {
860*795d594fSAndroid Build Coastguard Worker         return true;
861*795d594fSAndroid Build Coastguard Worker       } else {
862*795d594fSAndroid Build Coastguard Worker         AbortF("%s received NULL %s", function_name_, what);
863*795d594fSAndroid Build Coastguard Worker         return false;
864*795d594fSAndroid Build Coastguard Worker       }
865*795d594fSAndroid Build Coastguard Worker     }
866*795d594fSAndroid Build Coastguard Worker 
867*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Object> obj = nullptr;
868*795d594fSAndroid Build Coastguard Worker     IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
869*795d594fSAndroid Build Coastguard Worker     IndirectRefKind ref_kind = IndirectReferenceTable::GetIndirectRefKind(ref);
870*795d594fSAndroid Build Coastguard Worker     bool expect_null = false;
871*795d594fSAndroid Build Coastguard Worker     bool okay = true;
872*795d594fSAndroid Build Coastguard Worker     std::string error_msg;
873*795d594fSAndroid Build Coastguard Worker     if (ref_kind == kJniTransition) {
874*795d594fSAndroid Build Coastguard Worker       if (!soa.Self()->IsJniTransitionReference(java_object)) {
875*795d594fSAndroid Build Coastguard Worker         okay = false;
876*795d594fSAndroid Build Coastguard Worker         error_msg = "use of invalid jobject";
877*795d594fSAndroid Build Coastguard Worker       } else {
878*795d594fSAndroid Build Coastguard Worker         obj = soa.Decode<mirror::Object>(java_object);
879*795d594fSAndroid Build Coastguard Worker       }
880*795d594fSAndroid Build Coastguard Worker     } else if (ref_kind == kLocal) {
881*795d594fSAndroid Build Coastguard Worker       jni::LocalReferenceTable* lrt = GetLocalReferenceTable(soa);
882*795d594fSAndroid Build Coastguard Worker       okay = lrt->IsValidReference(java_object, &error_msg);
883*795d594fSAndroid Build Coastguard Worker       if (okay) {
884*795d594fSAndroid Build Coastguard Worker         obj = lrt->Get(ref);
885*795d594fSAndroid Build Coastguard Worker       }
886*795d594fSAndroid Build Coastguard Worker     } else {
887*795d594fSAndroid Build Coastguard Worker       IndirectReferenceTable* irt = GetIndirectReferenceTable(soa, ref_kind);
888*795d594fSAndroid Build Coastguard Worker       okay = irt->IsValidReference(java_object, &error_msg);
889*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(okay, error_msg.empty());
890*795d594fSAndroid Build Coastguard Worker       if (okay) {
891*795d594fSAndroid Build Coastguard Worker         // Note: The `IsValidReference()` checks for null but we do not prevent races,
892*795d594fSAndroid Build Coastguard Worker         // so the null check below can still fail. Even if it succeeds, another thread
893*795d594fSAndroid Build Coastguard Worker         // could delete the global or weak global before it's used by JNI.
894*795d594fSAndroid Build Coastguard Worker         if (ref_kind == kGlobal) {
895*795d594fSAndroid Build Coastguard Worker           obj = soa.Env()->GetVm()->DecodeGlobal(ref);
896*795d594fSAndroid Build Coastguard Worker         } else {
897*795d594fSAndroid Build Coastguard Worker           obj = soa.Env()->GetVm()->DecodeWeakGlobal(soa.Self(), ref);
898*795d594fSAndroid Build Coastguard Worker           if (Runtime::Current()->IsClearedJniWeakGlobal(obj)) {
899*795d594fSAndroid Build Coastguard Worker             obj = nullptr;
900*795d594fSAndroid Build Coastguard Worker             expect_null = true;
901*795d594fSAndroid Build Coastguard Worker           }
902*795d594fSAndroid Build Coastguard Worker         }
903*795d594fSAndroid Build Coastguard Worker       }
904*795d594fSAndroid Build Coastguard Worker     }
905*795d594fSAndroid Build Coastguard Worker     if (okay) {
906*795d594fSAndroid Build Coastguard Worker       if (!expect_null && obj == nullptr) {
907*795d594fSAndroid Build Coastguard Worker         okay = false;
908*795d594fSAndroid Build Coastguard Worker         error_msg = "deleted reference";
909*795d594fSAndroid Build Coastguard Worker       }
910*795d594fSAndroid Build Coastguard Worker       if (expect_null && !null_ok) {
911*795d594fSAndroid Build Coastguard Worker         okay = false;
912*795d594fSAndroid Build Coastguard Worker         error_msg = "cleared weak reference";
913*795d594fSAndroid Build Coastguard Worker       }
914*795d594fSAndroid Build Coastguard Worker     }
915*795d594fSAndroid Build Coastguard Worker     if (!okay) {
916*795d594fSAndroid Build Coastguard Worker       AbortF("JNI ERROR (app bug): %s is an invalid %s: %p (%s)",
917*795d594fSAndroid Build Coastguard Worker              what,
918*795d594fSAndroid Build Coastguard Worker              ToStr<IndirectRefKind>(ref_kind).c_str(),
919*795d594fSAndroid Build Coastguard Worker              java_object,
920*795d594fSAndroid Build Coastguard Worker              error_msg.c_str());
921*795d594fSAndroid Build Coastguard Worker       return false;
922*795d594fSAndroid Build Coastguard Worker     }
923*795d594fSAndroid Build Coastguard Worker 
924*795d594fSAndroid Build Coastguard Worker     if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj.Ptr())) {
925*795d594fSAndroid Build Coastguard Worker       Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
926*795d594fSAndroid Build Coastguard Worker       AbortF("%s is an invalid %s: %p (%p)",
927*795d594fSAndroid Build Coastguard Worker              what,
928*795d594fSAndroid Build Coastguard Worker              GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
929*795d594fSAndroid Build Coastguard Worker              java_object,
930*795d594fSAndroid Build Coastguard Worker              obj.Ptr());
931*795d594fSAndroid Build Coastguard Worker       return false;
932*795d594fSAndroid Build Coastguard Worker     }
933*795d594fSAndroid Build Coastguard Worker 
934*795d594fSAndroid Build Coastguard Worker     switch (kind) {
935*795d594fSAndroid Build Coastguard Worker     case kClass:
936*795d594fSAndroid Build Coastguard Worker       okay = obj->IsClass();
937*795d594fSAndroid Build Coastguard Worker       break;
938*795d594fSAndroid Build Coastguard Worker     case kDirectByteBuffer:
939*795d594fSAndroid Build Coastguard Worker       UNIMPLEMENTED(FATAL);
940*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
941*795d594fSAndroid Build Coastguard Worker     case kString:
942*795d594fSAndroid Build Coastguard Worker       okay = obj->GetClass()->IsStringClass();
943*795d594fSAndroid Build Coastguard Worker       break;
944*795d594fSAndroid Build Coastguard Worker     case kThrowable:
945*795d594fSAndroid Build Coastguard Worker       okay = obj->GetClass()->IsThrowableClass();
946*795d594fSAndroid Build Coastguard Worker       break;
947*795d594fSAndroid Build Coastguard Worker     case kObject:
948*795d594fSAndroid Build Coastguard Worker       break;
949*795d594fSAndroid Build Coastguard Worker     }
950*795d594fSAndroid Build Coastguard Worker     if (!okay) {
951*795d594fSAndroid Build Coastguard Worker       AbortF("%s has wrong type: %s", what, mirror::Object::PrettyTypeOf(obj).c_str());
952*795d594fSAndroid Build Coastguard Worker       return false;
953*795d594fSAndroid Build Coastguard Worker     }
954*795d594fSAndroid Build Coastguard Worker 
955*795d594fSAndroid Build Coastguard Worker     return true;
956*795d594fSAndroid Build Coastguard Worker   }
957*795d594fSAndroid Build Coastguard Worker 
958*795d594fSAndroid Build Coastguard Worker   /*
959*795d594fSAndroid Build Coastguard Worker    * Verify that the "mode" argument passed to a primitive array Release
960*795d594fSAndroid Build Coastguard Worker    * function is one of the valid values.
961*795d594fSAndroid Build Coastguard Worker    */
CheckReleaseMode(jint mode)962*795d594fSAndroid Build Coastguard Worker   bool CheckReleaseMode(jint mode) {
963*795d594fSAndroid Build Coastguard Worker     if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
964*795d594fSAndroid Build Coastguard Worker       AbortF("unknown value for release mode: %d", mode);
965*795d594fSAndroid Build Coastguard Worker       return false;
966*795d594fSAndroid Build Coastguard Worker     }
967*795d594fSAndroid Build Coastguard Worker     return true;
968*795d594fSAndroid Build Coastguard Worker   }
969*795d594fSAndroid Build Coastguard Worker 
CheckPossibleHeapValue(ScopedObjectAccess & soa,char fmt,JniValueType arg)970*795d594fSAndroid Build Coastguard Worker   bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
971*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
972*795d594fSAndroid Build Coastguard Worker     switch (fmt) {
973*795d594fSAndroid Build Coastguard Worker       case 'a':  // jarray
974*795d594fSAndroid Build Coastguard Worker         return CheckArray(soa, arg.a);
975*795d594fSAndroid Build Coastguard Worker       case 'c':  // jclass
976*795d594fSAndroid Build Coastguard Worker         return CheckInstance(soa, kClass, arg.c, false);
977*795d594fSAndroid Build Coastguard Worker       case 'f':  // jfieldID
978*795d594fSAndroid Build Coastguard Worker         return CheckFieldID(arg.f) != nullptr;
979*795d594fSAndroid Build Coastguard Worker       case 'm':  // jmethodID
980*795d594fSAndroid Build Coastguard Worker         return CheckMethodID(arg.m) != nullptr;
981*795d594fSAndroid Build Coastguard Worker       case 'r':  // release int
982*795d594fSAndroid Build Coastguard Worker         return CheckReleaseMode(arg.r);
983*795d594fSAndroid Build Coastguard Worker       case 's':  // jstring
984*795d594fSAndroid Build Coastguard Worker         return CheckInstance(soa, kString, arg.s, false);
985*795d594fSAndroid Build Coastguard Worker       case 't':  // jthrowable
986*795d594fSAndroid Build Coastguard Worker         return CheckInstance(soa, kThrowable, arg.t, false);
987*795d594fSAndroid Build Coastguard Worker       case 'E':  // JNIEnv*
988*795d594fSAndroid Build Coastguard Worker         return CheckThread(arg.E);
989*795d594fSAndroid Build Coastguard Worker       case 'L':  // jobject
990*795d594fSAndroid Build Coastguard Worker         return CheckInstance(soa, kObject, arg.L, true);
991*795d594fSAndroid Build Coastguard Worker       case '.':  // A VarArgs list
992*795d594fSAndroid Build Coastguard Worker         return CheckVarArgs(soa, arg.va);
993*795d594fSAndroid Build Coastguard Worker       default:
994*795d594fSAndroid Build Coastguard Worker         return CheckNonHeapValue(fmt, arg);
995*795d594fSAndroid Build Coastguard Worker     }
996*795d594fSAndroid Build Coastguard Worker   }
997*795d594fSAndroid Build Coastguard Worker 
CheckVarArgs(ScopedObjectAccess & soa,const VarArgs * args_p)998*795d594fSAndroid Build Coastguard Worker   bool CheckVarArgs(ScopedObjectAccess& soa, const VarArgs* args_p)
999*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
1000*795d594fSAndroid Build Coastguard Worker     CHECK(args_p != nullptr);
1001*795d594fSAndroid Build Coastguard Worker     VarArgs args(args_p->Clone());
1002*795d594fSAndroid Build Coastguard Worker     ArtMethod* m = CheckMethodID(args.GetMethodID());
1003*795d594fSAndroid Build Coastguard Worker     if (m == nullptr) {
1004*795d594fSAndroid Build Coastguard Worker       return false;
1005*795d594fSAndroid Build Coastguard Worker     }
1006*795d594fSAndroid Build Coastguard Worker     uint32_t len = 0;
1007*795d594fSAndroid Build Coastguard Worker     const char* shorty = m->GetShorty(&len);
1008*795d594fSAndroid Build Coastguard Worker     // Skip the return type
1009*795d594fSAndroid Build Coastguard Worker     CHECK_GE(len, 1u);
1010*795d594fSAndroid Build Coastguard Worker     len--;
1011*795d594fSAndroid Build Coastguard Worker     shorty++;
1012*795d594fSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < len; i++) {
1013*795d594fSAndroid Build Coastguard Worker       if (!CheckPossibleHeapValue(soa, shorty[i], args.GetValue(shorty[i]))) {
1014*795d594fSAndroid Build Coastguard Worker         return false;
1015*795d594fSAndroid Build Coastguard Worker       }
1016*795d594fSAndroid Build Coastguard Worker     }
1017*795d594fSAndroid Build Coastguard Worker     return true;
1018*795d594fSAndroid Build Coastguard Worker   }
1019*795d594fSAndroid Build Coastguard Worker 
CheckNonHeapValue(char fmt,JniValueType arg)1020*795d594fSAndroid Build Coastguard Worker   bool CheckNonHeapValue(char fmt, JniValueType arg) {
1021*795d594fSAndroid Build Coastguard Worker     switch (fmt) {
1022*795d594fSAndroid Build Coastguard Worker       case 'p':  // TODO: pointer - null or readable?
1023*795d594fSAndroid Build Coastguard Worker       case 'v':  // JavaVM*
1024*795d594fSAndroid Build Coastguard Worker       case 'D':  // jdouble
1025*795d594fSAndroid Build Coastguard Worker       case 'F':  // jfloat
1026*795d594fSAndroid Build Coastguard Worker       case 'J':  // jlong
1027*795d594fSAndroid Build Coastguard Worker       case 'I':  // jint
1028*795d594fSAndroid Build Coastguard Worker         break;  // Ignored.
1029*795d594fSAndroid Build Coastguard Worker       case 'b':  // jboolean, why two? Fall-through.
1030*795d594fSAndroid Build Coastguard Worker       case 'Z':
1031*795d594fSAndroid Build Coastguard Worker         return CheckBoolean(arg.I);
1032*795d594fSAndroid Build Coastguard Worker       case 'B':  // jbyte
1033*795d594fSAndroid Build Coastguard Worker         return CheckByte(arg.I);
1034*795d594fSAndroid Build Coastguard Worker       case 'C':  // jchar
1035*795d594fSAndroid Build Coastguard Worker         return CheckChar(arg.I);
1036*795d594fSAndroid Build Coastguard Worker       case 'S':  // jshort
1037*795d594fSAndroid Build Coastguard Worker         return CheckShort(arg.I);
1038*795d594fSAndroid Build Coastguard Worker       case 'u':  // utf8
1039*795d594fSAndroid Build Coastguard Worker         if ((flags_ & kFlag_Release) != 0) {
1040*795d594fSAndroid Build Coastguard Worker           return CheckNonNull(arg.u);
1041*795d594fSAndroid Build Coastguard Worker         } else {
1042*795d594fSAndroid Build Coastguard Worker           bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
1043*795d594fSAndroid Build Coastguard Worker           return CheckUtfString(arg.u, nullable);
1044*795d594fSAndroid Build Coastguard Worker         }
1045*795d594fSAndroid Build Coastguard Worker       case 'w':  // jobjectRefType
1046*795d594fSAndroid Build Coastguard Worker         switch (arg.w) {
1047*795d594fSAndroid Build Coastguard Worker           case JNIInvalidRefType:
1048*795d594fSAndroid Build Coastguard Worker           case JNILocalRefType:
1049*795d594fSAndroid Build Coastguard Worker           case JNIGlobalRefType:
1050*795d594fSAndroid Build Coastguard Worker           case JNIWeakGlobalRefType:
1051*795d594fSAndroid Build Coastguard Worker             break;
1052*795d594fSAndroid Build Coastguard Worker           default:
1053*795d594fSAndroid Build Coastguard Worker             AbortF("Unknown reference type");
1054*795d594fSAndroid Build Coastguard Worker             return false;
1055*795d594fSAndroid Build Coastguard Worker         }
1056*795d594fSAndroid Build Coastguard Worker         break;
1057*795d594fSAndroid Build Coastguard Worker       case 'z':  // jsize
1058*795d594fSAndroid Build Coastguard Worker         return CheckLengthPositive(arg.z);
1059*795d594fSAndroid Build Coastguard Worker       default:
1060*795d594fSAndroid Build Coastguard Worker         AbortF("unknown format specifier: '%c'", fmt);
1061*795d594fSAndroid Build Coastguard Worker         return false;
1062*795d594fSAndroid Build Coastguard Worker     }
1063*795d594fSAndroid Build Coastguard Worker     return true;
1064*795d594fSAndroid Build Coastguard Worker   }
1065*795d594fSAndroid Build Coastguard Worker 
TracePossibleHeapValue(ScopedObjectAccess & soa,bool entry,char fmt,JniValueType arg,std::string * msg)1066*795d594fSAndroid Build Coastguard Worker   void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
1067*795d594fSAndroid Build Coastguard Worker                               std::string* msg)
1068*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
1069*795d594fSAndroid Build Coastguard Worker     switch (fmt) {
1070*795d594fSAndroid Build Coastguard Worker       case 'L':  // jobject fall-through.
1071*795d594fSAndroid Build Coastguard Worker       case 'a':  // jarray fall-through.
1072*795d594fSAndroid Build Coastguard Worker       case 's':  // jstring fall-through.
1073*795d594fSAndroid Build Coastguard Worker       case 't':  // jthrowable fall-through.
1074*795d594fSAndroid Build Coastguard Worker         if (arg.L == nullptr) {
1075*795d594fSAndroid Build Coastguard Worker           *msg += "NULL";
1076*795d594fSAndroid Build Coastguard Worker         } else {
1077*795d594fSAndroid Build Coastguard Worker           StringAppendF(msg, "%p", arg.L);
1078*795d594fSAndroid Build Coastguard Worker         }
1079*795d594fSAndroid Build Coastguard Worker         break;
1080*795d594fSAndroid Build Coastguard Worker       case 'c': {  // jclass
1081*795d594fSAndroid Build Coastguard Worker         jclass jc = arg.c;
1082*795d594fSAndroid Build Coastguard Worker         ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
1083*795d594fSAndroid Build Coastguard Worker         if (c == nullptr) {
1084*795d594fSAndroid Build Coastguard Worker           *msg += "NULL";
1085*795d594fSAndroid Build Coastguard Worker         } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c.Ptr())) {
1086*795d594fSAndroid Build Coastguard Worker           StringAppendF(msg, "INVALID POINTER:%p", jc);
1087*795d594fSAndroid Build Coastguard Worker         } else if (!c->IsClass()) {
1088*795d594fSAndroid Build Coastguard Worker           *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + c->PrettyTypeOf();
1089*795d594fSAndroid Build Coastguard Worker         } else {
1090*795d594fSAndroid Build Coastguard Worker           *msg += c->PrettyClass();
1091*795d594fSAndroid Build Coastguard Worker           if (!entry) {
1092*795d594fSAndroid Build Coastguard Worker             StringAppendF(msg, " (%p)", jc);
1093*795d594fSAndroid Build Coastguard Worker           }
1094*795d594fSAndroid Build Coastguard Worker         }
1095*795d594fSAndroid Build Coastguard Worker         break;
1096*795d594fSAndroid Build Coastguard Worker       }
1097*795d594fSAndroid Build Coastguard Worker       case 'f': {  // jfieldID
1098*795d594fSAndroid Build Coastguard Worker         jfieldID fid = arg.f;
1099*795d594fSAndroid Build Coastguard Worker         ArtField* f = jni::DecodeArtField(fid);
1100*795d594fSAndroid Build Coastguard Worker         *msg += ArtField::PrettyField(f);
1101*795d594fSAndroid Build Coastguard Worker         if (!entry) {
1102*795d594fSAndroid Build Coastguard Worker           StringAppendF(msg, " (%p)", fid);
1103*795d594fSAndroid Build Coastguard Worker         }
1104*795d594fSAndroid Build Coastguard Worker         break;
1105*795d594fSAndroid Build Coastguard Worker       }
1106*795d594fSAndroid Build Coastguard Worker       case 'm': {  // jmethodID
1107*795d594fSAndroid Build Coastguard Worker         jmethodID mid = arg.m;
1108*795d594fSAndroid Build Coastguard Worker         ArtMethod* m = jni::DecodeArtMethod(mid);
1109*795d594fSAndroid Build Coastguard Worker         *msg += ArtMethod::PrettyMethod(m);
1110*795d594fSAndroid Build Coastguard Worker         if (!entry) {
1111*795d594fSAndroid Build Coastguard Worker           StringAppendF(msg, " (%p)", mid);
1112*795d594fSAndroid Build Coastguard Worker         }
1113*795d594fSAndroid Build Coastguard Worker         break;
1114*795d594fSAndroid Build Coastguard Worker       }
1115*795d594fSAndroid Build Coastguard Worker       case '.': {
1116*795d594fSAndroid Build Coastguard Worker         const VarArgs* va = arg.va;
1117*795d594fSAndroid Build Coastguard Worker         VarArgs args(va->Clone());
1118*795d594fSAndroid Build Coastguard Worker         ArtMethod* m = jni::DecodeArtMethod(args.GetMethodID());
1119*795d594fSAndroid Build Coastguard Worker         uint32_t len;
1120*795d594fSAndroid Build Coastguard Worker         const char* shorty = m->GetShorty(&len);
1121*795d594fSAndroid Build Coastguard Worker         CHECK_GE(len, 1u);
1122*795d594fSAndroid Build Coastguard Worker         // Skip past return value.
1123*795d594fSAndroid Build Coastguard Worker         len--;
1124*795d594fSAndroid Build Coastguard Worker         shorty++;
1125*795d594fSAndroid Build Coastguard Worker         // Remove the previous ', ' from the message.
1126*795d594fSAndroid Build Coastguard Worker         msg->erase(msg->length() - 2);
1127*795d594fSAndroid Build Coastguard Worker         for (uint32_t i = 0; i < len; i++) {
1128*795d594fSAndroid Build Coastguard Worker           *msg += ", ";
1129*795d594fSAndroid Build Coastguard Worker           TracePossibleHeapValue(soa, entry, shorty[i], args.GetValue(shorty[i]), msg);
1130*795d594fSAndroid Build Coastguard Worker         }
1131*795d594fSAndroid Build Coastguard Worker         break;
1132*795d594fSAndroid Build Coastguard Worker       }
1133*795d594fSAndroid Build Coastguard Worker       default:
1134*795d594fSAndroid Build Coastguard Worker         TraceNonHeapValue(fmt, arg, msg);
1135*795d594fSAndroid Build Coastguard Worker         break;
1136*795d594fSAndroid Build Coastguard Worker     }
1137*795d594fSAndroid Build Coastguard Worker   }
1138*795d594fSAndroid Build Coastguard Worker 
TraceNonHeapValue(char fmt,JniValueType arg,std::string * msg)1139*795d594fSAndroid Build Coastguard Worker   void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
1140*795d594fSAndroid Build Coastguard Worker     switch (fmt) {
1141*795d594fSAndroid Build Coastguard Worker       case 'B':  // jbyte
1142*795d594fSAndroid Build Coastguard Worker         if (arg.B >= 0 && arg.B < 10) {
1143*795d594fSAndroid Build Coastguard Worker           StringAppendF(msg, "%d", arg.B);
1144*795d594fSAndroid Build Coastguard Worker         } else {
1145*795d594fSAndroid Build Coastguard Worker           StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
1146*795d594fSAndroid Build Coastguard Worker         }
1147*795d594fSAndroid Build Coastguard Worker         break;
1148*795d594fSAndroid Build Coastguard Worker       case 'C':  // jchar
1149*795d594fSAndroid Build Coastguard Worker         if (arg.C < 0x7f && arg.C >= ' ') {
1150*795d594fSAndroid Build Coastguard Worker           StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
1151*795d594fSAndroid Build Coastguard Worker         } else {
1152*795d594fSAndroid Build Coastguard Worker           StringAppendF(msg, "U+%x", arg.C);
1153*795d594fSAndroid Build Coastguard Worker         }
1154*795d594fSAndroid Build Coastguard Worker         break;
1155*795d594fSAndroid Build Coastguard Worker       case 'F':  // jfloat
1156*795d594fSAndroid Build Coastguard Worker         StringAppendF(msg, "%g", arg.F);
1157*795d594fSAndroid Build Coastguard Worker         break;
1158*795d594fSAndroid Build Coastguard Worker       case 'D':  // jdouble
1159*795d594fSAndroid Build Coastguard Worker         StringAppendF(msg, "%g", arg.D);
1160*795d594fSAndroid Build Coastguard Worker         break;
1161*795d594fSAndroid Build Coastguard Worker       case 'S':  // jshort
1162*795d594fSAndroid Build Coastguard Worker         StringAppendF(msg, "%d", arg.S);
1163*795d594fSAndroid Build Coastguard Worker         break;
1164*795d594fSAndroid Build Coastguard Worker       case 'i':  // jint - fall-through.
1165*795d594fSAndroid Build Coastguard Worker       case 'I':  // jint
1166*795d594fSAndroid Build Coastguard Worker         StringAppendF(msg, "%d", arg.I);
1167*795d594fSAndroid Build Coastguard Worker         break;
1168*795d594fSAndroid Build Coastguard Worker       case 'J':  // jlong
1169*795d594fSAndroid Build Coastguard Worker         StringAppendF(msg, "%" PRId64, arg.J);
1170*795d594fSAndroid Build Coastguard Worker         break;
1171*795d594fSAndroid Build Coastguard Worker       case 'Z':  // jboolean
1172*795d594fSAndroid Build Coastguard Worker       case 'b':  // jboolean (JNI-style)
1173*795d594fSAndroid Build Coastguard Worker         *msg += arg.b == JNI_TRUE ? "true" : "false";
1174*795d594fSAndroid Build Coastguard Worker         break;
1175*795d594fSAndroid Build Coastguard Worker       case 'V':  // void
1176*795d594fSAndroid Build Coastguard Worker         DCHECK(arg.V == nullptr);
1177*795d594fSAndroid Build Coastguard Worker         *msg += "void";
1178*795d594fSAndroid Build Coastguard Worker         break;
1179*795d594fSAndroid Build Coastguard Worker       case 'v':  // JavaVM*
1180*795d594fSAndroid Build Coastguard Worker         StringAppendF(msg, "(JavaVM*)%p", arg.v);
1181*795d594fSAndroid Build Coastguard Worker         break;
1182*795d594fSAndroid Build Coastguard Worker       case 'E':
1183*795d594fSAndroid Build Coastguard Worker         StringAppendF(msg, "(JNIEnv*)%p", arg.E);
1184*795d594fSAndroid Build Coastguard Worker         break;
1185*795d594fSAndroid Build Coastguard Worker       case 'z':  // non-negative jsize
1186*795d594fSAndroid Build Coastguard Worker         // You might expect jsize to be size_t, but it's not; it's the same as jint.
1187*795d594fSAndroid Build Coastguard Worker         // We only treat this specially so we can do the non-negative check.
1188*795d594fSAndroid Build Coastguard Worker         // TODO: maybe this wasn't worth it?
1189*795d594fSAndroid Build Coastguard Worker         StringAppendF(msg, "%d", arg.z);
1190*795d594fSAndroid Build Coastguard Worker         break;
1191*795d594fSAndroid Build Coastguard Worker       case 'p':  // void* ("pointer")
1192*795d594fSAndroid Build Coastguard Worker         if (arg.p == nullptr) {
1193*795d594fSAndroid Build Coastguard Worker           *msg += "NULL";
1194*795d594fSAndroid Build Coastguard Worker         } else {
1195*795d594fSAndroid Build Coastguard Worker           StringAppendF(msg, "(void*) %p", arg.p);
1196*795d594fSAndroid Build Coastguard Worker         }
1197*795d594fSAndroid Build Coastguard Worker         break;
1198*795d594fSAndroid Build Coastguard Worker       case 'r': {  // jint (release mode)
1199*795d594fSAndroid Build Coastguard Worker         jint releaseMode = arg.r;
1200*795d594fSAndroid Build Coastguard Worker         if (releaseMode == 0) {
1201*795d594fSAndroid Build Coastguard Worker           *msg += "0";
1202*795d594fSAndroid Build Coastguard Worker         } else if (releaseMode == JNI_ABORT) {
1203*795d594fSAndroid Build Coastguard Worker           *msg += "JNI_ABORT";
1204*795d594fSAndroid Build Coastguard Worker         } else if (releaseMode == JNI_COMMIT) {
1205*795d594fSAndroid Build Coastguard Worker           *msg += "JNI_COMMIT";
1206*795d594fSAndroid Build Coastguard Worker         } else {
1207*795d594fSAndroid Build Coastguard Worker           StringAppendF(msg, "invalid release mode %d", releaseMode);
1208*795d594fSAndroid Build Coastguard Worker         }
1209*795d594fSAndroid Build Coastguard Worker         break;
1210*795d594fSAndroid Build Coastguard Worker       }
1211*795d594fSAndroid Build Coastguard Worker       case 'u':  // const char* (Modified UTF-8)
1212*795d594fSAndroid Build Coastguard Worker         if (arg.u == nullptr) {
1213*795d594fSAndroid Build Coastguard Worker           *msg += "NULL";
1214*795d594fSAndroid Build Coastguard Worker         } else {
1215*795d594fSAndroid Build Coastguard Worker           StringAppendF(msg, "\"%s\"", arg.u);
1216*795d594fSAndroid Build Coastguard Worker         }
1217*795d594fSAndroid Build Coastguard Worker         break;
1218*795d594fSAndroid Build Coastguard Worker       case 'w':  // jobjectRefType
1219*795d594fSAndroid Build Coastguard Worker         switch (arg.w) {
1220*795d594fSAndroid Build Coastguard Worker           case JNIInvalidRefType:
1221*795d594fSAndroid Build Coastguard Worker             *msg += "invalid reference type";
1222*795d594fSAndroid Build Coastguard Worker             break;
1223*795d594fSAndroid Build Coastguard Worker           case JNILocalRefType:
1224*795d594fSAndroid Build Coastguard Worker             *msg += "local ref type";
1225*795d594fSAndroid Build Coastguard Worker             break;
1226*795d594fSAndroid Build Coastguard Worker           case JNIGlobalRefType:
1227*795d594fSAndroid Build Coastguard Worker             *msg += "global ref type";
1228*795d594fSAndroid Build Coastguard Worker             break;
1229*795d594fSAndroid Build Coastguard Worker           case JNIWeakGlobalRefType:
1230*795d594fSAndroid Build Coastguard Worker             *msg += "weak global ref type";
1231*795d594fSAndroid Build Coastguard Worker             break;
1232*795d594fSAndroid Build Coastguard Worker           default:
1233*795d594fSAndroid Build Coastguard Worker             *msg += "unknown ref type";
1234*795d594fSAndroid Build Coastguard Worker             break;
1235*795d594fSAndroid Build Coastguard Worker         }
1236*795d594fSAndroid Build Coastguard Worker         break;
1237*795d594fSAndroid Build Coastguard Worker       default:
1238*795d594fSAndroid Build Coastguard Worker         LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
1239*795d594fSAndroid Build Coastguard Worker     }
1240*795d594fSAndroid Build Coastguard Worker   }
1241*795d594fSAndroid Build Coastguard Worker   /*
1242*795d594fSAndroid Build Coastguard Worker    * Verify that "array" is non-null and points to an Array object.
1243*795d594fSAndroid Build Coastguard Worker    *
1244*795d594fSAndroid Build Coastguard Worker    * Since we're dealing with objects, switch to "running" mode.
1245*795d594fSAndroid Build Coastguard Worker    */
CheckArray(ScopedObjectAccess & soa,jarray java_array)1246*795d594fSAndroid Build Coastguard Worker   bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
1247*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
1248*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(java_array == nullptr)) {
1249*795d594fSAndroid Build Coastguard Worker       AbortF("jarray was NULL");
1250*795d594fSAndroid Build Coastguard Worker       return false;
1251*795d594fSAndroid Build Coastguard Worker     }
1252*795d594fSAndroid Build Coastguard Worker 
1253*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
1254*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a.Ptr()))) {
1255*795d594fSAndroid Build Coastguard Worker       Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
1256*795d594fSAndroid Build Coastguard Worker       AbortF("jarray is an invalid %s: %p (%p)",
1257*795d594fSAndroid Build Coastguard Worker              GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_array)),
1258*795d594fSAndroid Build Coastguard Worker              java_array,
1259*795d594fSAndroid Build Coastguard Worker              a.Ptr());
1260*795d594fSAndroid Build Coastguard Worker       return false;
1261*795d594fSAndroid Build Coastguard Worker     } else if (!a->IsArrayInstance()) {
1262*795d594fSAndroid Build Coastguard Worker       AbortF("jarray argument has non-array type: %s", a->PrettyTypeOf().c_str());
1263*795d594fSAndroid Build Coastguard Worker       return false;
1264*795d594fSAndroid Build Coastguard Worker     }
1265*795d594fSAndroid Build Coastguard Worker     return true;
1266*795d594fSAndroid Build Coastguard Worker   }
1267*795d594fSAndroid Build Coastguard Worker 
CheckBoolean(jint z)1268*795d594fSAndroid Build Coastguard Worker   bool CheckBoolean(jint z) {
1269*795d594fSAndroid Build Coastguard Worker     if (z != JNI_TRUE && z != JNI_FALSE) {
1270*795d594fSAndroid Build Coastguard Worker       // Note, broken booleans are always fatal.
1271*795d594fSAndroid Build Coastguard Worker       AbortF("unexpected jboolean value: %d", z);
1272*795d594fSAndroid Build Coastguard Worker       return false;
1273*795d594fSAndroid Build Coastguard Worker     }
1274*795d594fSAndroid Build Coastguard Worker     return true;
1275*795d594fSAndroid Build Coastguard Worker   }
1276*795d594fSAndroid Build Coastguard Worker 
CheckByte(jint b)1277*795d594fSAndroid Build Coastguard Worker   bool CheckByte(jint b) {
1278*795d594fSAndroid Build Coastguard Worker     if (b < std::numeric_limits<jbyte>::min() ||
1279*795d594fSAndroid Build Coastguard Worker         b > std::numeric_limits<jbyte>::max()) {
1280*795d594fSAndroid Build Coastguard Worker       if (kBrokenPrimitivesAreFatal) {
1281*795d594fSAndroid Build Coastguard Worker         AbortF("unexpected jbyte value: %d", b);
1282*795d594fSAndroid Build Coastguard Worker         return false;
1283*795d594fSAndroid Build Coastguard Worker       } else {
1284*795d594fSAndroid Build Coastguard Worker         LOG(WARNING) << "Unexpected jbyte value: " << b;
1285*795d594fSAndroid Build Coastguard Worker       }
1286*795d594fSAndroid Build Coastguard Worker     }
1287*795d594fSAndroid Build Coastguard Worker     return true;
1288*795d594fSAndroid Build Coastguard Worker   }
1289*795d594fSAndroid Build Coastguard Worker 
CheckShort(jint s)1290*795d594fSAndroid Build Coastguard Worker   bool CheckShort(jint s) {
1291*795d594fSAndroid Build Coastguard Worker     if (s < std::numeric_limits<jshort>::min() ||
1292*795d594fSAndroid Build Coastguard Worker         s > std::numeric_limits<jshort>::max()) {
1293*795d594fSAndroid Build Coastguard Worker       if (kBrokenPrimitivesAreFatal) {
1294*795d594fSAndroid Build Coastguard Worker         AbortF("unexpected jshort value: %d", s);
1295*795d594fSAndroid Build Coastguard Worker         return false;
1296*795d594fSAndroid Build Coastguard Worker       } else {
1297*795d594fSAndroid Build Coastguard Worker         LOG(WARNING) << "Unexpected jshort value: " << s;
1298*795d594fSAndroid Build Coastguard Worker       }
1299*795d594fSAndroid Build Coastguard Worker     }
1300*795d594fSAndroid Build Coastguard Worker     return true;
1301*795d594fSAndroid Build Coastguard Worker   }
1302*795d594fSAndroid Build Coastguard Worker 
CheckChar(jint c)1303*795d594fSAndroid Build Coastguard Worker   bool CheckChar(jint c) {
1304*795d594fSAndroid Build Coastguard Worker     if (c < std::numeric_limits<jchar>::min() ||
1305*795d594fSAndroid Build Coastguard Worker         c > std::numeric_limits<jchar>::max()) {
1306*795d594fSAndroid Build Coastguard Worker       if (kBrokenPrimitivesAreFatal) {
1307*795d594fSAndroid Build Coastguard Worker         AbortF("unexpected jchar value: %d", c);
1308*795d594fSAndroid Build Coastguard Worker         return false;
1309*795d594fSAndroid Build Coastguard Worker       } else {
1310*795d594fSAndroid Build Coastguard Worker         LOG(WARNING) << "Unexpected jchar value: " << c;
1311*795d594fSAndroid Build Coastguard Worker       }
1312*795d594fSAndroid Build Coastguard Worker     }
1313*795d594fSAndroid Build Coastguard Worker     return true;
1314*795d594fSAndroid Build Coastguard Worker   }
1315*795d594fSAndroid Build Coastguard Worker 
CheckLengthPositive(jsize length)1316*795d594fSAndroid Build Coastguard Worker   bool CheckLengthPositive(jsize length) {
1317*795d594fSAndroid Build Coastguard Worker     if (length < 0) {
1318*795d594fSAndroid Build Coastguard Worker       AbortF("negative jsize: %d", length);
1319*795d594fSAndroid Build Coastguard Worker       return false;
1320*795d594fSAndroid Build Coastguard Worker     }
1321*795d594fSAndroid Build Coastguard Worker     return true;
1322*795d594fSAndroid Build Coastguard Worker   }
1323*795d594fSAndroid Build Coastguard Worker 
CheckFieldID(jfieldID fid)1324*795d594fSAndroid Build Coastguard Worker   ArtField* CheckFieldID(jfieldID fid) REQUIRES_SHARED(Locks::mutator_lock_) {
1325*795d594fSAndroid Build Coastguard Worker     if (fid == nullptr) {
1326*795d594fSAndroid Build Coastguard Worker       AbortF("jfieldID was NULL");
1327*795d594fSAndroid Build Coastguard Worker       return nullptr;
1328*795d594fSAndroid Build Coastguard Worker     }
1329*795d594fSAndroid Build Coastguard Worker     ArtField* f = jni::DecodeArtField(fid);
1330*795d594fSAndroid Build Coastguard Worker     // TODO: Better check here.
1331*795d594fSAndroid Build Coastguard Worker     if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass().Ptr())) {
1332*795d594fSAndroid Build Coastguard Worker       Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
1333*795d594fSAndroid Build Coastguard Worker       AbortF("invalid jfieldID: %p", fid);
1334*795d594fSAndroid Build Coastguard Worker       return nullptr;
1335*795d594fSAndroid Build Coastguard Worker     }
1336*795d594fSAndroid Build Coastguard Worker     return f;
1337*795d594fSAndroid Build Coastguard Worker   }
1338*795d594fSAndroid Build Coastguard Worker 
CheckMethodID(jmethodID mid)1339*795d594fSAndroid Build Coastguard Worker   ArtMethod* CheckMethodID(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
1340*795d594fSAndroid Build Coastguard Worker     if (mid == nullptr) {
1341*795d594fSAndroid Build Coastguard Worker       AbortF("jmethodID was NULL");
1342*795d594fSAndroid Build Coastguard Worker       return nullptr;
1343*795d594fSAndroid Build Coastguard Worker     }
1344*795d594fSAndroid Build Coastguard Worker     ArtMethod* m = jni::DecodeArtMethod(mid);
1345*795d594fSAndroid Build Coastguard Worker     // TODO: Better check here.
1346*795d594fSAndroid Build Coastguard Worker     if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass().Ptr())) {
1347*795d594fSAndroid Build Coastguard Worker       Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
1348*795d594fSAndroid Build Coastguard Worker       AbortF("invalid jmethodID: %p", mid);
1349*795d594fSAndroid Build Coastguard Worker       return nullptr;
1350*795d594fSAndroid Build Coastguard Worker     }
1351*795d594fSAndroid Build Coastguard Worker     return m;
1352*795d594fSAndroid Build Coastguard Worker   }
1353*795d594fSAndroid Build Coastguard Worker 
CheckThread(JNIEnv * env)1354*795d594fSAndroid Build Coastguard Worker   bool CheckThread(JNIEnv* env) REQUIRES_SHARED(Locks::mutator_lock_) {
1355*795d594fSAndroid Build Coastguard Worker     Thread* self = Thread::Current();
1356*795d594fSAndroid Build Coastguard Worker     CHECK(self != nullptr);
1357*795d594fSAndroid Build Coastguard Worker 
1358*795d594fSAndroid Build Coastguard Worker     // Get the current thread's JNIEnv by going through our TLS pointer.
1359*795d594fSAndroid Build Coastguard Worker     JNIEnvExt* threadEnv = self->GetJniEnv();
1360*795d594fSAndroid Build Coastguard Worker 
1361*795d594fSAndroid Build Coastguard Worker     // Verify that the current thread is (a) attached and (b) associated with
1362*795d594fSAndroid Build Coastguard Worker     // this particular instance of JNIEnv.
1363*795d594fSAndroid Build Coastguard Worker     if (env != threadEnv) {
1364*795d594fSAndroid Build Coastguard Worker       // Get the thread owning the JNIEnv that's being used.
1365*795d594fSAndroid Build Coastguard Worker       Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->GetSelf();
1366*795d594fSAndroid Build Coastguard Worker       AbortF("thread %s using JNIEnv* from thread %s",
1367*795d594fSAndroid Build Coastguard Worker              ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str());
1368*795d594fSAndroid Build Coastguard Worker       return false;
1369*795d594fSAndroid Build Coastguard Worker     }
1370*795d594fSAndroid Build Coastguard Worker 
1371*795d594fSAndroid Build Coastguard Worker     // Verify that, if this thread previously made a critical "get" call, we
1372*795d594fSAndroid Build Coastguard Worker     // do the corresponding "release" call before we try anything else.
1373*795d594fSAndroid Build Coastguard Worker     switch (flags_ & kFlag_CritMask) {
1374*795d594fSAndroid Build Coastguard Worker     case kFlag_CritOkay:    // okay to call this method
1375*795d594fSAndroid Build Coastguard Worker       break;
1376*795d594fSAndroid Build Coastguard Worker     case kFlag_CritBad:     // not okay to call
1377*795d594fSAndroid Build Coastguard Worker       if (threadEnv->GetCritical() > 0) {
1378*795d594fSAndroid Build Coastguard Worker         AbortF("thread %s using JNI after critical get",
1379*795d594fSAndroid Build Coastguard Worker                ToStr<Thread>(*self).c_str());
1380*795d594fSAndroid Build Coastguard Worker         return false;
1381*795d594fSAndroid Build Coastguard Worker       }
1382*795d594fSAndroid Build Coastguard Worker       break;
1383*795d594fSAndroid Build Coastguard Worker     case kFlag_CritGet:     // this is a "get" call
1384*795d594fSAndroid Build Coastguard Worker       // Don't check here; we allow nested gets.
1385*795d594fSAndroid Build Coastguard Worker       if (threadEnv->GetCritical() == 0) {
1386*795d594fSAndroid Build Coastguard Worker         threadEnv->SetCriticalStartUs(self->GetCpuMicroTime());
1387*795d594fSAndroid Build Coastguard Worker       }
1388*795d594fSAndroid Build Coastguard Worker       threadEnv->SetCritical(threadEnv->GetCritical() + 1);
1389*795d594fSAndroid Build Coastguard Worker       break;
1390*795d594fSAndroid Build Coastguard Worker     case kFlag_CritRelease:  // this is a "release" call
1391*795d594fSAndroid Build Coastguard Worker       if (threadEnv->GetCritical() == 0) {
1392*795d594fSAndroid Build Coastguard Worker         AbortF("thread %s called too many critical releases",
1393*795d594fSAndroid Build Coastguard Worker                ToStr<Thread>(*self).c_str());
1394*795d594fSAndroid Build Coastguard Worker         return false;
1395*795d594fSAndroid Build Coastguard Worker       } else if (threadEnv->GetCritical() == 1) {
1396*795d594fSAndroid Build Coastguard Worker         // Leaving the critical region, possibly warn about long critical regions.
1397*795d594fSAndroid Build Coastguard Worker         uint64_t critical_duration_us = self->GetCpuMicroTime() - threadEnv->GetCriticalStartUs();
1398*795d594fSAndroid Build Coastguard Worker         if (critical_duration_us > kCriticalWarnTimeUs) {
1399*795d594fSAndroid Build Coastguard Worker           LOG(WARNING) << "JNI critical lock held for "
1400*795d594fSAndroid Build Coastguard Worker                        << PrettyDuration(UsToNs(critical_duration_us)) << " on " << *self;
1401*795d594fSAndroid Build Coastguard Worker         }
1402*795d594fSAndroid Build Coastguard Worker       }
1403*795d594fSAndroid Build Coastguard Worker       threadEnv->SetCritical(threadEnv->GetCritical() - 1);
1404*795d594fSAndroid Build Coastguard Worker       break;
1405*795d594fSAndroid Build Coastguard Worker     default:
1406*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "Bad flags (internal error): " << flags_;
1407*795d594fSAndroid Build Coastguard Worker     }
1408*795d594fSAndroid Build Coastguard Worker 
1409*795d594fSAndroid Build Coastguard Worker     // Verify that, if an exception has been raised, the native code doesn't
1410*795d594fSAndroid Build Coastguard Worker     // make any JNI calls other than the Exception* methods.
1411*795d594fSAndroid Build Coastguard Worker     if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
1412*795d594fSAndroid Build Coastguard Worker       mirror::Throwable* exception = self->GetException();
1413*795d594fSAndroid Build Coastguard Worker       AbortF("JNI %s called with pending exception %s",
1414*795d594fSAndroid Build Coastguard Worker              function_name_,
1415*795d594fSAndroid Build Coastguard Worker              exception->Dump().c_str());
1416*795d594fSAndroid Build Coastguard Worker       return false;
1417*795d594fSAndroid Build Coastguard Worker     }
1418*795d594fSAndroid Build Coastguard Worker     return true;
1419*795d594fSAndroid Build Coastguard Worker   }
1420*795d594fSAndroid Build Coastguard Worker 
1421*795d594fSAndroid Build Coastguard Worker   // Verifies that "bytes" points to valid Modified UTF-8 data.
CheckUtfString(const char * bytes,bool nullable)1422*795d594fSAndroid Build Coastguard Worker   bool CheckUtfString(const char* bytes, bool nullable) {
1423*795d594fSAndroid Build Coastguard Worker     if (bytes == nullptr) {
1424*795d594fSAndroid Build Coastguard Worker       if (!nullable) {
1425*795d594fSAndroid Build Coastguard Worker         AbortF("non-nullable const char* was NULL");
1426*795d594fSAndroid Build Coastguard Worker         return false;
1427*795d594fSAndroid Build Coastguard Worker       }
1428*795d594fSAndroid Build Coastguard Worker       return true;
1429*795d594fSAndroid Build Coastguard Worker     }
1430*795d594fSAndroid Build Coastguard Worker 
1431*795d594fSAndroid Build Coastguard Worker     const char* errorKind = nullptr;
1432*795d594fSAndroid Build Coastguard Worker     const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind);
1433*795d594fSAndroid Build Coastguard Worker     if (errorKind != nullptr) {
1434*795d594fSAndroid Build Coastguard Worker       // This is an expensive loop that will resize often, but this isn't supposed to hit in
1435*795d594fSAndroid Build Coastguard Worker       // practice anyways.
1436*795d594fSAndroid Build Coastguard Worker       std::ostringstream oss;
1437*795d594fSAndroid Build Coastguard Worker       oss << std::hex;
1438*795d594fSAndroid Build Coastguard Worker       const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes);
1439*795d594fSAndroid Build Coastguard Worker       while (*tmp != 0) {
1440*795d594fSAndroid Build Coastguard Worker         if (tmp == utf8) {
1441*795d594fSAndroid Build Coastguard Worker           oss << "<";
1442*795d594fSAndroid Build Coastguard Worker         }
1443*795d594fSAndroid Build Coastguard Worker         oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp);
1444*795d594fSAndroid Build Coastguard Worker         if (tmp == utf8) {
1445*795d594fSAndroid Build Coastguard Worker           oss << '>';
1446*795d594fSAndroid Build Coastguard Worker         }
1447*795d594fSAndroid Build Coastguard Worker         tmp++;
1448*795d594fSAndroid Build Coastguard Worker         if (*tmp != 0) {
1449*795d594fSAndroid Build Coastguard Worker           oss << ' ';
1450*795d594fSAndroid Build Coastguard Worker         }
1451*795d594fSAndroid Build Coastguard Worker       }
1452*795d594fSAndroid Build Coastguard Worker 
1453*795d594fSAndroid Build Coastguard Worker       AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
1454*795d594fSAndroid Build Coastguard Worker           "    string: '%s'\n    input: '%s'", errorKind, *utf8, bytes, oss.str().c_str());
1455*795d594fSAndroid Build Coastguard Worker       return false;
1456*795d594fSAndroid Build Coastguard Worker     }
1457*795d594fSAndroid Build Coastguard Worker     return true;
1458*795d594fSAndroid Build Coastguard Worker   }
1459*795d594fSAndroid Build Coastguard Worker 
1460*795d594fSAndroid Build Coastguard Worker   // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1461*795d594fSAndroid Build Coastguard Worker   // sequences in place of encoded surrogate pairs.
CheckUtfBytes(const char * bytes,const char ** errorKind)1462*795d594fSAndroid Build Coastguard Worker   static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) {
1463*795d594fSAndroid Build Coastguard Worker     while (*bytes != '\0') {
1464*795d594fSAndroid Build Coastguard Worker       const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1465*795d594fSAndroid Build Coastguard Worker       // Switch on the high four bits.
1466*795d594fSAndroid Build Coastguard Worker       switch (*utf8 >> 4) {
1467*795d594fSAndroid Build Coastguard Worker       case 0x00:
1468*795d594fSAndroid Build Coastguard Worker       case 0x01:
1469*795d594fSAndroid Build Coastguard Worker       case 0x02:
1470*795d594fSAndroid Build Coastguard Worker       case 0x03:
1471*795d594fSAndroid Build Coastguard Worker       case 0x04:
1472*795d594fSAndroid Build Coastguard Worker       case 0x05:
1473*795d594fSAndroid Build Coastguard Worker       case 0x06:
1474*795d594fSAndroid Build Coastguard Worker       case 0x07:
1475*795d594fSAndroid Build Coastguard Worker         // Bit pattern 0xxx. No need for any extra bytes.
1476*795d594fSAndroid Build Coastguard Worker         break;
1477*795d594fSAndroid Build Coastguard Worker       case 0x08:
1478*795d594fSAndroid Build Coastguard Worker       case 0x09:
1479*795d594fSAndroid Build Coastguard Worker       case 0x0a:
1480*795d594fSAndroid Build Coastguard Worker       case 0x0b:
1481*795d594fSAndroid Build Coastguard Worker          // Bit patterns 10xx, which are illegal start bytes.
1482*795d594fSAndroid Build Coastguard Worker         *errorKind = "start";
1483*795d594fSAndroid Build Coastguard Worker         return utf8;
1484*795d594fSAndroid Build Coastguard Worker       case 0x0f:
1485*795d594fSAndroid Build Coastguard Worker         // Bit pattern 1111, which might be the start of a 4 byte sequence.
1486*795d594fSAndroid Build Coastguard Worker         if ((*utf8 & 0x08) == 0) {
1487*795d594fSAndroid Build Coastguard Worker           // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1488*795d594fSAndroid Build Coastguard Worker           // We consume one continuation byte here, and fall through to consume two more.
1489*795d594fSAndroid Build Coastguard Worker           utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1490*795d594fSAndroid Build Coastguard Worker           if ((*utf8 & 0xc0) != 0x80) {
1491*795d594fSAndroid Build Coastguard Worker             *errorKind = "continuation";
1492*795d594fSAndroid Build Coastguard Worker             return utf8;
1493*795d594fSAndroid Build Coastguard Worker           }
1494*795d594fSAndroid Build Coastguard Worker         } else {
1495*795d594fSAndroid Build Coastguard Worker           *errorKind = "start";
1496*795d594fSAndroid Build Coastguard Worker           return utf8;
1497*795d594fSAndroid Build Coastguard Worker         }
1498*795d594fSAndroid Build Coastguard Worker 
1499*795d594fSAndroid Build Coastguard Worker         // Fall through to the cases below to consume two more continuation bytes.
1500*795d594fSAndroid Build Coastguard Worker         FALLTHROUGH_INTENDED;
1501*795d594fSAndroid Build Coastguard Worker       case 0x0e:
1502*795d594fSAndroid Build Coastguard Worker         // Bit pattern 1110, so there are two additional bytes.
1503*795d594fSAndroid Build Coastguard Worker         utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1504*795d594fSAndroid Build Coastguard Worker         if ((*utf8 & 0xc0) != 0x80) {
1505*795d594fSAndroid Build Coastguard Worker           *errorKind = "continuation";
1506*795d594fSAndroid Build Coastguard Worker           return utf8;
1507*795d594fSAndroid Build Coastguard Worker         }
1508*795d594fSAndroid Build Coastguard Worker 
1509*795d594fSAndroid Build Coastguard Worker         // Fall through to consume one more continuation byte.
1510*795d594fSAndroid Build Coastguard Worker         FALLTHROUGH_INTENDED;
1511*795d594fSAndroid Build Coastguard Worker       case 0x0c:
1512*795d594fSAndroid Build Coastguard Worker       case 0x0d:
1513*795d594fSAndroid Build Coastguard Worker         // Bit pattern 110x, so there is one additional byte.
1514*795d594fSAndroid Build Coastguard Worker         utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1515*795d594fSAndroid Build Coastguard Worker         if ((*utf8 & 0xc0) != 0x80) {
1516*795d594fSAndroid Build Coastguard Worker           *errorKind = "continuation";
1517*795d594fSAndroid Build Coastguard Worker           return utf8;
1518*795d594fSAndroid Build Coastguard Worker         }
1519*795d594fSAndroid Build Coastguard Worker         break;
1520*795d594fSAndroid Build Coastguard Worker       }
1521*795d594fSAndroid Build Coastguard Worker     }
1522*795d594fSAndroid Build Coastguard Worker     return nullptr;
1523*795d594fSAndroid Build Coastguard Worker   }
1524*795d594fSAndroid Build Coastguard Worker 
AbortF(const char * fmt,...)1525*795d594fSAndroid Build Coastguard Worker   void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1526*795d594fSAndroid Build Coastguard Worker     va_list args;
1527*795d594fSAndroid Build Coastguard Worker     va_start(args, fmt);
1528*795d594fSAndroid Build Coastguard Worker     Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1529*795d594fSAndroid Build Coastguard Worker     va_end(args);
1530*795d594fSAndroid Build Coastguard Worker   }
1531*795d594fSAndroid Build Coastguard Worker 
1532*795d594fSAndroid Build Coastguard Worker   // The name of the JNI function being checked.
1533*795d594fSAndroid Build Coastguard Worker   const char* const function_name_;
1534*795d594fSAndroid Build Coastguard Worker 
1535*795d594fSAndroid Build Coastguard Worker   int indent_;
1536*795d594fSAndroid Build Coastguard Worker 
1537*795d594fSAndroid Build Coastguard Worker   const uint16_t flags_;
1538*795d594fSAndroid Build Coastguard Worker 
1539*795d594fSAndroid Build Coastguard Worker   const bool has_method_;
1540*795d594fSAndroid Build Coastguard Worker 
1541*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1542*795d594fSAndroid Build Coastguard Worker };
1543*795d594fSAndroid Build Coastguard Worker 
1544*795d594fSAndroid Build Coastguard Worker /*
1545*795d594fSAndroid Build Coastguard Worker  * ===========================================================================
1546*795d594fSAndroid Build Coastguard Worker  *      Guarded arrays
1547*795d594fSAndroid Build Coastguard Worker  * ===========================================================================
1548*795d594fSAndroid Build Coastguard Worker  */
1549*795d594fSAndroid Build Coastguard Worker 
1550*795d594fSAndroid Build Coastguard Worker /* this gets tucked in at the start of the buffer; struct size must be even */
1551*795d594fSAndroid Build Coastguard Worker class GuardedCopy {
1552*795d594fSAndroid Build Coastguard Worker  public:
1553*795d594fSAndroid Build Coastguard Worker   /*
1554*795d594fSAndroid Build Coastguard Worker    * Create an over-sized buffer to hold the contents of "buf".  Copy it in,
1555*795d594fSAndroid Build Coastguard Worker    * filling in the area around it with guard data.
1556*795d594fSAndroid Build Coastguard Worker    */
Create(void * original_buf,size_t len,bool mod_okay)1557*795d594fSAndroid Build Coastguard Worker   static void* Create(void* original_buf, size_t len, bool mod_okay) {
1558*795d594fSAndroid Build Coastguard Worker     const size_t new_len = LengthIncludingRedZones(len);
1559*795d594fSAndroid Build Coastguard Worker     uint8_t* const new_buf = DebugAlloc(new_len);
1560*795d594fSAndroid Build Coastguard Worker 
1561*795d594fSAndroid Build Coastguard Worker     // If modification is not expected, grab a checksum.
1562*795d594fSAndroid Build Coastguard Worker     uLong adler = 0;
1563*795d594fSAndroid Build Coastguard Worker     if (!mod_okay) {
1564*795d594fSAndroid Build Coastguard Worker       adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
1565*795d594fSAndroid Build Coastguard Worker     }
1566*795d594fSAndroid Build Coastguard Worker 
1567*795d594fSAndroid Build Coastguard Worker     GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
1568*795d594fSAndroid Build Coastguard Worker 
1569*795d594fSAndroid Build Coastguard Worker     // Fill begin region with canary pattern.
1570*795d594fSAndroid Build Coastguard Worker     const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1571*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1572*795d594fSAndroid Build Coastguard Worker       const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1573*795d594fSAndroid Build Coastguard Worker       if (kCanary[j] == '\0') {
1574*795d594fSAndroid Build Coastguard Worker         j = 0;
1575*795d594fSAndroid Build Coastguard Worker       } else {
1576*795d594fSAndroid Build Coastguard Worker         j++;
1577*795d594fSAndroid Build Coastguard Worker       }
1578*795d594fSAndroid Build Coastguard Worker     }
1579*795d594fSAndroid Build Coastguard Worker 
1580*795d594fSAndroid Build Coastguard Worker     // Copy the data in; note "len" could be zero.
1581*795d594fSAndroid Build Coastguard Worker     memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1582*795d594fSAndroid Build Coastguard Worker 
1583*795d594fSAndroid Build Coastguard Worker     // Fill end region with canary pattern.
1584*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1585*795d594fSAndroid Build Coastguard Worker       const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1586*795d594fSAndroid Build Coastguard Worker       if (kCanary[j] == '\0') {
1587*795d594fSAndroid Build Coastguard Worker         j = 0;
1588*795d594fSAndroid Build Coastguard Worker       } else {
1589*795d594fSAndroid Build Coastguard Worker         j++;
1590*795d594fSAndroid Build Coastguard Worker       }
1591*795d594fSAndroid Build Coastguard Worker     }
1592*795d594fSAndroid Build Coastguard Worker 
1593*795d594fSAndroid Build Coastguard Worker     return const_cast<uint8_t*>(copy->BufferWithinRedZones());
1594*795d594fSAndroid Build Coastguard Worker   }
1595*795d594fSAndroid Build Coastguard Worker 
1596*795d594fSAndroid Build Coastguard Worker   /*
1597*795d594fSAndroid Build Coastguard Worker    * Create a guarded copy of a primitive array.  Modifications to the copied
1598*795d594fSAndroid Build Coastguard Worker    * data are allowed.  Returns a pointer to the copied data.
1599*795d594fSAndroid Build Coastguard Worker    */
CreateGuardedPACopy(JNIEnv * env,const jarray java_array,jboolean * is_copy,void * original_ptr)1600*795d594fSAndroid Build Coastguard Worker   static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
1601*795d594fSAndroid Build Coastguard Worker                                    void* original_ptr) {
1602*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
1603*795d594fSAndroid Build Coastguard Worker 
1604*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
1605*795d594fSAndroid Build Coastguard Worker     size_t component_size = a->GetClass()->GetComponentSize();
1606*795d594fSAndroid Build Coastguard Worker     size_t byte_count = a->GetLength() * component_size;
1607*795d594fSAndroid Build Coastguard Worker     void* result = Create(original_ptr, byte_count, true);
1608*795d594fSAndroid Build Coastguard Worker     if (is_copy != nullptr) {
1609*795d594fSAndroid Build Coastguard Worker       *is_copy = JNI_TRUE;
1610*795d594fSAndroid Build Coastguard Worker     }
1611*795d594fSAndroid Build Coastguard Worker     return result;
1612*795d594fSAndroid Build Coastguard Worker   }
1613*795d594fSAndroid Build Coastguard Worker 
1614*795d594fSAndroid Build Coastguard Worker   /*
1615*795d594fSAndroid Build Coastguard Worker    * Perform the array "release" operation, which may or may not copy data
1616*795d594fSAndroid Build Coastguard Worker    * back into the managed heap, and may or may not release the underlying storage.
1617*795d594fSAndroid Build Coastguard Worker    */
ReleaseGuardedPACopy(const char * function_name,JNIEnv * env,jarray java_array,void * embedded_buf,int mode)1618*795d594fSAndroid Build Coastguard Worker   static void* ReleaseGuardedPACopy(const char* function_name,
1619*795d594fSAndroid Build Coastguard Worker                                     JNIEnv* env,
1620*795d594fSAndroid Build Coastguard Worker                                     [[maybe_unused]] jarray java_array,
1621*795d594fSAndroid Build Coastguard Worker                                     void* embedded_buf,
1622*795d594fSAndroid Build Coastguard Worker                                     int mode) {
1623*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
1624*795d594fSAndroid Build Coastguard Worker     if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1625*795d594fSAndroid Build Coastguard Worker       return nullptr;
1626*795d594fSAndroid Build Coastguard Worker     }
1627*795d594fSAndroid Build Coastguard Worker     GuardedCopy* const copy = FromEmbedded(embedded_buf);
1628*795d594fSAndroid Build Coastguard Worker     void* original_ptr = copy->original_ptr_;
1629*795d594fSAndroid Build Coastguard Worker     if (mode != JNI_ABORT) {
1630*795d594fSAndroid Build Coastguard Worker       memcpy(original_ptr, embedded_buf, copy->original_length_);
1631*795d594fSAndroid Build Coastguard Worker     }
1632*795d594fSAndroid Build Coastguard Worker     if (mode != JNI_COMMIT) {
1633*795d594fSAndroid Build Coastguard Worker       Destroy(embedded_buf);
1634*795d594fSAndroid Build Coastguard Worker     }
1635*795d594fSAndroid Build Coastguard Worker     return original_ptr;
1636*795d594fSAndroid Build Coastguard Worker   }
1637*795d594fSAndroid Build Coastguard Worker 
1638*795d594fSAndroid Build Coastguard Worker   /*
1639*795d594fSAndroid Build Coastguard Worker    * Free up the guard buffer, scrub it, and return the original pointer.
1640*795d594fSAndroid Build Coastguard Worker    */
Destroy(void * embedded_buf)1641*795d594fSAndroid Build Coastguard Worker   static void* Destroy(void* embedded_buf) {
1642*795d594fSAndroid Build Coastguard Worker     GuardedCopy* copy = FromEmbedded(embedded_buf);
1643*795d594fSAndroid Build Coastguard Worker     void* original_ptr = const_cast<void*>(copy->original_ptr_);
1644*795d594fSAndroid Build Coastguard Worker     size_t len = LengthIncludingRedZones(copy->original_length_);
1645*795d594fSAndroid Build Coastguard Worker     DebugFree(copy, len);
1646*795d594fSAndroid Build Coastguard Worker     return original_ptr;
1647*795d594fSAndroid Build Coastguard Worker   }
1648*795d594fSAndroid Build Coastguard Worker 
1649*795d594fSAndroid Build Coastguard Worker   /*
1650*795d594fSAndroid Build Coastguard Worker    * Verify the guard area and, if "modOkay" is false, that the data itself
1651*795d594fSAndroid Build Coastguard Worker    * has not been altered.
1652*795d594fSAndroid Build Coastguard Worker    *
1653*795d594fSAndroid Build Coastguard Worker    * The caller has already checked that "dataBuf" is non-null.
1654*795d594fSAndroid Build Coastguard Worker    */
Check(const char * function_name,const void * embedded_buf,bool mod_okay)1655*795d594fSAndroid Build Coastguard Worker   static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1656*795d594fSAndroid Build Coastguard Worker     const GuardedCopy* copy = FromEmbedded(embedded_buf);
1657*795d594fSAndroid Build Coastguard Worker     return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
1658*795d594fSAndroid Build Coastguard Worker   }
1659*795d594fSAndroid Build Coastguard Worker 
1660*795d594fSAndroid Build Coastguard Worker  private:
GuardedCopy(void * original_buf,size_t len,uLong adler)1661*795d594fSAndroid Build Coastguard Worker   GuardedCopy(void* original_buf, size_t len, uLong adler) :
1662*795d594fSAndroid Build Coastguard Worker     magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1663*795d594fSAndroid Build Coastguard Worker   }
1664*795d594fSAndroid Build Coastguard Worker 
DebugAlloc(size_t len)1665*795d594fSAndroid Build Coastguard Worker   static uint8_t* DebugAlloc(size_t len) {
1666*795d594fSAndroid Build Coastguard Worker     void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
1667*795d594fSAndroid Build Coastguard Worker     if (result == MAP_FAILED) {
1668*795d594fSAndroid Build Coastguard Worker       PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1669*795d594fSAndroid Build Coastguard Worker     }
1670*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<uint8_t*>(result);
1671*795d594fSAndroid Build Coastguard Worker   }
1672*795d594fSAndroid Build Coastguard Worker 
DebugFree(void * buf,size_t len)1673*795d594fSAndroid Build Coastguard Worker   static void DebugFree(void* buf, size_t len) {
1674*795d594fSAndroid Build Coastguard Worker     if (munmap(buf, len) != 0) {
1675*795d594fSAndroid Build Coastguard Worker       PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
1676*795d594fSAndroid Build Coastguard Worker     }
1677*795d594fSAndroid Build Coastguard Worker   }
1678*795d594fSAndroid Build Coastguard Worker 
LengthIncludingRedZones(size_t len)1679*795d594fSAndroid Build Coastguard Worker   static size_t LengthIncludingRedZones(size_t len) {
1680*795d594fSAndroid Build Coastguard Worker     return len + kRedZoneSize;
1681*795d594fSAndroid Build Coastguard Worker   }
1682*795d594fSAndroid Build Coastguard Worker 
1683*795d594fSAndroid Build Coastguard Worker   // Get the GuardedCopy from the interior pointer.
FromEmbedded(void * embedded_buf)1684*795d594fSAndroid Build Coastguard Worker   static GuardedCopy* FromEmbedded(void* embedded_buf) {
1685*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<GuardedCopy*>(
1686*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
1687*795d594fSAndroid Build Coastguard Worker   }
1688*795d594fSAndroid Build Coastguard Worker 
FromEmbedded(const void * embedded_buf)1689*795d594fSAndroid Build Coastguard Worker   static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1690*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<const GuardedCopy*>(
1691*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
1692*795d594fSAndroid Build Coastguard Worker   }
1693*795d594fSAndroid Build Coastguard Worker 
AbortF(const char * jni_function_name,const char * fmt,...)1694*795d594fSAndroid Build Coastguard Worker   static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1695*795d594fSAndroid Build Coastguard Worker     va_list args;
1696*795d594fSAndroid Build Coastguard Worker     va_start(args, fmt);
1697*795d594fSAndroid Build Coastguard Worker     Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1698*795d594fSAndroid Build Coastguard Worker     va_end(args);
1699*795d594fSAndroid Build Coastguard Worker   }
1700*795d594fSAndroid Build Coastguard Worker 
CheckHeader(const char * function_name,bool mod_okay) const1701*795d594fSAndroid Build Coastguard Worker   bool CheckHeader(const char* function_name, bool mod_okay) const {
1702*795d594fSAndroid Build Coastguard Worker     static const uint32_t kMagicCmp = kGuardMagic;
1703*795d594fSAndroid Build Coastguard Worker 
1704*795d594fSAndroid Build Coastguard Worker     // Before we do anything with "pExtra", check the magic number.  We
1705*795d594fSAndroid Build Coastguard Worker     // do the check with memcmp rather than "==" in case the pointer is
1706*795d594fSAndroid Build Coastguard Worker     // unaligned.  If it points to completely bogus memory we're going
1707*795d594fSAndroid Build Coastguard Worker     // to crash, but there's no easy way around that.
1708*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1709*795d594fSAndroid Build Coastguard Worker       uint8_t buf[4];
1710*795d594fSAndroid Build Coastguard Worker       memcpy(buf, &magic_, 4);
1711*795d594fSAndroid Build Coastguard Worker       AbortF(function_name,
1712*795d594fSAndroid Build Coastguard Worker              "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1713*795d594fSAndroid Build Coastguard Worker              buf[3], buf[2], buf[1], buf[0], this);  // Assumes little-endian.
1714*795d594fSAndroid Build Coastguard Worker       return false;
1715*795d594fSAndroid Build Coastguard Worker     }
1716*795d594fSAndroid Build Coastguard Worker 
1717*795d594fSAndroid Build Coastguard Worker     // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1718*795d594fSAndroid Build Coastguard Worker     // told the client that we made a copy, there's no reason they can't alter the buffer.
1719*795d594fSAndroid Build Coastguard Worker     if (!mod_okay) {
1720*795d594fSAndroid Build Coastguard Worker       uLong computed_adler =
1721*795d594fSAndroid Build Coastguard Worker           adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1722*795d594fSAndroid Build Coastguard Worker       if (computed_adler != adler_) {
1723*795d594fSAndroid Build Coastguard Worker         AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1724*795d594fSAndroid Build Coastguard Worker                computed_adler, adler_, this);
1725*795d594fSAndroid Build Coastguard Worker         return false;
1726*795d594fSAndroid Build Coastguard Worker       }
1727*795d594fSAndroid Build Coastguard Worker     }
1728*795d594fSAndroid Build Coastguard Worker     return true;
1729*795d594fSAndroid Build Coastguard Worker   }
1730*795d594fSAndroid Build Coastguard Worker 
CheckRedZones(const char * function_name) const1731*795d594fSAndroid Build Coastguard Worker   bool CheckRedZones(const char* function_name) const {
1732*795d594fSAndroid Build Coastguard Worker     // Check the begin red zone.
1733*795d594fSAndroid Build Coastguard Worker     const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1734*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1735*795d594fSAndroid Build Coastguard Worker       if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1736*795d594fSAndroid Build Coastguard Worker         AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1737*795d594fSAndroid Build Coastguard Worker         return false;
1738*795d594fSAndroid Build Coastguard Worker       }
1739*795d594fSAndroid Build Coastguard Worker       if (kCanary[j] == '\0') {
1740*795d594fSAndroid Build Coastguard Worker         j = 0;
1741*795d594fSAndroid Build Coastguard Worker       } else {
1742*795d594fSAndroid Build Coastguard Worker         j++;
1743*795d594fSAndroid Build Coastguard Worker       }
1744*795d594fSAndroid Build Coastguard Worker     }
1745*795d594fSAndroid Build Coastguard Worker 
1746*795d594fSAndroid Build Coastguard Worker     // Check end region.
1747*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1748*795d594fSAndroid Build Coastguard Worker       if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1749*795d594fSAndroid Build Coastguard Worker         size_t offset_from_buffer_start =
1750*795d594fSAndroid Build Coastguard Worker             &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1751*795d594fSAndroid Build Coastguard Worker         AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1752*795d594fSAndroid Build Coastguard Worker                offset_from_buffer_start);
1753*795d594fSAndroid Build Coastguard Worker         return false;
1754*795d594fSAndroid Build Coastguard Worker       }
1755*795d594fSAndroid Build Coastguard Worker       if (kCanary[j] == '\0') {
1756*795d594fSAndroid Build Coastguard Worker         j = 0;
1757*795d594fSAndroid Build Coastguard Worker       } else {
1758*795d594fSAndroid Build Coastguard Worker         j++;
1759*795d594fSAndroid Build Coastguard Worker       }
1760*795d594fSAndroid Build Coastguard Worker     }
1761*795d594fSAndroid Build Coastguard Worker     return true;
1762*795d594fSAndroid Build Coastguard Worker   }
1763*795d594fSAndroid Build Coastguard Worker 
1764*795d594fSAndroid Build Coastguard Worker   // Location that canary value will be written before the guarded region.
StartRedZone() const1765*795d594fSAndroid Build Coastguard Worker   const char* StartRedZone() const {
1766*795d594fSAndroid Build Coastguard Worker     const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1767*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1768*795d594fSAndroid Build Coastguard Worker   }
1769*795d594fSAndroid Build Coastguard Worker 
1770*795d594fSAndroid Build Coastguard Worker   // Return the interior embedded buffer.
BufferWithinRedZones() const1771*795d594fSAndroid Build Coastguard Worker   const uint8_t* BufferWithinRedZones() const {
1772*795d594fSAndroid Build Coastguard Worker     const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1773*795d594fSAndroid Build Coastguard Worker     return embedded_buf;
1774*795d594fSAndroid Build Coastguard Worker   }
1775*795d594fSAndroid Build Coastguard Worker 
1776*795d594fSAndroid Build Coastguard Worker   // Location that canary value will be written after the guarded region.
EndRedZone() const1777*795d594fSAndroid Build Coastguard Worker   const char* EndRedZone() const {
1778*795d594fSAndroid Build Coastguard Worker     const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1779*795d594fSAndroid Build Coastguard Worker     size_t buf_len = LengthIncludingRedZones(original_length_);
1780*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1781*795d594fSAndroid Build Coastguard Worker   }
1782*795d594fSAndroid Build Coastguard Worker 
1783*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kRedZoneSize = 512;
1784*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1785*795d594fSAndroid Build Coastguard Worker 
1786*795d594fSAndroid Build Coastguard Worker   // Value written before and after the guarded array.
1787*795d594fSAndroid Build Coastguard Worker   static const char* const kCanary;
1788*795d594fSAndroid Build Coastguard Worker 
1789*795d594fSAndroid Build Coastguard Worker   static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1790*795d594fSAndroid Build Coastguard Worker 
1791*795d594fSAndroid Build Coastguard Worker   const uint32_t magic_;
1792*795d594fSAndroid Build Coastguard Worker   const uLong adler_;
1793*795d594fSAndroid Build Coastguard Worker   void* const original_ptr_;
1794*795d594fSAndroid Build Coastguard Worker   const size_t original_length_;
1795*795d594fSAndroid Build Coastguard Worker };
1796*795d594fSAndroid Build Coastguard Worker const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
1797*795d594fSAndroid Build Coastguard Worker 
1798*795d594fSAndroid Build Coastguard Worker /*
1799*795d594fSAndroid Build Coastguard Worker  * ===========================================================================
1800*795d594fSAndroid Build Coastguard Worker  *      JNI functions
1801*795d594fSAndroid Build Coastguard Worker  * ===========================================================================
1802*795d594fSAndroid Build Coastguard Worker  */
1803*795d594fSAndroid Build Coastguard Worker 
1804*795d594fSAndroid Build Coastguard Worker class CheckJNI {
1805*795d594fSAndroid Build Coastguard Worker  public:
GetVersion(JNIEnv * env)1806*795d594fSAndroid Build Coastguard Worker   static jint GetVersion(JNIEnv* env) {
1807*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
1808*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
1809*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
1810*795d594fSAndroid Build Coastguard Worker     JniValueType args[1] = {{.E = env }};
1811*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "E", args)) {
1812*795d594fSAndroid Build Coastguard Worker       JniValueType result;
1813*795d594fSAndroid Build Coastguard Worker       result.I = baseEnv(env)->GetVersion(env);
1814*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "I", &result)) {
1815*795d594fSAndroid Build Coastguard Worker         return result.I;
1816*795d594fSAndroid Build Coastguard Worker       }
1817*795d594fSAndroid Build Coastguard Worker     }
1818*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
1819*795d594fSAndroid Build Coastguard Worker   }
1820*795d594fSAndroid Build Coastguard Worker 
GetJavaVM(JNIEnv * env,JavaVM ** vm)1821*795d594fSAndroid Build Coastguard Worker   static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1822*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
1823*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
1824*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
1825*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env }, {.p = vm}};
1826*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Ep", args)) {
1827*795d594fSAndroid Build Coastguard Worker       JniValueType result;
1828*795d594fSAndroid Build Coastguard Worker       result.i = baseEnv(env)->GetJavaVM(env, vm);
1829*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "i", &result)) {
1830*795d594fSAndroid Build Coastguard Worker         return result.i;
1831*795d594fSAndroid Build Coastguard Worker       }
1832*795d594fSAndroid Build Coastguard Worker     }
1833*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
1834*795d594fSAndroid Build Coastguard Worker   }
1835*795d594fSAndroid Build Coastguard Worker 
RegisterNatives(JNIEnv * env,jclass c,const JNINativeMethod * methods,jint nMethods)1836*795d594fSAndroid Build Coastguard Worker   static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1837*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
1838*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
1839*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
1840*795d594fSAndroid Build Coastguard Worker     JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1841*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EcpI", args)) {
1842*795d594fSAndroid Build Coastguard Worker       JniValueType result;
1843*795d594fSAndroid Build Coastguard Worker       result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1844*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "i", &result)) {
1845*795d594fSAndroid Build Coastguard Worker         return result.i;
1846*795d594fSAndroid Build Coastguard Worker       }
1847*795d594fSAndroid Build Coastguard Worker     }
1848*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
1849*795d594fSAndroid Build Coastguard Worker   }
1850*795d594fSAndroid Build Coastguard Worker 
UnregisterNatives(JNIEnv * env,jclass c)1851*795d594fSAndroid Build Coastguard Worker   static jint UnregisterNatives(JNIEnv* env, jclass c) {
1852*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
1853*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
1854*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
1855*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env }, {.c = c}};
1856*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Ec", args)) {
1857*795d594fSAndroid Build Coastguard Worker       JniValueType result;
1858*795d594fSAndroid Build Coastguard Worker       result.i = baseEnv(env)->UnregisterNatives(env, c);
1859*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "i", &result)) {
1860*795d594fSAndroid Build Coastguard Worker         return result.i;
1861*795d594fSAndroid Build Coastguard Worker       }
1862*795d594fSAndroid Build Coastguard Worker     }
1863*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
1864*795d594fSAndroid Build Coastguard Worker   }
1865*795d594fSAndroid Build Coastguard Worker 
GetObjectRefType(JNIEnv * env,jobject obj)1866*795d594fSAndroid Build Coastguard Worker   static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
1867*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNIInvalidRefType);
1868*795d594fSAndroid Build Coastguard Worker     // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1869*795d594fSAndroid Build Coastguard Worker     // know the object is invalid. The spec says that passing invalid objects or even ones that
1870*795d594fSAndroid Build Coastguard Worker     // are deleted isn't supported.
1871*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
1872*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
1873*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env }, {.L = obj}};
1874*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EL", args)) {
1875*795d594fSAndroid Build Coastguard Worker       JniValueType result;
1876*795d594fSAndroid Build Coastguard Worker       result.w = baseEnv(env)->GetObjectRefType(env, obj);
1877*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "w", &result)) {
1878*795d594fSAndroid Build Coastguard Worker         return result.w;
1879*795d594fSAndroid Build Coastguard Worker       }
1880*795d594fSAndroid Build Coastguard Worker     }
1881*795d594fSAndroid Build Coastguard Worker     return JNIInvalidRefType;
1882*795d594fSAndroid Build Coastguard Worker   }
1883*795d594fSAndroid Build Coastguard Worker 
DefineClass(JNIEnv * env,const char * name,jobject loader,const jbyte * buf,jsize bufLen)1884*795d594fSAndroid Build Coastguard Worker   static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1885*795d594fSAndroid Build Coastguard Worker                             jsize bufLen) {
1886*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
1887*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
1888*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
1889*795d594fSAndroid Build Coastguard Worker     JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1890*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1891*795d594fSAndroid Build Coastguard Worker       JniValueType result;
1892*795d594fSAndroid Build Coastguard Worker       result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1893*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "c", &result)) {
1894*795d594fSAndroid Build Coastguard Worker         return result.c;
1895*795d594fSAndroid Build Coastguard Worker       }
1896*795d594fSAndroid Build Coastguard Worker     }
1897*795d594fSAndroid Build Coastguard Worker     return nullptr;
1898*795d594fSAndroid Build Coastguard Worker   }
1899*795d594fSAndroid Build Coastguard Worker 
FindClass(JNIEnv * env,const char * name)1900*795d594fSAndroid Build Coastguard Worker   static jclass FindClass(JNIEnv* env, const char* name) {
1901*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
1902*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
1903*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
1904*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.u = name}};
1905*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1906*795d594fSAndroid Build Coastguard Worker       JniValueType result;
1907*795d594fSAndroid Build Coastguard Worker       result.c = baseEnv(env)->FindClass(env, name);
1908*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "c", &result)) {
1909*795d594fSAndroid Build Coastguard Worker         return result.c;
1910*795d594fSAndroid Build Coastguard Worker       }
1911*795d594fSAndroid Build Coastguard Worker     }
1912*795d594fSAndroid Build Coastguard Worker     return nullptr;
1913*795d594fSAndroid Build Coastguard Worker   }
1914*795d594fSAndroid Build Coastguard Worker 
GetSuperclass(JNIEnv * env,jclass c)1915*795d594fSAndroid Build Coastguard Worker   static jclass GetSuperclass(JNIEnv* env, jclass c) {
1916*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
1917*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
1918*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
1919*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.c = c}};
1920*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Ec", args)) {
1921*795d594fSAndroid Build Coastguard Worker       JniValueType result;
1922*795d594fSAndroid Build Coastguard Worker       result.c = baseEnv(env)->GetSuperclass(env, c);
1923*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "c", &result)) {
1924*795d594fSAndroid Build Coastguard Worker         return result.c;
1925*795d594fSAndroid Build Coastguard Worker       }
1926*795d594fSAndroid Build Coastguard Worker     }
1927*795d594fSAndroid Build Coastguard Worker     return nullptr;
1928*795d594fSAndroid Build Coastguard Worker   }
1929*795d594fSAndroid Build Coastguard Worker 
IsAssignableFrom(JNIEnv * env,jclass c1,jclass c2)1930*795d594fSAndroid Build Coastguard Worker   static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
1931*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE);
1932*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
1933*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
1934*795d594fSAndroid Build Coastguard Worker     JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1935*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Ecc", args)) {
1936*795d594fSAndroid Build Coastguard Worker       JniValueType result;
1937*795d594fSAndroid Build Coastguard Worker       result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1938*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "b", &result)) {
1939*795d594fSAndroid Build Coastguard Worker         return result.b;
1940*795d594fSAndroid Build Coastguard Worker       }
1941*795d594fSAndroid Build Coastguard Worker     }
1942*795d594fSAndroid Build Coastguard Worker     return JNI_FALSE;
1943*795d594fSAndroid Build Coastguard Worker   }
1944*795d594fSAndroid Build Coastguard Worker 
FromReflectedMethod(JNIEnv * env,jobject method)1945*795d594fSAndroid Build Coastguard Worker   static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
1946*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
1947*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
1948*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
1949*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.L = method}};
1950*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1951*795d594fSAndroid Build Coastguard Worker       JniValueType result;
1952*795d594fSAndroid Build Coastguard Worker       result.m = baseEnv(env)->FromReflectedMethod(env, method);
1953*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "m", &result)) {
1954*795d594fSAndroid Build Coastguard Worker         return result.m;
1955*795d594fSAndroid Build Coastguard Worker       }
1956*795d594fSAndroid Build Coastguard Worker     }
1957*795d594fSAndroid Build Coastguard Worker     return nullptr;
1958*795d594fSAndroid Build Coastguard Worker   }
1959*795d594fSAndroid Build Coastguard Worker 
FromReflectedField(JNIEnv * env,jobject field)1960*795d594fSAndroid Build Coastguard Worker   static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
1961*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
1962*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
1963*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
1964*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.L = field}};
1965*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1966*795d594fSAndroid Build Coastguard Worker       JniValueType result;
1967*795d594fSAndroid Build Coastguard Worker       result.f = baseEnv(env)->FromReflectedField(env, field);
1968*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "f", &result)) {
1969*795d594fSAndroid Build Coastguard Worker         return result.f;
1970*795d594fSAndroid Build Coastguard Worker       }
1971*795d594fSAndroid Build Coastguard Worker     }
1972*795d594fSAndroid Build Coastguard Worker     return nullptr;
1973*795d594fSAndroid Build Coastguard Worker   }
1974*795d594fSAndroid Build Coastguard Worker 
ToReflectedMethod(JNIEnv * env,jclass cls,jmethodID mid,jboolean isStatic)1975*795d594fSAndroid Build Coastguard Worker   static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
1976*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
1977*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
1978*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
1979*795d594fSAndroid Build Coastguard Worker     JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.I = isStatic}};
1980*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Ecmb", args)) {
1981*795d594fSAndroid Build Coastguard Worker       JniValueType result;
1982*795d594fSAndroid Build Coastguard Worker       result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1983*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1984*795d594fSAndroid Build Coastguard Worker         DCHECK(sc.CheckReflectedMethod(soa, result.L));
1985*795d594fSAndroid Build Coastguard Worker         return result.L;
1986*795d594fSAndroid Build Coastguard Worker       }
1987*795d594fSAndroid Build Coastguard Worker     }
1988*795d594fSAndroid Build Coastguard Worker     return nullptr;
1989*795d594fSAndroid Build Coastguard Worker   }
1990*795d594fSAndroid Build Coastguard Worker 
ToReflectedField(JNIEnv * env,jclass cls,jfieldID fid,jboolean isStatic)1991*795d594fSAndroid Build Coastguard Worker   static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
1992*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
1993*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
1994*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
1995*795d594fSAndroid Build Coastguard Worker     JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.I = isStatic}};
1996*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Ecfb", args)) {
1997*795d594fSAndroid Build Coastguard Worker       JniValueType result;
1998*795d594fSAndroid Build Coastguard Worker       result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1999*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
2000*795d594fSAndroid Build Coastguard Worker         DCHECK(sc.CheckReflectedField(soa, result.L));
2001*795d594fSAndroid Build Coastguard Worker         return result.L;
2002*795d594fSAndroid Build Coastguard Worker       }
2003*795d594fSAndroid Build Coastguard Worker     }
2004*795d594fSAndroid Build Coastguard Worker     return nullptr;
2005*795d594fSAndroid Build Coastguard Worker   }
2006*795d594fSAndroid Build Coastguard Worker 
Throw(JNIEnv * env,jthrowable obj)2007*795d594fSAndroid Build Coastguard Worker   static jint Throw(JNIEnv* env, jthrowable obj) {
2008*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2009*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2010*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
2011*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.t = obj}};
2012*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
2013*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2014*795d594fSAndroid Build Coastguard Worker       result.i = baseEnv(env)->Throw(env, obj);
2015*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "i", &result)) {
2016*795d594fSAndroid Build Coastguard Worker         return result.i;
2017*795d594fSAndroid Build Coastguard Worker       }
2018*795d594fSAndroid Build Coastguard Worker     }
2019*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
2020*795d594fSAndroid Build Coastguard Worker   }
2021*795d594fSAndroid Build Coastguard Worker 
ThrowNew(JNIEnv * env,jclass c,const char * message)2022*795d594fSAndroid Build Coastguard Worker   static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
2023*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2024*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2025*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2026*795d594fSAndroid Build Coastguard Worker     JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
2027*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
2028*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2029*795d594fSAndroid Build Coastguard Worker       result.i = baseEnv(env)->ThrowNew(env, c, message);
2030*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "i", &result)) {
2031*795d594fSAndroid Build Coastguard Worker         return result.i;
2032*795d594fSAndroid Build Coastguard Worker       }
2033*795d594fSAndroid Build Coastguard Worker     }
2034*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
2035*795d594fSAndroid Build Coastguard Worker   }
2036*795d594fSAndroid Build Coastguard Worker 
ExceptionOccurred(JNIEnv * env)2037*795d594fSAndroid Build Coastguard Worker   static jthrowable ExceptionOccurred(JNIEnv* env) {
2038*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2039*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2040*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2041*795d594fSAndroid Build Coastguard Worker     JniValueType args[1] = {{.E = env}};
2042*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "E", args)) {
2043*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2044*795d594fSAndroid Build Coastguard Worker       result.t = baseEnv(env)->ExceptionOccurred(env);
2045*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "t", &result)) {
2046*795d594fSAndroid Build Coastguard Worker         return result.t;
2047*795d594fSAndroid Build Coastguard Worker       }
2048*795d594fSAndroid Build Coastguard Worker     }
2049*795d594fSAndroid Build Coastguard Worker     return nullptr;
2050*795d594fSAndroid Build Coastguard Worker   }
2051*795d594fSAndroid Build Coastguard Worker 
ExceptionDescribe(JNIEnv * env)2052*795d594fSAndroid Build Coastguard Worker   static void ExceptionDescribe(JNIEnv* env) {
2053*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
2054*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2055*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2056*795d594fSAndroid Build Coastguard Worker     JniValueType args[1] = {{.E = env}};
2057*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "E", args)) {
2058*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2059*795d594fSAndroid Build Coastguard Worker       baseEnv(env)->ExceptionDescribe(env);
2060*795d594fSAndroid Build Coastguard Worker       result.V = nullptr;
2061*795d594fSAndroid Build Coastguard Worker       sc.Check(soa, false, "V", &result);
2062*795d594fSAndroid Build Coastguard Worker     }
2063*795d594fSAndroid Build Coastguard Worker   }
2064*795d594fSAndroid Build Coastguard Worker 
ExceptionClear(JNIEnv * env)2065*795d594fSAndroid Build Coastguard Worker   static void ExceptionClear(JNIEnv* env) {
2066*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
2067*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2068*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2069*795d594fSAndroid Build Coastguard Worker     JniValueType args[1] = {{.E = env}};
2070*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "E", args)) {
2071*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2072*795d594fSAndroid Build Coastguard Worker       baseEnv(env)->ExceptionClear(env);
2073*795d594fSAndroid Build Coastguard Worker       result.V = nullptr;
2074*795d594fSAndroid Build Coastguard Worker       sc.Check(soa, false, "V", &result);
2075*795d594fSAndroid Build Coastguard Worker     }
2076*795d594fSAndroid Build Coastguard Worker   }
2077*795d594fSAndroid Build Coastguard Worker 
ExceptionCheck(JNIEnv * env)2078*795d594fSAndroid Build Coastguard Worker   static jboolean ExceptionCheck(JNIEnv* env) {
2079*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE);
2080*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2081*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
2082*795d594fSAndroid Build Coastguard Worker     JniValueType args[1] = {{.E = env}};
2083*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "E", args)) {
2084*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2085*795d594fSAndroid Build Coastguard Worker       result.b = baseEnv(env)->ExceptionCheck(env);
2086*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "b", &result)) {
2087*795d594fSAndroid Build Coastguard Worker         return result.b;
2088*795d594fSAndroid Build Coastguard Worker       }
2089*795d594fSAndroid Build Coastguard Worker     }
2090*795d594fSAndroid Build Coastguard Worker     return JNI_FALSE;
2091*795d594fSAndroid Build Coastguard Worker   }
2092*795d594fSAndroid Build Coastguard Worker 
FatalError(JNIEnv * env,const char * msg)2093*795d594fSAndroid Build Coastguard Worker   static void FatalError(JNIEnv* env, const char* msg) {
2094*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
2095*795d594fSAndroid Build Coastguard Worker     // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
2096*795d594fSAndroid Build Coastguard Worker     // but you're about to abort anyway, and it's quite likely that you have a pending exception,
2097*795d594fSAndroid Build Coastguard Worker     // and it's not unimaginable that you don't know that you do. So we allow it.
2098*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2099*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
2100*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.u = msg}};
2101*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Eu", args)) {
2102*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2103*795d594fSAndroid Build Coastguard Worker       baseEnv(env)->FatalError(env, msg);
2104*795d594fSAndroid Build Coastguard Worker       // Unreachable.
2105*795d594fSAndroid Build Coastguard Worker       result.V = nullptr;
2106*795d594fSAndroid Build Coastguard Worker       sc.Check(soa, false, "V", &result);
2107*795d594fSAndroid Build Coastguard Worker     }
2108*795d594fSAndroid Build Coastguard Worker   }
2109*795d594fSAndroid Build Coastguard Worker 
PushLocalFrame(JNIEnv * env,jint capacity)2110*795d594fSAndroid Build Coastguard Worker   static jint PushLocalFrame(JNIEnv* env, jint capacity) {
2111*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2112*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2113*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2114*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.I = capacity}};
2115*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EI", args)) {
2116*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2117*795d594fSAndroid Build Coastguard Worker       result.i = baseEnv(env)->PushLocalFrame(env, capacity);
2118*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "i", &result)) {
2119*795d594fSAndroid Build Coastguard Worker         return result.i;
2120*795d594fSAndroid Build Coastguard Worker       }
2121*795d594fSAndroid Build Coastguard Worker     }
2122*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
2123*795d594fSAndroid Build Coastguard Worker   }
2124*795d594fSAndroid Build Coastguard Worker 
PopLocalFrame(JNIEnv * env,jobject res)2125*795d594fSAndroid Build Coastguard Worker   static jobject PopLocalFrame(JNIEnv* env, jobject res) {
2126*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2127*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2128*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2129*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.L = res}};
2130*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EL", args)) {
2131*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2132*795d594fSAndroid Build Coastguard Worker       result.L = baseEnv(env)->PopLocalFrame(env, res);
2133*795d594fSAndroid Build Coastguard Worker       sc.Check(soa, false, "L", &result);
2134*795d594fSAndroid Build Coastguard Worker       return result.L;
2135*795d594fSAndroid Build Coastguard Worker     }
2136*795d594fSAndroid Build Coastguard Worker     return nullptr;
2137*795d594fSAndroid Build Coastguard Worker   }
2138*795d594fSAndroid Build Coastguard Worker 
NewGlobalRef(JNIEnv * env,jobject obj)2139*795d594fSAndroid Build Coastguard Worker   static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
2140*795d594fSAndroid Build Coastguard Worker     return NewRef(__FUNCTION__, env, obj, kGlobal);
2141*795d594fSAndroid Build Coastguard Worker   }
2142*795d594fSAndroid Build Coastguard Worker 
NewLocalRef(JNIEnv * env,jobject obj)2143*795d594fSAndroid Build Coastguard Worker   static jobject NewLocalRef(JNIEnv* env, jobject obj) {
2144*795d594fSAndroid Build Coastguard Worker     return NewRef(__FUNCTION__, env, obj, kLocal);
2145*795d594fSAndroid Build Coastguard Worker   }
2146*795d594fSAndroid Build Coastguard Worker 
NewWeakGlobalRef(JNIEnv * env,jobject obj)2147*795d594fSAndroid Build Coastguard Worker   static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
2148*795d594fSAndroid Build Coastguard Worker     return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
2149*795d594fSAndroid Build Coastguard Worker   }
2150*795d594fSAndroid Build Coastguard Worker 
DeleteGlobalRef(JNIEnv * env,jobject obj)2151*795d594fSAndroid Build Coastguard Worker   static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
2152*795d594fSAndroid Build Coastguard Worker     DeleteRef(__FUNCTION__, env, obj, kGlobal);
2153*795d594fSAndroid Build Coastguard Worker   }
2154*795d594fSAndroid Build Coastguard Worker 
DeleteWeakGlobalRef(JNIEnv * env,jweak obj)2155*795d594fSAndroid Build Coastguard Worker   static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
2156*795d594fSAndroid Build Coastguard Worker     DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
2157*795d594fSAndroid Build Coastguard Worker   }
2158*795d594fSAndroid Build Coastguard Worker 
DeleteLocalRef(JNIEnv * env,jobject obj)2159*795d594fSAndroid Build Coastguard Worker   static void DeleteLocalRef(JNIEnv* env, jobject obj) {
2160*795d594fSAndroid Build Coastguard Worker     DeleteRef(__FUNCTION__, env, obj, kLocal);
2161*795d594fSAndroid Build Coastguard Worker   }
2162*795d594fSAndroid Build Coastguard Worker 
EnsureLocalCapacity(JNIEnv * env,jint capacity)2163*795d594fSAndroid Build Coastguard Worker   static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
2164*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2165*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2166*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
2167*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.I = capacity}};
2168*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EI", args)) {
2169*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2170*795d594fSAndroid Build Coastguard Worker       result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
2171*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "i", &result)) {
2172*795d594fSAndroid Build Coastguard Worker         return result.i;
2173*795d594fSAndroid Build Coastguard Worker       }
2174*795d594fSAndroid Build Coastguard Worker     }
2175*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
2176*795d594fSAndroid Build Coastguard Worker   }
2177*795d594fSAndroid Build Coastguard Worker 
IsSameObject(JNIEnv * env,jobject ref1,jobject ref2)2178*795d594fSAndroid Build Coastguard Worker   static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
2179*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE);
2180*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2181*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
2182*795d594fSAndroid Build Coastguard Worker     JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
2183*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "ELL", args)) {
2184*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2185*795d594fSAndroid Build Coastguard Worker       result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
2186*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "b", &result)) {
2187*795d594fSAndroid Build Coastguard Worker         return result.b;
2188*795d594fSAndroid Build Coastguard Worker       }
2189*795d594fSAndroid Build Coastguard Worker     }
2190*795d594fSAndroid Build Coastguard Worker     return JNI_FALSE;
2191*795d594fSAndroid Build Coastguard Worker   }
2192*795d594fSAndroid Build Coastguard Worker 
AllocObject(JNIEnv * env,jclass c)2193*795d594fSAndroid Build Coastguard Worker   static jobject AllocObject(JNIEnv* env, jclass c) {
2194*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2195*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2196*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
2197*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.c = c}};
2198*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
2199*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2200*795d594fSAndroid Build Coastguard Worker       result.L = baseEnv(env)->AllocObject(env, c);
2201*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "L", &result)) {
2202*795d594fSAndroid Build Coastguard Worker         return result.L;
2203*795d594fSAndroid Build Coastguard Worker       }
2204*795d594fSAndroid Build Coastguard Worker     }
2205*795d594fSAndroid Build Coastguard Worker     return nullptr;
2206*795d594fSAndroid Build Coastguard Worker   }
2207*795d594fSAndroid Build Coastguard Worker 
NewObjectV(JNIEnv * env,jclass c,jmethodID mid,va_list vargs)2208*795d594fSAndroid Build Coastguard Worker   static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2209*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2210*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2211*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
2212*795d594fSAndroid Build Coastguard Worker     VarArgs rest(mid, vargs);
2213*795d594fSAndroid Build Coastguard Worker     JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2214*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
2215*795d594fSAndroid Build Coastguard Worker         sc.CheckConstructor(mid)) {
2216*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2217*795d594fSAndroid Build Coastguard Worker       result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
2218*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "L", &result)) {
2219*795d594fSAndroid Build Coastguard Worker         return result.L;
2220*795d594fSAndroid Build Coastguard Worker       }
2221*795d594fSAndroid Build Coastguard Worker     }
2222*795d594fSAndroid Build Coastguard Worker     return nullptr;
2223*795d594fSAndroid Build Coastguard Worker   }
2224*795d594fSAndroid Build Coastguard Worker 
NewObject(JNIEnv * env,jclass c,jmethodID mid,...)2225*795d594fSAndroid Build Coastguard Worker   static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
2226*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2227*795d594fSAndroid Build Coastguard Worker     va_list args;
2228*795d594fSAndroid Build Coastguard Worker     va_start(args, mid);
2229*795d594fSAndroid Build Coastguard Worker     jobject result = NewObjectV(env, c, mid, args);
2230*795d594fSAndroid Build Coastguard Worker     va_end(args);
2231*795d594fSAndroid Build Coastguard Worker     return result;
2232*795d594fSAndroid Build Coastguard Worker   }
2233*795d594fSAndroid Build Coastguard Worker 
NewObjectA(JNIEnv * env,jclass c,jmethodID mid,const jvalue * vargs)2234*795d594fSAndroid Build Coastguard Worker   static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, const jvalue* vargs) {
2235*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2236*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2237*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
2238*795d594fSAndroid Build Coastguard Worker     VarArgs rest(mid, vargs);
2239*795d594fSAndroid Build Coastguard Worker     JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2240*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
2241*795d594fSAndroid Build Coastguard Worker         sc.CheckConstructor(mid)) {
2242*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2243*795d594fSAndroid Build Coastguard Worker       result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
2244*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "L", &result)) {
2245*795d594fSAndroid Build Coastguard Worker         return result.L;
2246*795d594fSAndroid Build Coastguard Worker       }
2247*795d594fSAndroid Build Coastguard Worker     }
2248*795d594fSAndroid Build Coastguard Worker     return nullptr;
2249*795d594fSAndroid Build Coastguard Worker   }
2250*795d594fSAndroid Build Coastguard Worker 
GetObjectClass(JNIEnv * env,jobject obj)2251*795d594fSAndroid Build Coastguard Worker   static jclass GetObjectClass(JNIEnv* env, jobject obj) {
2252*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2253*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2254*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
2255*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.L = obj}};
2256*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EL", args)) {
2257*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2258*795d594fSAndroid Build Coastguard Worker       result.c = baseEnv(env)->GetObjectClass(env, obj);
2259*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "c", &result)) {
2260*795d594fSAndroid Build Coastguard Worker         return result.c;
2261*795d594fSAndroid Build Coastguard Worker       }
2262*795d594fSAndroid Build Coastguard Worker     }
2263*795d594fSAndroid Build Coastguard Worker     return nullptr;
2264*795d594fSAndroid Build Coastguard Worker   }
2265*795d594fSAndroid Build Coastguard Worker 
IsInstanceOf(JNIEnv * env,jobject obj,jclass c)2266*795d594fSAndroid Build Coastguard Worker   static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
2267*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE);
2268*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2269*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
2270*795d594fSAndroid Build Coastguard Worker     JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
2271*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "ELc", args)) {
2272*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2273*795d594fSAndroid Build Coastguard Worker       result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
2274*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "b", &result)) {
2275*795d594fSAndroid Build Coastguard Worker         return result.b;
2276*795d594fSAndroid Build Coastguard Worker       }
2277*795d594fSAndroid Build Coastguard Worker     }
2278*795d594fSAndroid Build Coastguard Worker     return JNI_FALSE;
2279*795d594fSAndroid Build Coastguard Worker   }
2280*795d594fSAndroid Build Coastguard Worker 
GetMethodID(JNIEnv * env,jclass c,const char * name,const char * sig)2281*795d594fSAndroid Build Coastguard Worker   static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2282*795d594fSAndroid Build Coastguard Worker     return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
2283*795d594fSAndroid Build Coastguard Worker   }
2284*795d594fSAndroid Build Coastguard Worker 
GetStaticMethodID(JNIEnv * env,jclass c,const char * name,const char * sig)2285*795d594fSAndroid Build Coastguard Worker   static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2286*795d594fSAndroid Build Coastguard Worker     return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
2287*795d594fSAndroid Build Coastguard Worker   }
2288*795d594fSAndroid Build Coastguard Worker 
GetFieldID(JNIEnv * env,jclass c,const char * name,const char * sig)2289*795d594fSAndroid Build Coastguard Worker   static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2290*795d594fSAndroid Build Coastguard Worker     return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
2291*795d594fSAndroid Build Coastguard Worker   }
2292*795d594fSAndroid Build Coastguard Worker 
GetStaticFieldID(JNIEnv * env,jclass c,const char * name,const char * sig)2293*795d594fSAndroid Build Coastguard Worker   static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2294*795d594fSAndroid Build Coastguard Worker     return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
2295*795d594fSAndroid Build Coastguard Worker   }
2296*795d594fSAndroid Build Coastguard Worker 
2297*795d594fSAndroid Build Coastguard Worker #define FIELD_ACCESSORS(jtype, name, ptype, shorty, slot_sized_shorty)  \
2298*795d594fSAndroid Build Coastguard Worker   static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
2299*795d594fSAndroid Build Coastguard Worker     return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
2300*795d594fSAndroid Build Coastguard Worker   } \
2301*795d594fSAndroid Build Coastguard Worker   \
2302*795d594fSAndroid Build Coastguard Worker   static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
2303*795d594fSAndroid Build Coastguard Worker     return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
2304*795d594fSAndroid Build Coastguard Worker   } \
2305*795d594fSAndroid Build Coastguard Worker   \
2306*795d594fSAndroid Build Coastguard Worker   static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
2307*795d594fSAndroid Build Coastguard Worker     JniValueType value; \
2308*795d594fSAndroid Build Coastguard Worker     value.slot_sized_shorty = v; \
2309*795d594fSAndroid Build Coastguard Worker     SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
2310*795d594fSAndroid Build Coastguard Worker   } \
2311*795d594fSAndroid Build Coastguard Worker   \
2312*795d594fSAndroid Build Coastguard Worker   static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
2313*795d594fSAndroid Build Coastguard Worker     JniValueType value; \
2314*795d594fSAndroid Build Coastguard Worker     value.slot_sized_shorty = v; \
2315*795d594fSAndroid Build Coastguard Worker     SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
2316*795d594fSAndroid Build Coastguard Worker   }
2317*795d594fSAndroid Build Coastguard Worker 
FIELD_ACCESSORS(jobject,Object,Primitive::kPrimNot,L,L)2318*795d594fSAndroid Build Coastguard Worker   FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L, L)
2319*795d594fSAndroid Build Coastguard Worker   FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z, I)
2320*795d594fSAndroid Build Coastguard Worker   FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B, I)
2321*795d594fSAndroid Build Coastguard Worker   FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C, I)
2322*795d594fSAndroid Build Coastguard Worker   FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S, I)
2323*795d594fSAndroid Build Coastguard Worker   FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I, I)
2324*795d594fSAndroid Build Coastguard Worker   FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J, J)
2325*795d594fSAndroid Build Coastguard Worker   FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F, F)
2326*795d594fSAndroid Build Coastguard Worker   FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D, D)
2327*795d594fSAndroid Build Coastguard Worker #undef FIELD_ACCESSORS
2328*795d594fSAndroid Build Coastguard Worker 
2329*795d594fSAndroid Build Coastguard Worker   static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, const jvalue* vargs) {
2330*795d594fSAndroid Build Coastguard Worker     CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2331*795d594fSAndroid Build Coastguard Worker   }
2332*795d594fSAndroid Build Coastguard Worker 
CallNonvirtualVoidMethodA(JNIEnv * env,jobject obj,jclass c,jmethodID mid,const jvalue * vargs)2333*795d594fSAndroid Build Coastguard Worker   static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2334*795d594fSAndroid Build Coastguard Worker                                         const jvalue* vargs) {
2335*795d594fSAndroid Build Coastguard Worker     CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2336*795d594fSAndroid Build Coastguard Worker   }
2337*795d594fSAndroid Build Coastguard Worker 
CallStaticVoidMethodA(JNIEnv * env,jclass c,jmethodID mid,const jvalue * vargs)2338*795d594fSAndroid Build Coastguard Worker   static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, const jvalue* vargs) {
2339*795d594fSAndroid Build Coastguard Worker     CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2340*795d594fSAndroid Build Coastguard Worker   }
2341*795d594fSAndroid Build Coastguard Worker 
CallVoidMethodV(JNIEnv * env,jobject obj,jmethodID mid,va_list vargs)2342*795d594fSAndroid Build Coastguard Worker   static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
2343*795d594fSAndroid Build Coastguard Worker     CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2344*795d594fSAndroid Build Coastguard Worker   }
2345*795d594fSAndroid Build Coastguard Worker 
CallNonvirtualVoidMethodV(JNIEnv * env,jobject obj,jclass c,jmethodID mid,va_list vargs)2346*795d594fSAndroid Build Coastguard Worker   static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2347*795d594fSAndroid Build Coastguard Worker                                         va_list vargs) {
2348*795d594fSAndroid Build Coastguard Worker     CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2349*795d594fSAndroid Build Coastguard Worker   }
2350*795d594fSAndroid Build Coastguard Worker 
2351*795d594fSAndroid Build Coastguard Worker   NO_STACK_PROTECTOR
CallStaticVoidMethodV(JNIEnv * env,jclass c,jmethodID mid,va_list vargs)2352*795d594fSAndroid Build Coastguard Worker   static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2353*795d594fSAndroid Build Coastguard Worker     CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2354*795d594fSAndroid Build Coastguard Worker   }
2355*795d594fSAndroid Build Coastguard Worker 
CallVoidMethod(JNIEnv * env,jobject obj,jmethodID mid,...)2356*795d594fSAndroid Build Coastguard Worker   static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
2357*795d594fSAndroid Build Coastguard Worker     va_list vargs;
2358*795d594fSAndroid Build Coastguard Worker     va_start(vargs, mid);
2359*795d594fSAndroid Build Coastguard Worker     CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2360*795d594fSAndroid Build Coastguard Worker     va_end(vargs);
2361*795d594fSAndroid Build Coastguard Worker   }
2362*795d594fSAndroid Build Coastguard Worker 
CallNonvirtualVoidMethod(JNIEnv * env,jobject obj,jclass c,jmethodID mid,...)2363*795d594fSAndroid Build Coastguard Worker   static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
2364*795d594fSAndroid Build Coastguard Worker     va_list vargs;
2365*795d594fSAndroid Build Coastguard Worker     va_start(vargs, mid);
2366*795d594fSAndroid Build Coastguard Worker     CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2367*795d594fSAndroid Build Coastguard Worker     va_end(vargs);
2368*795d594fSAndroid Build Coastguard Worker   }
2369*795d594fSAndroid Build Coastguard Worker 
CallStaticVoidMethod(JNIEnv * env,jclass c,jmethodID mid,...)2370*795d594fSAndroid Build Coastguard Worker   static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
2371*795d594fSAndroid Build Coastguard Worker     va_list vargs;
2372*795d594fSAndroid Build Coastguard Worker     va_start(vargs, mid);
2373*795d594fSAndroid Build Coastguard Worker     CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2374*795d594fSAndroid Build Coastguard Worker     va_end(vargs);
2375*795d594fSAndroid Build Coastguard Worker   }
2376*795d594fSAndroid Build Coastguard Worker 
2377*795d594fSAndroid Build Coastguard Worker #define CALL(rtype, name, ptype, shorty) \
2378*795d594fSAndroid Build Coastguard Worker   static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, const jvalue* vargs) { \
2379*795d594fSAndroid Build Coastguard Worker     return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2380*795d594fSAndroid Build Coastguard Worker   } \
2381*795d594fSAndroid Build Coastguard Worker   \
2382*795d594fSAndroid Build Coastguard Worker   static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2383*795d594fSAndroid Build Coastguard Worker                                              const jvalue* vargs) { \
2384*795d594fSAndroid Build Coastguard Worker     return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2385*795d594fSAndroid Build Coastguard Worker   } \
2386*795d594fSAndroid Build Coastguard Worker   \
2387*795d594fSAndroid Build Coastguard Worker   static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, const jvalue* vargs) { \
2388*795d594fSAndroid Build Coastguard Worker     return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2389*795d594fSAndroid Build Coastguard Worker   } \
2390*795d594fSAndroid Build Coastguard Worker   \
2391*795d594fSAndroid Build Coastguard Worker   static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
2392*795d594fSAndroid Build Coastguard Worker     return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2393*795d594fSAndroid Build Coastguard Worker   } \
2394*795d594fSAndroid Build Coastguard Worker   \
2395*795d594fSAndroid Build Coastguard Worker   static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2396*795d594fSAndroid Build Coastguard Worker                                              va_list vargs) { \
2397*795d594fSAndroid Build Coastguard Worker     return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2398*795d594fSAndroid Build Coastguard Worker   } \
2399*795d594fSAndroid Build Coastguard Worker   \
2400*795d594fSAndroid Build Coastguard Worker   static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
2401*795d594fSAndroid Build Coastguard Worker     return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2402*795d594fSAndroid Build Coastguard Worker   } \
2403*795d594fSAndroid Build Coastguard Worker   \
2404*795d594fSAndroid Build Coastguard Worker   static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
2405*795d594fSAndroid Build Coastguard Worker     va_list vargs; \
2406*795d594fSAndroid Build Coastguard Worker     va_start(vargs, mid); \
2407*795d594fSAndroid Build Coastguard Worker     rtype result = \
2408*795d594fSAndroid Build Coastguard Worker         CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2409*795d594fSAndroid Build Coastguard Worker     va_end(vargs); \
2410*795d594fSAndroid Build Coastguard Worker     return result; \
2411*795d594fSAndroid Build Coastguard Worker   } \
2412*795d594fSAndroid Build Coastguard Worker   \
2413*795d594fSAndroid Build Coastguard Worker   static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2414*795d594fSAndroid Build Coastguard Worker                                             ...) { \
2415*795d594fSAndroid Build Coastguard Worker     va_list vargs; \
2416*795d594fSAndroid Build Coastguard Worker     va_start(vargs, mid); \
2417*795d594fSAndroid Build Coastguard Worker     rtype result = \
2418*795d594fSAndroid Build Coastguard Worker         CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2419*795d594fSAndroid Build Coastguard Worker     va_end(vargs); \
2420*795d594fSAndroid Build Coastguard Worker     return result; \
2421*795d594fSAndroid Build Coastguard Worker   } \
2422*795d594fSAndroid Build Coastguard Worker   \
2423*795d594fSAndroid Build Coastguard Worker   static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2424*795d594fSAndroid Build Coastguard Worker     va_list vargs; \
2425*795d594fSAndroid Build Coastguard Worker     va_start(vargs, mid); \
2426*795d594fSAndroid Build Coastguard Worker     rtype result = \
2427*795d594fSAndroid Build Coastguard Worker         CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2428*795d594fSAndroid Build Coastguard Worker     va_end(vargs); \
2429*795d594fSAndroid Build Coastguard Worker     return result; \
2430*795d594fSAndroid Build Coastguard Worker   }
2431*795d594fSAndroid Build Coastguard Worker 
CALL(jobject,Object,Primitive::kPrimNot,L)2432*795d594fSAndroid Build Coastguard Worker   CALL(jobject, Object, Primitive::kPrimNot, L)
2433*795d594fSAndroid Build Coastguard Worker   CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2434*795d594fSAndroid Build Coastguard Worker   CALL(jbyte, Byte, Primitive::kPrimByte, B)
2435*795d594fSAndroid Build Coastguard Worker   CALL(jchar, Char, Primitive::kPrimChar, C)
2436*795d594fSAndroid Build Coastguard Worker   CALL(jshort, Short, Primitive::kPrimShort, S)
2437*795d594fSAndroid Build Coastguard Worker   CALL(jint, Int, Primitive::kPrimInt, I)
2438*795d594fSAndroid Build Coastguard Worker   CALL(jlong, Long, Primitive::kPrimLong, J)
2439*795d594fSAndroid Build Coastguard Worker   CALL(jfloat, Float, Primitive::kPrimFloat, F)
2440*795d594fSAndroid Build Coastguard Worker   CALL(jdouble, Double, Primitive::kPrimDouble, D)
2441*795d594fSAndroid Build Coastguard Worker #undef CALL
2442*795d594fSAndroid Build Coastguard Worker 
2443*795d594fSAndroid Build Coastguard Worker   static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
2444*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2445*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2446*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
2447*795d594fSAndroid Build Coastguard Worker     JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2448*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Epz", args)) {
2449*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2450*795d594fSAndroid Build Coastguard Worker       result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2451*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "s", &result)) {
2452*795d594fSAndroid Build Coastguard Worker         return result.s;
2453*795d594fSAndroid Build Coastguard Worker       }
2454*795d594fSAndroid Build Coastguard Worker     }
2455*795d594fSAndroid Build Coastguard Worker     return nullptr;
2456*795d594fSAndroid Build Coastguard Worker   }
2457*795d594fSAndroid Build Coastguard Worker 
NewStringUTF(JNIEnv * env,const char * chars)2458*795d594fSAndroid Build Coastguard Worker   static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2459*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2460*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2461*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2462*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.u = chars}};
2463*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Eu", args)) {
2464*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2465*795d594fSAndroid Build Coastguard Worker       // TODO: stale? show pointer and truncate string.
2466*795d594fSAndroid Build Coastguard Worker       result.s = baseEnv(env)->NewStringUTF(env, chars);
2467*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "s", &result)) {
2468*795d594fSAndroid Build Coastguard Worker         return result.s;
2469*795d594fSAndroid Build Coastguard Worker       }
2470*795d594fSAndroid Build Coastguard Worker     }
2471*795d594fSAndroid Build Coastguard Worker     return nullptr;
2472*795d594fSAndroid Build Coastguard Worker   }
2473*795d594fSAndroid Build Coastguard Worker 
GetStringLength(JNIEnv * env,jstring string)2474*795d594fSAndroid Build Coastguard Worker   static jsize GetStringLength(JNIEnv* env, jstring string) {
2475*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2476*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2477*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2478*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.s = string}};
2479*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Es", args)) {
2480*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2481*795d594fSAndroid Build Coastguard Worker       result.z = baseEnv(env)->GetStringLength(env, string);
2482*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "z", &result)) {
2483*795d594fSAndroid Build Coastguard Worker         return result.z;
2484*795d594fSAndroid Build Coastguard Worker       }
2485*795d594fSAndroid Build Coastguard Worker     }
2486*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
2487*795d594fSAndroid Build Coastguard Worker   }
2488*795d594fSAndroid Build Coastguard Worker 
GetStringUTFLength(JNIEnv * env,jstring string)2489*795d594fSAndroid Build Coastguard Worker   static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2490*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2491*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2492*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2493*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.s = string}};
2494*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Es", args)) {
2495*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2496*795d594fSAndroid Build Coastguard Worker       result.z = baseEnv(env)->GetStringUTFLength(env, string);
2497*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "z", &result)) {
2498*795d594fSAndroid Build Coastguard Worker         return result.z;
2499*795d594fSAndroid Build Coastguard Worker       }
2500*795d594fSAndroid Build Coastguard Worker     }
2501*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
2502*795d594fSAndroid Build Coastguard Worker   }
2503*795d594fSAndroid Build Coastguard Worker 
GetStringChars(JNIEnv * env,jstring string,jboolean * is_copy)2504*795d594fSAndroid Build Coastguard Worker   static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2505*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2506*795d594fSAndroid Build Coastguard Worker                                                                  is_copy, false, false));
2507*795d594fSAndroid Build Coastguard Worker   }
2508*795d594fSAndroid Build Coastguard Worker 
GetStringUTFChars(JNIEnv * env,jstring string,jboolean * is_copy)2509*795d594fSAndroid Build Coastguard Worker   static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2510*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2511*795d594fSAndroid Build Coastguard Worker                                                                 is_copy, true, false));
2512*795d594fSAndroid Build Coastguard Worker   }
2513*795d594fSAndroid Build Coastguard Worker 
GetStringCritical(JNIEnv * env,jstring string,jboolean * is_copy)2514*795d594fSAndroid Build Coastguard Worker   static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2515*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2516*795d594fSAndroid Build Coastguard Worker                                                                  is_copy, false, true));
2517*795d594fSAndroid Build Coastguard Worker   }
2518*795d594fSAndroid Build Coastguard Worker 
ReleaseStringChars(JNIEnv * env,jstring string,const jchar * chars)2519*795d594fSAndroid Build Coastguard Worker   static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2520*795d594fSAndroid Build Coastguard Worker     ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2521*795d594fSAndroid Build Coastguard Worker   }
2522*795d594fSAndroid Build Coastguard Worker 
ReleaseStringUTFChars(JNIEnv * env,jstring string,const char * utf)2523*795d594fSAndroid Build Coastguard Worker   static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2524*795d594fSAndroid Build Coastguard Worker     ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2525*795d594fSAndroid Build Coastguard Worker   }
2526*795d594fSAndroid Build Coastguard Worker 
ReleaseStringCritical(JNIEnv * env,jstring string,const jchar * chars)2527*795d594fSAndroid Build Coastguard Worker   static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2528*795d594fSAndroid Build Coastguard Worker     ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2529*795d594fSAndroid Build Coastguard Worker   }
2530*795d594fSAndroid Build Coastguard Worker 
GetStringRegion(JNIEnv * env,jstring string,jsize start,jsize len,jchar * buf)2531*795d594fSAndroid Build Coastguard Worker   static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
2532*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
2533*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2534*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2535*795d594fSAndroid Build Coastguard Worker     JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2536*795d594fSAndroid Build Coastguard Worker     // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2537*795d594fSAndroid Build Coastguard Worker     // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2538*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EsIIp", args)) {
2539*795d594fSAndroid Build Coastguard Worker       baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2540*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2541*795d594fSAndroid Build Coastguard Worker       result.V = nullptr;
2542*795d594fSAndroid Build Coastguard Worker       sc.Check(soa, false, "V", &result);
2543*795d594fSAndroid Build Coastguard Worker     }
2544*795d594fSAndroid Build Coastguard Worker   }
2545*795d594fSAndroid Build Coastguard Worker 
GetStringUTFRegion(JNIEnv * env,jstring string,jsize start,jsize len,char * buf)2546*795d594fSAndroid Build Coastguard Worker   static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2547*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
2548*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2549*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2550*795d594fSAndroid Build Coastguard Worker     JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2551*795d594fSAndroid Build Coastguard Worker     // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2552*795d594fSAndroid Build Coastguard Worker     // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2553*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EsIIp", args)) {
2554*795d594fSAndroid Build Coastguard Worker       baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2555*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2556*795d594fSAndroid Build Coastguard Worker       result.V = nullptr;
2557*795d594fSAndroid Build Coastguard Worker       sc.Check(soa, false, "V", &result);
2558*795d594fSAndroid Build Coastguard Worker     }
2559*795d594fSAndroid Build Coastguard Worker   }
2560*795d594fSAndroid Build Coastguard Worker 
GetArrayLength(JNIEnv * env,jarray array)2561*795d594fSAndroid Build Coastguard Worker   static jsize GetArrayLength(JNIEnv* env, jarray array) {
2562*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2563*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2564*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2565*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.a = array}};
2566*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Ea", args)) {
2567*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2568*795d594fSAndroid Build Coastguard Worker       result.z = baseEnv(env)->GetArrayLength(env, array);
2569*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "z", &result)) {
2570*795d594fSAndroid Build Coastguard Worker         return result.z;
2571*795d594fSAndroid Build Coastguard Worker       }
2572*795d594fSAndroid Build Coastguard Worker     }
2573*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
2574*795d594fSAndroid Build Coastguard Worker   }
2575*795d594fSAndroid Build Coastguard Worker 
NewObjectArray(JNIEnv * env,jsize length,jclass element_class,jobject initial_element)2576*795d594fSAndroid Build Coastguard Worker   static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2577*795d594fSAndroid Build Coastguard Worker                                      jobject initial_element) {
2578*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2579*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2580*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
2581*795d594fSAndroid Build Coastguard Worker     JniValueType args[4] =
2582*795d594fSAndroid Build Coastguard Worker         {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2583*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EzcL", args)) {
2584*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2585*795d594fSAndroid Build Coastguard Worker       // Note: assignability tests of initial_element are done in the base implementation.
2586*795d594fSAndroid Build Coastguard Worker       result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2587*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "a", &result)) {
2588*795d594fSAndroid Build Coastguard Worker         return down_cast<jobjectArray>(result.a);
2589*795d594fSAndroid Build Coastguard Worker       }
2590*795d594fSAndroid Build Coastguard Worker     }
2591*795d594fSAndroid Build Coastguard Worker     return nullptr;
2592*795d594fSAndroid Build Coastguard Worker   }
2593*795d594fSAndroid Build Coastguard Worker 
GetObjectArrayElement(JNIEnv * env,jobjectArray array,jsize index)2594*795d594fSAndroid Build Coastguard Worker   static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2595*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2596*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2597*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
2598*795d594fSAndroid Build Coastguard Worker     JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2599*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Eaz", args)) {
2600*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2601*795d594fSAndroid Build Coastguard Worker       result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2602*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "L", &result)) {
2603*795d594fSAndroid Build Coastguard Worker         return result.L;
2604*795d594fSAndroid Build Coastguard Worker       }
2605*795d594fSAndroid Build Coastguard Worker     }
2606*795d594fSAndroid Build Coastguard Worker     return nullptr;
2607*795d594fSAndroid Build Coastguard Worker   }
2608*795d594fSAndroid Build Coastguard Worker 
SetObjectArrayElement(JNIEnv * env,jobjectArray array,jsize index,jobject value)2609*795d594fSAndroid Build Coastguard Worker   static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2610*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
2611*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2612*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
2613*795d594fSAndroid Build Coastguard Worker     JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2614*795d594fSAndroid Build Coastguard Worker     // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2615*795d594fSAndroid Build Coastguard Worker     // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2616*795d594fSAndroid Build Coastguard Worker     // in ArrayStoreExceptions.
2617*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EaIL", args)) {
2618*795d594fSAndroid Build Coastguard Worker       baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2619*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2620*795d594fSAndroid Build Coastguard Worker       result.V = nullptr;
2621*795d594fSAndroid Build Coastguard Worker       sc.Check(soa, false, "V", &result);
2622*795d594fSAndroid Build Coastguard Worker     }
2623*795d594fSAndroid Build Coastguard Worker   }
2624*795d594fSAndroid Build Coastguard Worker 
NewBooleanArray(JNIEnv * env,jsize length)2625*795d594fSAndroid Build Coastguard Worker   static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2626*795d594fSAndroid Build Coastguard Worker     return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2627*795d594fSAndroid Build Coastguard Worker                                                       Primitive::kPrimBoolean));
2628*795d594fSAndroid Build Coastguard Worker   }
2629*795d594fSAndroid Build Coastguard Worker 
NewByteArray(JNIEnv * env,jsize length)2630*795d594fSAndroid Build Coastguard Worker   static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2631*795d594fSAndroid Build Coastguard Worker     return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2632*795d594fSAndroid Build Coastguard Worker                                                    Primitive::kPrimByte));
2633*795d594fSAndroid Build Coastguard Worker   }
2634*795d594fSAndroid Build Coastguard Worker 
NewCharArray(JNIEnv * env,jsize length)2635*795d594fSAndroid Build Coastguard Worker   static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2636*795d594fSAndroid Build Coastguard Worker     return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2637*795d594fSAndroid Build Coastguard Worker                                                    Primitive::kPrimChar));
2638*795d594fSAndroid Build Coastguard Worker   }
2639*795d594fSAndroid Build Coastguard Worker 
NewShortArray(JNIEnv * env,jsize length)2640*795d594fSAndroid Build Coastguard Worker   static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2641*795d594fSAndroid Build Coastguard Worker     return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2642*795d594fSAndroid Build Coastguard Worker                                                     Primitive::kPrimShort));
2643*795d594fSAndroid Build Coastguard Worker   }
2644*795d594fSAndroid Build Coastguard Worker 
NewIntArray(JNIEnv * env,jsize length)2645*795d594fSAndroid Build Coastguard Worker   static jintArray NewIntArray(JNIEnv* env, jsize length) {
2646*795d594fSAndroid Build Coastguard Worker     return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2647*795d594fSAndroid Build Coastguard Worker   }
2648*795d594fSAndroid Build Coastguard Worker 
NewLongArray(JNIEnv * env,jsize length)2649*795d594fSAndroid Build Coastguard Worker   static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2650*795d594fSAndroid Build Coastguard Worker     return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2651*795d594fSAndroid Build Coastguard Worker                                                    Primitive::kPrimLong));
2652*795d594fSAndroid Build Coastguard Worker   }
2653*795d594fSAndroid Build Coastguard Worker 
NewFloatArray(JNIEnv * env,jsize length)2654*795d594fSAndroid Build Coastguard Worker   static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2655*795d594fSAndroid Build Coastguard Worker     return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2656*795d594fSAndroid Build Coastguard Worker                                                     Primitive::kPrimFloat));
2657*795d594fSAndroid Build Coastguard Worker   }
2658*795d594fSAndroid Build Coastguard Worker 
NewDoubleArray(JNIEnv * env,jsize length)2659*795d594fSAndroid Build Coastguard Worker   static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2660*795d594fSAndroid Build Coastguard Worker     return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2661*795d594fSAndroid Build Coastguard Worker                                                      Primitive::kPrimDouble));
2662*795d594fSAndroid Build Coastguard Worker   }
2663*795d594fSAndroid Build Coastguard Worker 
2664*795d594fSAndroid Build Coastguard Worker // NOLINT added to avoid wrong warning/fix from clang-tidy.
2665*795d594fSAndroid Build Coastguard Worker #define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
2666*795d594fSAndroid Build Coastguard Worker   static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { /* NOLINT */ \
2667*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<ctype*>( /* NOLINT */ \
2668*795d594fSAndroid Build Coastguard Worker         GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2669*795d594fSAndroid Build Coastguard Worker   } \
2670*795d594fSAndroid Build Coastguard Worker   \
2671*795d594fSAndroid Build Coastguard Worker   static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, /* NOLINT */ \
2672*795d594fSAndroid Build Coastguard Worker                                            jint mode) { \
2673*795d594fSAndroid Build Coastguard Worker     ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2674*795d594fSAndroid Build Coastguard Worker   } \
2675*795d594fSAndroid Build Coastguard Worker   \
2676*795d594fSAndroid Build Coastguard Worker   static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2677*795d594fSAndroid Build Coastguard Worker                                      ctype* buf) { /* NOLINT */ \
2678*795d594fSAndroid Build Coastguard Worker     GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2679*795d594fSAndroid Build Coastguard Worker   } \
2680*795d594fSAndroid Build Coastguard Worker   \
2681*795d594fSAndroid Build Coastguard Worker   static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2682*795d594fSAndroid Build Coastguard Worker                                      const ctype* buf) { \
2683*795d594fSAndroid Build Coastguard Worker     SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2684*795d594fSAndroid Build Coastguard Worker   }
2685*795d594fSAndroid Build Coastguard Worker 
PRIMITIVE_ARRAY_FUNCTIONS(jboolean,Boolean,Primitive::kPrimBoolean)2686*795d594fSAndroid Build Coastguard Worker   PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2687*795d594fSAndroid Build Coastguard Worker   PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2688*795d594fSAndroid Build Coastguard Worker   PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2689*795d594fSAndroid Build Coastguard Worker   PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2690*795d594fSAndroid Build Coastguard Worker   PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2691*795d594fSAndroid Build Coastguard Worker   PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2692*795d594fSAndroid Build Coastguard Worker   PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2693*795d594fSAndroid Build Coastguard Worker   PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2694*795d594fSAndroid Build Coastguard Worker #undef PRIMITIVE_ARRAY_FUNCTIONS
2695*795d594fSAndroid Build Coastguard Worker 
2696*795d594fSAndroid Build Coastguard Worker   static jint MonitorEnter(JNIEnv* env, jobject obj) {
2697*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2698*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2699*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
2700*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.L = obj}};
2701*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EL", args)) {
2702*795d594fSAndroid Build Coastguard Worker       if (obj != nullptr) {
2703*795d594fSAndroid Build Coastguard Worker         down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj);
2704*795d594fSAndroid Build Coastguard Worker       }
2705*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2706*795d594fSAndroid Build Coastguard Worker       result.i = baseEnv(env)->MonitorEnter(env, obj);
2707*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "i", &result)) {
2708*795d594fSAndroid Build Coastguard Worker         return result.i;
2709*795d594fSAndroid Build Coastguard Worker       }
2710*795d594fSAndroid Build Coastguard Worker     }
2711*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
2712*795d594fSAndroid Build Coastguard Worker   }
2713*795d594fSAndroid Build Coastguard Worker 
MonitorExit(JNIEnv * env,jobject obj)2714*795d594fSAndroid Build Coastguard Worker   static jint MonitorExit(JNIEnv* env, jobject obj) {
2715*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2716*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2717*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2718*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.L = obj}};
2719*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EL", args)) {
2720*795d594fSAndroid Build Coastguard Worker       if (obj != nullptr) {
2721*795d594fSAndroid Build Coastguard Worker         down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj);
2722*795d594fSAndroid Build Coastguard Worker       }
2723*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2724*795d594fSAndroid Build Coastguard Worker       result.i = baseEnv(env)->MonitorExit(env, obj);
2725*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "i", &result)) {
2726*795d594fSAndroid Build Coastguard Worker         return result.i;
2727*795d594fSAndroid Build Coastguard Worker       }
2728*795d594fSAndroid Build Coastguard Worker     }
2729*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
2730*795d594fSAndroid Build Coastguard Worker   }
2731*795d594fSAndroid Build Coastguard Worker 
GetPrimitiveArrayCritical(JNIEnv * env,jarray array,jboolean * is_copy)2732*795d594fSAndroid Build Coastguard Worker   static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2733*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2734*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2735*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2736*795d594fSAndroid Build Coastguard Worker     JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2737*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Eap", args)) {
2738*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2739*795d594fSAndroid Build Coastguard Worker       void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2740*795d594fSAndroid Build Coastguard Worker       if (ptr != nullptr && soa.ForceCopy()) {
2741*795d594fSAndroid Build Coastguard Worker         ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
2742*795d594fSAndroid Build Coastguard Worker       }
2743*795d594fSAndroid Build Coastguard Worker       result.p = ptr;
2744*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "p", &result)) {
2745*795d594fSAndroid Build Coastguard Worker         return const_cast<void*>(result.p);
2746*795d594fSAndroid Build Coastguard Worker       }
2747*795d594fSAndroid Build Coastguard Worker     }
2748*795d594fSAndroid Build Coastguard Worker     return nullptr;
2749*795d594fSAndroid Build Coastguard Worker   }
2750*795d594fSAndroid Build Coastguard Worker 
ReleasePrimitiveArrayCritical(JNIEnv * env,jarray array,void * carray,jint mode)2751*795d594fSAndroid Build Coastguard Worker   static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2752*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
2753*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2754*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2755*795d594fSAndroid Build Coastguard Worker     sc.CheckNonNull(carray);
2756*795d594fSAndroid Build Coastguard Worker     JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2757*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Eapr", args)) {
2758*795d594fSAndroid Build Coastguard Worker       if (soa.ForceCopy()) {
2759*795d594fSAndroid Build Coastguard Worker         carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
2760*795d594fSAndroid Build Coastguard Worker       }
2761*795d594fSAndroid Build Coastguard Worker       baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2762*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2763*795d594fSAndroid Build Coastguard Worker       result.V = nullptr;
2764*795d594fSAndroid Build Coastguard Worker       sc.Check(soa, false, "V", &result);
2765*795d594fSAndroid Build Coastguard Worker     }
2766*795d594fSAndroid Build Coastguard Worker   }
2767*795d594fSAndroid Build Coastguard Worker 
NewDirectByteBuffer(JNIEnv * env,void * address,jlong capacity)2768*795d594fSAndroid Build Coastguard Worker   static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
2769*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2770*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2771*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
2772*795d594fSAndroid Build Coastguard Worker     JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2773*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EpJ", args)) {
2774*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2775*795d594fSAndroid Build Coastguard Worker       // Note: the validity of address and capacity are checked in the base implementation.
2776*795d594fSAndroid Build Coastguard Worker       result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2777*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "L", &result)) {
2778*795d594fSAndroid Build Coastguard Worker         return result.L;
2779*795d594fSAndroid Build Coastguard Worker       }
2780*795d594fSAndroid Build Coastguard Worker     }
2781*795d594fSAndroid Build Coastguard Worker     return nullptr;
2782*795d594fSAndroid Build Coastguard Worker   }
2783*795d594fSAndroid Build Coastguard Worker 
GetDirectBufferAddress(JNIEnv * env,jobject buf)2784*795d594fSAndroid Build Coastguard Worker   static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
2785*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2786*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2787*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
2788*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.L = buf}};
2789*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EL", args)) {
2790*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2791*795d594fSAndroid Build Coastguard Worker       // Note: this is implemented in the base environment by a GetLongField which will check the
2792*795d594fSAndroid Build Coastguard Worker       // type of buf in GetLongField above.
2793*795d594fSAndroid Build Coastguard Worker       result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2794*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "p", &result)) {
2795*795d594fSAndroid Build Coastguard Worker         return const_cast<void*>(result.p);
2796*795d594fSAndroid Build Coastguard Worker       }
2797*795d594fSAndroid Build Coastguard Worker     }
2798*795d594fSAndroid Build Coastguard Worker     return nullptr;
2799*795d594fSAndroid Build Coastguard Worker   }
2800*795d594fSAndroid Build Coastguard Worker 
GetDirectBufferCapacity(JNIEnv * env,jobject buf)2801*795d594fSAndroid Build Coastguard Worker   static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
2802*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2803*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2804*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, __FUNCTION__);
2805*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.L = buf}};
2806*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EL", args)) {
2807*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2808*795d594fSAndroid Build Coastguard Worker       // Note: this is implemented in the base environment by a GetIntField which will check the
2809*795d594fSAndroid Build Coastguard Worker       // type of buf in GetIntField above.
2810*795d594fSAndroid Build Coastguard Worker       result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2811*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "J", &result)) {
2812*795d594fSAndroid Build Coastguard Worker         return result.J;
2813*795d594fSAndroid Build Coastguard Worker       }
2814*795d594fSAndroid Build Coastguard Worker     }
2815*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
2816*795d594fSAndroid Build Coastguard Worker   }
2817*795d594fSAndroid Build Coastguard Worker 
2818*795d594fSAndroid Build Coastguard Worker  private:
GetJavaVMExt(JNIEnv * env)2819*795d594fSAndroid Build Coastguard Worker   static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
2820*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<JNIEnvExt*>(env)->GetVm();
2821*795d594fSAndroid Build Coastguard Worker   }
2822*795d594fSAndroid Build Coastguard Worker 
baseEnv(JNIEnv * env)2823*795d594fSAndroid Build Coastguard Worker   static const JNINativeInterface* baseEnv(JNIEnv* env) {
2824*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<JNIEnvExt*>(env)->GetUncheckedFunctions();
2825*795d594fSAndroid Build Coastguard Worker   }
2826*795d594fSAndroid Build Coastguard Worker 
NewRef(const char * function_name,JNIEnv * env,jobject obj,IndirectRefKind kind)2827*795d594fSAndroid Build Coastguard Worker   static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2828*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(function_name, nullptr);
2829*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2830*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, function_name);
2831*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.L = obj}};
2832*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EL", args)) {
2833*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2834*795d594fSAndroid Build Coastguard Worker       switch (kind) {
2835*795d594fSAndroid Build Coastguard Worker         case kGlobal:
2836*795d594fSAndroid Build Coastguard Worker           result.L = baseEnv(env)->NewGlobalRef(env, obj);
2837*795d594fSAndroid Build Coastguard Worker           break;
2838*795d594fSAndroid Build Coastguard Worker         case kLocal:
2839*795d594fSAndroid Build Coastguard Worker           result.L = baseEnv(env)->NewLocalRef(env, obj);
2840*795d594fSAndroid Build Coastguard Worker           break;
2841*795d594fSAndroid Build Coastguard Worker         case kWeakGlobal:
2842*795d594fSAndroid Build Coastguard Worker           result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2843*795d594fSAndroid Build Coastguard Worker           break;
2844*795d594fSAndroid Build Coastguard Worker         default:
2845*795d594fSAndroid Build Coastguard Worker           LOG(FATAL) << "Unexpected reference kind: " << kind;
2846*795d594fSAndroid Build Coastguard Worker       }
2847*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "L", &result)) {
2848*795d594fSAndroid Build Coastguard Worker         DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
2849*795d594fSAndroid Build Coastguard Worker         DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
2850*795d594fSAndroid Build Coastguard Worker         return result.L;
2851*795d594fSAndroid Build Coastguard Worker       }
2852*795d594fSAndroid Build Coastguard Worker     }
2853*795d594fSAndroid Build Coastguard Worker     return nullptr;
2854*795d594fSAndroid Build Coastguard Worker   }
2855*795d594fSAndroid Build Coastguard Worker 
DeleteRef(const char * function_name,JNIEnv * env,jobject obj,IndirectRefKind kind)2856*795d594fSAndroid Build Coastguard Worker   static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2857*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD_VOID(function_name);
2858*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2859*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_ExcepOkay, function_name);
2860*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.L = obj}};
2861*795d594fSAndroid Build Coastguard Worker     sc.Check(soa, true, "EL", args);
2862*795d594fSAndroid Build Coastguard Worker     if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
2863*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2864*795d594fSAndroid Build Coastguard Worker       switch (kind) {
2865*795d594fSAndroid Build Coastguard Worker         case kGlobal:
2866*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->DeleteGlobalRef(env, obj);
2867*795d594fSAndroid Build Coastguard Worker           break;
2868*795d594fSAndroid Build Coastguard Worker         case kLocal:
2869*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->DeleteLocalRef(env, obj);
2870*795d594fSAndroid Build Coastguard Worker           break;
2871*795d594fSAndroid Build Coastguard Worker         case kWeakGlobal:
2872*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2873*795d594fSAndroid Build Coastguard Worker           break;
2874*795d594fSAndroid Build Coastguard Worker         default:
2875*795d594fSAndroid Build Coastguard Worker           LOG(FATAL) << "Unexpected reference kind: " << kind;
2876*795d594fSAndroid Build Coastguard Worker       }
2877*795d594fSAndroid Build Coastguard Worker       result.V = nullptr;
2878*795d594fSAndroid Build Coastguard Worker       sc.Check(soa, false, "V", &result);
2879*795d594fSAndroid Build Coastguard Worker     }
2880*795d594fSAndroid Build Coastguard Worker   }
2881*795d594fSAndroid Build Coastguard Worker 
GetMethodIDInternal(const char * function_name,JNIEnv * env,jclass c,const char * name,const char * sig,bool is_static)2882*795d594fSAndroid Build Coastguard Worker   static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2883*795d594fSAndroid Build Coastguard Worker                                        const char* name, const char* sig, bool is_static) {
2884*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(function_name, nullptr);
2885*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2886*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, function_name);
2887*795d594fSAndroid Build Coastguard Worker     JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2888*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Ecuu", args)) {
2889*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2890*795d594fSAndroid Build Coastguard Worker       if (is_static) {
2891*795d594fSAndroid Build Coastguard Worker         result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2892*795d594fSAndroid Build Coastguard Worker       } else {
2893*795d594fSAndroid Build Coastguard Worker         result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2894*795d594fSAndroid Build Coastguard Worker       }
2895*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "m", &result)) {
2896*795d594fSAndroid Build Coastguard Worker         return result.m;
2897*795d594fSAndroid Build Coastguard Worker       }
2898*795d594fSAndroid Build Coastguard Worker     }
2899*795d594fSAndroid Build Coastguard Worker     return nullptr;
2900*795d594fSAndroid Build Coastguard Worker   }
2901*795d594fSAndroid Build Coastguard Worker 
GetFieldIDInternal(const char * function_name,JNIEnv * env,jclass c,const char * name,const char * sig,bool is_static)2902*795d594fSAndroid Build Coastguard Worker   static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2903*795d594fSAndroid Build Coastguard Worker                                      const char* name, const char* sig, bool is_static) {
2904*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(function_name, nullptr);
2905*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2906*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, function_name);
2907*795d594fSAndroid Build Coastguard Worker     JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2908*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Ecuu", args)) {
2909*795d594fSAndroid Build Coastguard Worker       JniValueType result;
2910*795d594fSAndroid Build Coastguard Worker       if (is_static) {
2911*795d594fSAndroid Build Coastguard Worker         result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2912*795d594fSAndroid Build Coastguard Worker       } else {
2913*795d594fSAndroid Build Coastguard Worker         result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2914*795d594fSAndroid Build Coastguard Worker       }
2915*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "f", &result)) {
2916*795d594fSAndroid Build Coastguard Worker         return result.f;
2917*795d594fSAndroid Build Coastguard Worker       }
2918*795d594fSAndroid Build Coastguard Worker     }
2919*795d594fSAndroid Build Coastguard Worker     return nullptr;
2920*795d594fSAndroid Build Coastguard Worker   }
2921*795d594fSAndroid Build Coastguard Worker 
GetField(const char * function_name,JNIEnv * env,jobject obj,jfieldID fid,bool is_static,Primitive::Type type)2922*795d594fSAndroid Build Coastguard Worker   static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2923*795d594fSAndroid Build Coastguard Worker                                bool is_static, Primitive::Type type) {
2924*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(function_name, JniValueType());
2925*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
2926*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, function_name);
2927*795d594fSAndroid Build Coastguard Worker     JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2928*795d594fSAndroid Build Coastguard Worker     JniValueType result;
2929*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2930*795d594fSAndroid Build Coastguard Worker         sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2931*795d594fSAndroid Build Coastguard Worker       const char* result_check = nullptr;
2932*795d594fSAndroid Build Coastguard Worker       switch (type) {
2933*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimNot:
2934*795d594fSAndroid Build Coastguard Worker           if (is_static) {
2935*795d594fSAndroid Build Coastguard Worker             result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2936*795d594fSAndroid Build Coastguard Worker           } else {
2937*795d594fSAndroid Build Coastguard Worker             result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2938*795d594fSAndroid Build Coastguard Worker           }
2939*795d594fSAndroid Build Coastguard Worker           result_check = "L";
2940*795d594fSAndroid Build Coastguard Worker           break;
2941*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimBoolean:
2942*795d594fSAndroid Build Coastguard Worker           if (is_static) {
2943*795d594fSAndroid Build Coastguard Worker             result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2944*795d594fSAndroid Build Coastguard Worker           } else {
2945*795d594fSAndroid Build Coastguard Worker             result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2946*795d594fSAndroid Build Coastguard Worker           }
2947*795d594fSAndroid Build Coastguard Worker           result_check = "Z";
2948*795d594fSAndroid Build Coastguard Worker           break;
2949*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimByte:
2950*795d594fSAndroid Build Coastguard Worker           if (is_static) {
2951*795d594fSAndroid Build Coastguard Worker             result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2952*795d594fSAndroid Build Coastguard Worker           } else {
2953*795d594fSAndroid Build Coastguard Worker             result.B = baseEnv(env)->GetByteField(env, obj, fid);
2954*795d594fSAndroid Build Coastguard Worker           }
2955*795d594fSAndroid Build Coastguard Worker           result_check = "B";
2956*795d594fSAndroid Build Coastguard Worker           break;
2957*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimChar:
2958*795d594fSAndroid Build Coastguard Worker           if (is_static) {
2959*795d594fSAndroid Build Coastguard Worker             result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2960*795d594fSAndroid Build Coastguard Worker           } else {
2961*795d594fSAndroid Build Coastguard Worker             result.C = baseEnv(env)->GetCharField(env, obj, fid);
2962*795d594fSAndroid Build Coastguard Worker           }
2963*795d594fSAndroid Build Coastguard Worker           result_check = "C";
2964*795d594fSAndroid Build Coastguard Worker           break;
2965*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimShort:
2966*795d594fSAndroid Build Coastguard Worker           if (is_static) {
2967*795d594fSAndroid Build Coastguard Worker             result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2968*795d594fSAndroid Build Coastguard Worker           } else {
2969*795d594fSAndroid Build Coastguard Worker             result.S = baseEnv(env)->GetShortField(env, obj, fid);
2970*795d594fSAndroid Build Coastguard Worker           }
2971*795d594fSAndroid Build Coastguard Worker           result_check = "S";
2972*795d594fSAndroid Build Coastguard Worker           break;
2973*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimInt:
2974*795d594fSAndroid Build Coastguard Worker           if (is_static) {
2975*795d594fSAndroid Build Coastguard Worker             result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2976*795d594fSAndroid Build Coastguard Worker           } else {
2977*795d594fSAndroid Build Coastguard Worker             result.I = baseEnv(env)->GetIntField(env, obj, fid);
2978*795d594fSAndroid Build Coastguard Worker           }
2979*795d594fSAndroid Build Coastguard Worker           result_check = "I";
2980*795d594fSAndroid Build Coastguard Worker           break;
2981*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimLong:
2982*795d594fSAndroid Build Coastguard Worker           if (is_static) {
2983*795d594fSAndroid Build Coastguard Worker             result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2984*795d594fSAndroid Build Coastguard Worker           } else {
2985*795d594fSAndroid Build Coastguard Worker             result.J = baseEnv(env)->GetLongField(env, obj, fid);
2986*795d594fSAndroid Build Coastguard Worker           }
2987*795d594fSAndroid Build Coastguard Worker           result_check = "J";
2988*795d594fSAndroid Build Coastguard Worker           break;
2989*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimFloat:
2990*795d594fSAndroid Build Coastguard Worker           if (is_static) {
2991*795d594fSAndroid Build Coastguard Worker             result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2992*795d594fSAndroid Build Coastguard Worker           } else {
2993*795d594fSAndroid Build Coastguard Worker             result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2994*795d594fSAndroid Build Coastguard Worker           }
2995*795d594fSAndroid Build Coastguard Worker           result_check = "F";
2996*795d594fSAndroid Build Coastguard Worker           break;
2997*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimDouble:
2998*795d594fSAndroid Build Coastguard Worker           if (is_static) {
2999*795d594fSAndroid Build Coastguard Worker             result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
3000*795d594fSAndroid Build Coastguard Worker           } else {
3001*795d594fSAndroid Build Coastguard Worker             result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
3002*795d594fSAndroid Build Coastguard Worker           }
3003*795d594fSAndroid Build Coastguard Worker           result_check = "D";
3004*795d594fSAndroid Build Coastguard Worker           break;
3005*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimVoid:
3006*795d594fSAndroid Build Coastguard Worker           LOG(FATAL) << "Unexpected type: " << type;
3007*795d594fSAndroid Build Coastguard Worker           UNREACHABLE();
3008*795d594fSAndroid Build Coastguard Worker       }
3009*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, result_check, &result)) {
3010*795d594fSAndroid Build Coastguard Worker         return result;
3011*795d594fSAndroid Build Coastguard Worker       }
3012*795d594fSAndroid Build Coastguard Worker     }
3013*795d594fSAndroid Build Coastguard Worker     result.J = 0;
3014*795d594fSAndroid Build Coastguard Worker     return result;
3015*795d594fSAndroid Build Coastguard Worker   }
3016*795d594fSAndroid Build Coastguard Worker 
SetField(const char * function_name,JNIEnv * env,jobject obj,jfieldID fid,bool is_static,Primitive::Type type,JniValueType value)3017*795d594fSAndroid Build Coastguard Worker   static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
3018*795d594fSAndroid Build Coastguard Worker                        bool is_static, Primitive::Type type, JniValueType value) {
3019*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD_VOID(function_name);
3020*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
3021*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, function_name);
3022*795d594fSAndroid Build Coastguard Worker     JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
3023*795d594fSAndroid Build Coastguard Worker     char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
3024*795d594fSAndroid Build Coastguard Worker         type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
3025*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, sig, args) &&
3026*795d594fSAndroid Build Coastguard Worker         sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
3027*795d594fSAndroid Build Coastguard Worker       switch (type) {
3028*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimNot:
3029*795d594fSAndroid Build Coastguard Worker           if (is_static) {
3030*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
3031*795d594fSAndroid Build Coastguard Worker           } else {
3032*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->SetObjectField(env, obj, fid, value.L);
3033*795d594fSAndroid Build Coastguard Worker           }
3034*795d594fSAndroid Build Coastguard Worker           break;
3035*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimBoolean:
3036*795d594fSAndroid Build Coastguard Worker           if (is_static) {
3037*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
3038*795d594fSAndroid Build Coastguard Worker           } else {
3039*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
3040*795d594fSAndroid Build Coastguard Worker           }
3041*795d594fSAndroid Build Coastguard Worker           break;
3042*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimByte:
3043*795d594fSAndroid Build Coastguard Worker           if (is_static) {
3044*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
3045*795d594fSAndroid Build Coastguard Worker           } else {
3046*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->SetByteField(env, obj, fid, value.B);
3047*795d594fSAndroid Build Coastguard Worker           }
3048*795d594fSAndroid Build Coastguard Worker           break;
3049*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimChar:
3050*795d594fSAndroid Build Coastguard Worker           if (is_static) {
3051*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
3052*795d594fSAndroid Build Coastguard Worker           } else {
3053*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->SetCharField(env, obj, fid, value.C);
3054*795d594fSAndroid Build Coastguard Worker           }
3055*795d594fSAndroid Build Coastguard Worker           break;
3056*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimShort:
3057*795d594fSAndroid Build Coastguard Worker           if (is_static) {
3058*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
3059*795d594fSAndroid Build Coastguard Worker           } else {
3060*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->SetShortField(env, obj, fid, value.S);
3061*795d594fSAndroid Build Coastguard Worker           }
3062*795d594fSAndroid Build Coastguard Worker           break;
3063*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimInt:
3064*795d594fSAndroid Build Coastguard Worker           if (is_static) {
3065*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
3066*795d594fSAndroid Build Coastguard Worker           } else {
3067*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->SetIntField(env, obj, fid, value.I);
3068*795d594fSAndroid Build Coastguard Worker           }
3069*795d594fSAndroid Build Coastguard Worker           break;
3070*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimLong:
3071*795d594fSAndroid Build Coastguard Worker           if (is_static) {
3072*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
3073*795d594fSAndroid Build Coastguard Worker           } else {
3074*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->SetLongField(env, obj, fid, value.J);
3075*795d594fSAndroid Build Coastguard Worker           }
3076*795d594fSAndroid Build Coastguard Worker           break;
3077*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimFloat:
3078*795d594fSAndroid Build Coastguard Worker           if (is_static) {
3079*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
3080*795d594fSAndroid Build Coastguard Worker           } else {
3081*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->SetFloatField(env, obj, fid, value.F);
3082*795d594fSAndroid Build Coastguard Worker           }
3083*795d594fSAndroid Build Coastguard Worker           break;
3084*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimDouble:
3085*795d594fSAndroid Build Coastguard Worker           if (is_static) {
3086*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
3087*795d594fSAndroid Build Coastguard Worker           } else {
3088*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
3089*795d594fSAndroid Build Coastguard Worker           }
3090*795d594fSAndroid Build Coastguard Worker           break;
3091*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimVoid:
3092*795d594fSAndroid Build Coastguard Worker           LOG(FATAL) << "Unexpected type: " << type;
3093*795d594fSAndroid Build Coastguard Worker           UNREACHABLE();
3094*795d594fSAndroid Build Coastguard Worker       }
3095*795d594fSAndroid Build Coastguard Worker       JniValueType result;
3096*795d594fSAndroid Build Coastguard Worker       result.V = nullptr;
3097*795d594fSAndroid Build Coastguard Worker       sc.Check(soa, false, "V", &result);
3098*795d594fSAndroid Build Coastguard Worker     }
3099*795d594fSAndroid Build Coastguard Worker   }
3100*795d594fSAndroid Build Coastguard Worker 
CheckCallArgs(ScopedObjectAccess & soa,ScopedCheck & sc,JNIEnv * env,jobject obj,jclass c,jmethodID mid,InvokeType invoke,const VarArgs * vargs)3101*795d594fSAndroid Build Coastguard Worker   static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
3102*795d594fSAndroid Build Coastguard Worker                             jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs)
3103*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
3104*795d594fSAndroid Build Coastguard Worker     bool checked;
3105*795d594fSAndroid Build Coastguard Worker     switch (invoke) {
3106*795d594fSAndroid Build Coastguard Worker       case kVirtual: {
3107*795d594fSAndroid Build Coastguard Worker         DCHECK(c == nullptr);
3108*795d594fSAndroid Build Coastguard Worker         JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}};
3109*795d594fSAndroid Build Coastguard Worker         checked = sc.Check(soa, true, "ELm.", args);
3110*795d594fSAndroid Build Coastguard Worker         break;
3111*795d594fSAndroid Build Coastguard Worker       }
3112*795d594fSAndroid Build Coastguard Worker       case kDirect: {
3113*795d594fSAndroid Build Coastguard Worker         JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}};
3114*795d594fSAndroid Build Coastguard Worker         checked = sc.Check(soa, true, "ELcm.", args);
3115*795d594fSAndroid Build Coastguard Worker         break;
3116*795d594fSAndroid Build Coastguard Worker       }
3117*795d594fSAndroid Build Coastguard Worker       case kStatic: {
3118*795d594fSAndroid Build Coastguard Worker         DCHECK(obj == nullptr);
3119*795d594fSAndroid Build Coastguard Worker         JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}};
3120*795d594fSAndroid Build Coastguard Worker         checked = sc.Check(soa, true, "Ecm.", args);
3121*795d594fSAndroid Build Coastguard Worker         break;
3122*795d594fSAndroid Build Coastguard Worker       }
3123*795d594fSAndroid Build Coastguard Worker       default:
3124*795d594fSAndroid Build Coastguard Worker         LOG(FATAL) << "Unexpected invoke: " << invoke;
3125*795d594fSAndroid Build Coastguard Worker         checked = false;
3126*795d594fSAndroid Build Coastguard Worker         break;
3127*795d594fSAndroid Build Coastguard Worker     }
3128*795d594fSAndroid Build Coastguard Worker     return checked;
3129*795d594fSAndroid Build Coastguard Worker   }
3130*795d594fSAndroid Build Coastguard Worker 
CallMethodA(const char * function_name,JNIEnv * env,jobject obj,jclass c,jmethodID mid,const jvalue * vargs,Primitive::Type type,InvokeType invoke)3131*795d594fSAndroid Build Coastguard Worker   static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
3132*795d594fSAndroid Build Coastguard Worker                                   jmethodID mid, const jvalue* vargs, Primitive::Type type,
3133*795d594fSAndroid Build Coastguard Worker                                   InvokeType invoke) {
3134*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(function_name, JniValueType());
3135*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
3136*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, function_name);
3137*795d594fSAndroid Build Coastguard Worker     JniValueType result;
3138*795d594fSAndroid Build Coastguard Worker     VarArgs rest(mid, vargs);
3139*795d594fSAndroid Build Coastguard Worker     if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
3140*795d594fSAndroid Build Coastguard Worker         sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3141*795d594fSAndroid Build Coastguard Worker       const char* result_check;
3142*795d594fSAndroid Build Coastguard Worker       switch (type) {
3143*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimNot:
3144*795d594fSAndroid Build Coastguard Worker           result_check = "L";
3145*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3146*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3147*795d594fSAndroid Build Coastguard Worker               result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
3148*795d594fSAndroid Build Coastguard Worker               break;
3149*795d594fSAndroid Build Coastguard Worker             case kDirect:
3150*795d594fSAndroid Build Coastguard Worker               result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
3151*795d594fSAndroid Build Coastguard Worker               break;
3152*795d594fSAndroid Build Coastguard Worker             case kStatic:
3153*795d594fSAndroid Build Coastguard Worker               result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
3154*795d594fSAndroid Build Coastguard Worker               break;
3155*795d594fSAndroid Build Coastguard Worker             default:
3156*795d594fSAndroid Build Coastguard Worker               break;
3157*795d594fSAndroid Build Coastguard Worker           }
3158*795d594fSAndroid Build Coastguard Worker           break;
3159*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimBoolean:
3160*795d594fSAndroid Build Coastguard Worker           result_check = "Z";
3161*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3162*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3163*795d594fSAndroid Build Coastguard Worker               result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
3164*795d594fSAndroid Build Coastguard Worker               break;
3165*795d594fSAndroid Build Coastguard Worker             case kDirect:
3166*795d594fSAndroid Build Coastguard Worker               result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
3167*795d594fSAndroid Build Coastguard Worker               break;
3168*795d594fSAndroid Build Coastguard Worker             case kStatic:
3169*795d594fSAndroid Build Coastguard Worker               result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
3170*795d594fSAndroid Build Coastguard Worker               break;
3171*795d594fSAndroid Build Coastguard Worker             default:
3172*795d594fSAndroid Build Coastguard Worker               break;
3173*795d594fSAndroid Build Coastguard Worker           }
3174*795d594fSAndroid Build Coastguard Worker           break;
3175*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimByte:
3176*795d594fSAndroid Build Coastguard Worker           result_check = "B";
3177*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3178*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3179*795d594fSAndroid Build Coastguard Worker               result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
3180*795d594fSAndroid Build Coastguard Worker               break;
3181*795d594fSAndroid Build Coastguard Worker             case kDirect:
3182*795d594fSAndroid Build Coastguard Worker               result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
3183*795d594fSAndroid Build Coastguard Worker               break;
3184*795d594fSAndroid Build Coastguard Worker             case kStatic:
3185*795d594fSAndroid Build Coastguard Worker               result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
3186*795d594fSAndroid Build Coastguard Worker               break;
3187*795d594fSAndroid Build Coastguard Worker             default:
3188*795d594fSAndroid Build Coastguard Worker               break;
3189*795d594fSAndroid Build Coastguard Worker           }
3190*795d594fSAndroid Build Coastguard Worker           break;
3191*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimChar:
3192*795d594fSAndroid Build Coastguard Worker           result_check = "C";
3193*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3194*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3195*795d594fSAndroid Build Coastguard Worker               result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
3196*795d594fSAndroid Build Coastguard Worker               break;
3197*795d594fSAndroid Build Coastguard Worker             case kDirect:
3198*795d594fSAndroid Build Coastguard Worker               result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
3199*795d594fSAndroid Build Coastguard Worker               break;
3200*795d594fSAndroid Build Coastguard Worker             case kStatic:
3201*795d594fSAndroid Build Coastguard Worker               result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
3202*795d594fSAndroid Build Coastguard Worker               break;
3203*795d594fSAndroid Build Coastguard Worker             default:
3204*795d594fSAndroid Build Coastguard Worker               break;
3205*795d594fSAndroid Build Coastguard Worker           }
3206*795d594fSAndroid Build Coastguard Worker           break;
3207*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimShort:
3208*795d594fSAndroid Build Coastguard Worker           result_check = "S";
3209*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3210*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3211*795d594fSAndroid Build Coastguard Worker               result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
3212*795d594fSAndroid Build Coastguard Worker               break;
3213*795d594fSAndroid Build Coastguard Worker             case kDirect:
3214*795d594fSAndroid Build Coastguard Worker               result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
3215*795d594fSAndroid Build Coastguard Worker               break;
3216*795d594fSAndroid Build Coastguard Worker             case kStatic:
3217*795d594fSAndroid Build Coastguard Worker               result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
3218*795d594fSAndroid Build Coastguard Worker               break;
3219*795d594fSAndroid Build Coastguard Worker             default:
3220*795d594fSAndroid Build Coastguard Worker               break;
3221*795d594fSAndroid Build Coastguard Worker           }
3222*795d594fSAndroid Build Coastguard Worker           break;
3223*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimInt:
3224*795d594fSAndroid Build Coastguard Worker           result_check = "I";
3225*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3226*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3227*795d594fSAndroid Build Coastguard Worker               result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
3228*795d594fSAndroid Build Coastguard Worker               break;
3229*795d594fSAndroid Build Coastguard Worker             case kDirect:
3230*795d594fSAndroid Build Coastguard Worker               result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
3231*795d594fSAndroid Build Coastguard Worker               break;
3232*795d594fSAndroid Build Coastguard Worker             case kStatic:
3233*795d594fSAndroid Build Coastguard Worker               result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
3234*795d594fSAndroid Build Coastguard Worker               break;
3235*795d594fSAndroid Build Coastguard Worker             default:
3236*795d594fSAndroid Build Coastguard Worker               break;
3237*795d594fSAndroid Build Coastguard Worker           }
3238*795d594fSAndroid Build Coastguard Worker           break;
3239*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimLong:
3240*795d594fSAndroid Build Coastguard Worker           result_check = "J";
3241*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3242*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3243*795d594fSAndroid Build Coastguard Worker               result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
3244*795d594fSAndroid Build Coastguard Worker               break;
3245*795d594fSAndroid Build Coastguard Worker             case kDirect:
3246*795d594fSAndroid Build Coastguard Worker               result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
3247*795d594fSAndroid Build Coastguard Worker               break;
3248*795d594fSAndroid Build Coastguard Worker             case kStatic:
3249*795d594fSAndroid Build Coastguard Worker               result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
3250*795d594fSAndroid Build Coastguard Worker               break;
3251*795d594fSAndroid Build Coastguard Worker             default:
3252*795d594fSAndroid Build Coastguard Worker               break;
3253*795d594fSAndroid Build Coastguard Worker           }
3254*795d594fSAndroid Build Coastguard Worker           break;
3255*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimFloat:
3256*795d594fSAndroid Build Coastguard Worker           result_check = "F";
3257*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3258*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3259*795d594fSAndroid Build Coastguard Worker               result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
3260*795d594fSAndroid Build Coastguard Worker               break;
3261*795d594fSAndroid Build Coastguard Worker             case kDirect:
3262*795d594fSAndroid Build Coastguard Worker               result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
3263*795d594fSAndroid Build Coastguard Worker               break;
3264*795d594fSAndroid Build Coastguard Worker             case kStatic:
3265*795d594fSAndroid Build Coastguard Worker               result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
3266*795d594fSAndroid Build Coastguard Worker               break;
3267*795d594fSAndroid Build Coastguard Worker             default:
3268*795d594fSAndroid Build Coastguard Worker               break;
3269*795d594fSAndroid Build Coastguard Worker           }
3270*795d594fSAndroid Build Coastguard Worker           break;
3271*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimDouble:
3272*795d594fSAndroid Build Coastguard Worker           result_check = "D";
3273*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3274*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3275*795d594fSAndroid Build Coastguard Worker               result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
3276*795d594fSAndroid Build Coastguard Worker               break;
3277*795d594fSAndroid Build Coastguard Worker             case kDirect:
3278*795d594fSAndroid Build Coastguard Worker               result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
3279*795d594fSAndroid Build Coastguard Worker               break;
3280*795d594fSAndroid Build Coastguard Worker             case kStatic:
3281*795d594fSAndroid Build Coastguard Worker               result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
3282*795d594fSAndroid Build Coastguard Worker               break;
3283*795d594fSAndroid Build Coastguard Worker             default:
3284*795d594fSAndroid Build Coastguard Worker               break;
3285*795d594fSAndroid Build Coastguard Worker           }
3286*795d594fSAndroid Build Coastguard Worker           break;
3287*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimVoid:
3288*795d594fSAndroid Build Coastguard Worker           result_check = "V";
3289*795d594fSAndroid Build Coastguard Worker           result.V = nullptr;
3290*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3291*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3292*795d594fSAndroid Build Coastguard Worker               baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
3293*795d594fSAndroid Build Coastguard Worker               break;
3294*795d594fSAndroid Build Coastguard Worker             case kDirect:
3295*795d594fSAndroid Build Coastguard Worker               baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
3296*795d594fSAndroid Build Coastguard Worker               break;
3297*795d594fSAndroid Build Coastguard Worker             case kStatic:
3298*795d594fSAndroid Build Coastguard Worker               baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
3299*795d594fSAndroid Build Coastguard Worker               break;
3300*795d594fSAndroid Build Coastguard Worker             default:
3301*795d594fSAndroid Build Coastguard Worker               LOG(FATAL) << "Unexpected invoke: " << invoke;
3302*795d594fSAndroid Build Coastguard Worker           }
3303*795d594fSAndroid Build Coastguard Worker           break;
3304*795d594fSAndroid Build Coastguard Worker       }
3305*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, result_check, &result)) {
3306*795d594fSAndroid Build Coastguard Worker         return result;
3307*795d594fSAndroid Build Coastguard Worker       }
3308*795d594fSAndroid Build Coastguard Worker     }
3309*795d594fSAndroid Build Coastguard Worker     result.J = 0;
3310*795d594fSAndroid Build Coastguard Worker     return result;
3311*795d594fSAndroid Build Coastguard Worker   }
3312*795d594fSAndroid Build Coastguard Worker 
3313*795d594fSAndroid Build Coastguard Worker   NO_STACK_PROTECTOR
CallMethodV(const char * function_name,JNIEnv * env,jobject obj,jclass c,jmethodID mid,va_list vargs,Primitive::Type type,InvokeType invoke)3314*795d594fSAndroid Build Coastguard Worker   static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
3315*795d594fSAndroid Build Coastguard Worker                                   jmethodID mid, va_list vargs, Primitive::Type type,
3316*795d594fSAndroid Build Coastguard Worker                                   InvokeType invoke) {
3317*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(function_name, JniValueType());
3318*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
3319*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, function_name);
3320*795d594fSAndroid Build Coastguard Worker     JniValueType result;
3321*795d594fSAndroid Build Coastguard Worker     VarArgs rest(mid, vargs);
3322*795d594fSAndroid Build Coastguard Worker     if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
3323*795d594fSAndroid Build Coastguard Worker         sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3324*795d594fSAndroid Build Coastguard Worker       const char* result_check;
3325*795d594fSAndroid Build Coastguard Worker       switch (type) {
3326*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimNot:
3327*795d594fSAndroid Build Coastguard Worker           result_check = "L";
3328*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3329*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3330*795d594fSAndroid Build Coastguard Worker               result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
3331*795d594fSAndroid Build Coastguard Worker               break;
3332*795d594fSAndroid Build Coastguard Worker             case kDirect:
3333*795d594fSAndroid Build Coastguard Worker               result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
3334*795d594fSAndroid Build Coastguard Worker               break;
3335*795d594fSAndroid Build Coastguard Worker             case kStatic:
3336*795d594fSAndroid Build Coastguard Worker               result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
3337*795d594fSAndroid Build Coastguard Worker               break;
3338*795d594fSAndroid Build Coastguard Worker             default:
3339*795d594fSAndroid Build Coastguard Worker               LOG(FATAL) << "Unexpected invoke: " << invoke;
3340*795d594fSAndroid Build Coastguard Worker           }
3341*795d594fSAndroid Build Coastguard Worker           break;
3342*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimBoolean:
3343*795d594fSAndroid Build Coastguard Worker           result_check = "Z";
3344*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3345*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3346*795d594fSAndroid Build Coastguard Worker               result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
3347*795d594fSAndroid Build Coastguard Worker               break;
3348*795d594fSAndroid Build Coastguard Worker             case kDirect:
3349*795d594fSAndroid Build Coastguard Worker               result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
3350*795d594fSAndroid Build Coastguard Worker               break;
3351*795d594fSAndroid Build Coastguard Worker             case kStatic:
3352*795d594fSAndroid Build Coastguard Worker               result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
3353*795d594fSAndroid Build Coastguard Worker               break;
3354*795d594fSAndroid Build Coastguard Worker             default:
3355*795d594fSAndroid Build Coastguard Worker               LOG(FATAL) << "Unexpected invoke: " << invoke;
3356*795d594fSAndroid Build Coastguard Worker           }
3357*795d594fSAndroid Build Coastguard Worker           break;
3358*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimByte:
3359*795d594fSAndroid Build Coastguard Worker           result_check = "B";
3360*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3361*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3362*795d594fSAndroid Build Coastguard Worker               result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
3363*795d594fSAndroid Build Coastguard Worker               break;
3364*795d594fSAndroid Build Coastguard Worker             case kDirect:
3365*795d594fSAndroid Build Coastguard Worker               result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
3366*795d594fSAndroid Build Coastguard Worker               break;
3367*795d594fSAndroid Build Coastguard Worker             case kStatic:
3368*795d594fSAndroid Build Coastguard Worker               result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
3369*795d594fSAndroid Build Coastguard Worker               break;
3370*795d594fSAndroid Build Coastguard Worker             default:
3371*795d594fSAndroid Build Coastguard Worker               LOG(FATAL) << "Unexpected invoke: " << invoke;
3372*795d594fSAndroid Build Coastguard Worker           }
3373*795d594fSAndroid Build Coastguard Worker           break;
3374*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimChar:
3375*795d594fSAndroid Build Coastguard Worker           result_check = "C";
3376*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3377*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3378*795d594fSAndroid Build Coastguard Worker               result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
3379*795d594fSAndroid Build Coastguard Worker               break;
3380*795d594fSAndroid Build Coastguard Worker             case kDirect:
3381*795d594fSAndroid Build Coastguard Worker               result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
3382*795d594fSAndroid Build Coastguard Worker               break;
3383*795d594fSAndroid Build Coastguard Worker             case kStatic:
3384*795d594fSAndroid Build Coastguard Worker               result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
3385*795d594fSAndroid Build Coastguard Worker               break;
3386*795d594fSAndroid Build Coastguard Worker             default:
3387*795d594fSAndroid Build Coastguard Worker               LOG(FATAL) << "Unexpected invoke: " << invoke;
3388*795d594fSAndroid Build Coastguard Worker           }
3389*795d594fSAndroid Build Coastguard Worker           break;
3390*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimShort:
3391*795d594fSAndroid Build Coastguard Worker           result_check = "S";
3392*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3393*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3394*795d594fSAndroid Build Coastguard Worker               result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
3395*795d594fSAndroid Build Coastguard Worker               break;
3396*795d594fSAndroid Build Coastguard Worker             case kDirect:
3397*795d594fSAndroid Build Coastguard Worker               result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
3398*795d594fSAndroid Build Coastguard Worker               break;
3399*795d594fSAndroid Build Coastguard Worker             case kStatic:
3400*795d594fSAndroid Build Coastguard Worker               result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
3401*795d594fSAndroid Build Coastguard Worker               break;
3402*795d594fSAndroid Build Coastguard Worker             default:
3403*795d594fSAndroid Build Coastguard Worker               LOG(FATAL) << "Unexpected invoke: " << invoke;
3404*795d594fSAndroid Build Coastguard Worker           }
3405*795d594fSAndroid Build Coastguard Worker           break;
3406*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimInt:
3407*795d594fSAndroid Build Coastguard Worker           result_check = "I";
3408*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3409*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3410*795d594fSAndroid Build Coastguard Worker               result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
3411*795d594fSAndroid Build Coastguard Worker               break;
3412*795d594fSAndroid Build Coastguard Worker             case kDirect:
3413*795d594fSAndroid Build Coastguard Worker               result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
3414*795d594fSAndroid Build Coastguard Worker               break;
3415*795d594fSAndroid Build Coastguard Worker             case kStatic:
3416*795d594fSAndroid Build Coastguard Worker               result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
3417*795d594fSAndroid Build Coastguard Worker               break;
3418*795d594fSAndroid Build Coastguard Worker             default:
3419*795d594fSAndroid Build Coastguard Worker               LOG(FATAL) << "Unexpected invoke: " << invoke;
3420*795d594fSAndroid Build Coastguard Worker           }
3421*795d594fSAndroid Build Coastguard Worker           break;
3422*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimLong:
3423*795d594fSAndroid Build Coastguard Worker           result_check = "J";
3424*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3425*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3426*795d594fSAndroid Build Coastguard Worker               result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
3427*795d594fSAndroid Build Coastguard Worker               break;
3428*795d594fSAndroid Build Coastguard Worker             case kDirect:
3429*795d594fSAndroid Build Coastguard Worker               result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
3430*795d594fSAndroid Build Coastguard Worker               break;
3431*795d594fSAndroid Build Coastguard Worker             case kStatic:
3432*795d594fSAndroid Build Coastguard Worker               result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
3433*795d594fSAndroid Build Coastguard Worker               break;
3434*795d594fSAndroid Build Coastguard Worker             default:
3435*795d594fSAndroid Build Coastguard Worker               LOG(FATAL) << "Unexpected invoke: " << invoke;
3436*795d594fSAndroid Build Coastguard Worker           }
3437*795d594fSAndroid Build Coastguard Worker           break;
3438*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimFloat:
3439*795d594fSAndroid Build Coastguard Worker           result_check = "F";
3440*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3441*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3442*795d594fSAndroid Build Coastguard Worker               result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
3443*795d594fSAndroid Build Coastguard Worker               break;
3444*795d594fSAndroid Build Coastguard Worker             case kDirect:
3445*795d594fSAndroid Build Coastguard Worker               result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
3446*795d594fSAndroid Build Coastguard Worker               break;
3447*795d594fSAndroid Build Coastguard Worker             case kStatic:
3448*795d594fSAndroid Build Coastguard Worker               result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
3449*795d594fSAndroid Build Coastguard Worker               break;
3450*795d594fSAndroid Build Coastguard Worker             default:
3451*795d594fSAndroid Build Coastguard Worker               LOG(FATAL) << "Unexpected invoke: " << invoke;
3452*795d594fSAndroid Build Coastguard Worker           }
3453*795d594fSAndroid Build Coastguard Worker           break;
3454*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimDouble:
3455*795d594fSAndroid Build Coastguard Worker           result_check = "D";
3456*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3457*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3458*795d594fSAndroid Build Coastguard Worker               result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3459*795d594fSAndroid Build Coastguard Worker               break;
3460*795d594fSAndroid Build Coastguard Worker             case kDirect:
3461*795d594fSAndroid Build Coastguard Worker               result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3462*795d594fSAndroid Build Coastguard Worker               break;
3463*795d594fSAndroid Build Coastguard Worker             case kStatic:
3464*795d594fSAndroid Build Coastguard Worker               result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3465*795d594fSAndroid Build Coastguard Worker               break;
3466*795d594fSAndroid Build Coastguard Worker             default:
3467*795d594fSAndroid Build Coastguard Worker               LOG(FATAL) << "Unexpected invoke: " << invoke;
3468*795d594fSAndroid Build Coastguard Worker           }
3469*795d594fSAndroid Build Coastguard Worker           break;
3470*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimVoid:
3471*795d594fSAndroid Build Coastguard Worker           result_check = "V";
3472*795d594fSAndroid Build Coastguard Worker           result.V = nullptr;
3473*795d594fSAndroid Build Coastguard Worker           switch (invoke) {
3474*795d594fSAndroid Build Coastguard Worker             case kVirtual:
3475*795d594fSAndroid Build Coastguard Worker               baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3476*795d594fSAndroid Build Coastguard Worker               break;
3477*795d594fSAndroid Build Coastguard Worker             case kDirect:
3478*795d594fSAndroid Build Coastguard Worker               baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3479*795d594fSAndroid Build Coastguard Worker               break;
3480*795d594fSAndroid Build Coastguard Worker             case kStatic:
3481*795d594fSAndroid Build Coastguard Worker               baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3482*795d594fSAndroid Build Coastguard Worker               break;
3483*795d594fSAndroid Build Coastguard Worker             default:
3484*795d594fSAndroid Build Coastguard Worker               LOG(FATAL) << "Unexpected invoke: " << invoke;
3485*795d594fSAndroid Build Coastguard Worker           }
3486*795d594fSAndroid Build Coastguard Worker           break;
3487*795d594fSAndroid Build Coastguard Worker       }
3488*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, result_check, &result)) {
3489*795d594fSAndroid Build Coastguard Worker         return result;
3490*795d594fSAndroid Build Coastguard Worker       }
3491*795d594fSAndroid Build Coastguard Worker     }
3492*795d594fSAndroid Build Coastguard Worker     result.J = 0;
3493*795d594fSAndroid Build Coastguard Worker     return result;
3494*795d594fSAndroid Build Coastguard Worker   }
3495*795d594fSAndroid Build Coastguard Worker 
GetStringCharsInternal(const char * function_name,JNIEnv * env,jstring string,jboolean * is_copy,bool utf,bool critical)3496*795d594fSAndroid Build Coastguard Worker   static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3497*795d594fSAndroid Build Coastguard Worker                                             jboolean* is_copy, bool utf, bool critical) {
3498*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(function_name, nullptr);
3499*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
3500*795d594fSAndroid Build Coastguard Worker     int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3501*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(flags, function_name);
3502*795d594fSAndroid Build Coastguard Worker     JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3503*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Esp", args)) {
3504*795d594fSAndroid Build Coastguard Worker       JniValueType result;
3505*795d594fSAndroid Build Coastguard Worker       void* ptr;
3506*795d594fSAndroid Build Coastguard Worker       if (utf) {
3507*795d594fSAndroid Build Coastguard Worker         CHECK(!critical);
3508*795d594fSAndroid Build Coastguard Worker         ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
3509*795d594fSAndroid Build Coastguard Worker         result.u = reinterpret_cast<char*>(ptr);
3510*795d594fSAndroid Build Coastguard Worker       } else {
3511*795d594fSAndroid Build Coastguard Worker         ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
3512*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->GetStringChars(env, string, is_copy));
3513*795d594fSAndroid Build Coastguard Worker         result.p = ptr;
3514*795d594fSAndroid Build Coastguard Worker       }
3515*795d594fSAndroid Build Coastguard Worker       // TODO: could we be smarter about not copying when local_is_copy?
3516*795d594fSAndroid Build Coastguard Worker       if (ptr != nullptr && soa.ForceCopy()) {
3517*795d594fSAndroid Build Coastguard Worker         if (utf) {
3518*795d594fSAndroid Build Coastguard Worker           size_t length_in_bytes = strlen(result.u) + 1;
3519*795d594fSAndroid Build Coastguard Worker           result.u =
3520*795d594fSAndroid Build Coastguard Worker               reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
3521*795d594fSAndroid Build Coastguard Worker         } else {
3522*795d594fSAndroid Build Coastguard Worker           size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3523*795d594fSAndroid Build Coastguard Worker           result.p =
3524*795d594fSAndroid Build Coastguard Worker               reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
3525*795d594fSAndroid Build Coastguard Worker         }
3526*795d594fSAndroid Build Coastguard Worker         if (is_copy != nullptr) {
3527*795d594fSAndroid Build Coastguard Worker           *is_copy = JNI_TRUE;
3528*795d594fSAndroid Build Coastguard Worker         }
3529*795d594fSAndroid Build Coastguard Worker       }
3530*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3531*795d594fSAndroid Build Coastguard Worker         return utf ? result.u : result.p;
3532*795d594fSAndroid Build Coastguard Worker       }
3533*795d594fSAndroid Build Coastguard Worker     }
3534*795d594fSAndroid Build Coastguard Worker     return nullptr;
3535*795d594fSAndroid Build Coastguard Worker   }
3536*795d594fSAndroid Build Coastguard Worker 
ReleaseStringCharsInternal(const char * function_name,JNIEnv * env,jstring string,const void * chars,bool utf,bool critical)3537*795d594fSAndroid Build Coastguard Worker   static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3538*795d594fSAndroid Build Coastguard Worker                                          const void* chars, bool utf, bool critical) {
3539*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD_VOID(function_name);
3540*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
3541*795d594fSAndroid Build Coastguard Worker     int flags = kFlag_ExcepOkay | kFlag_Release;
3542*795d594fSAndroid Build Coastguard Worker     if (critical) {
3543*795d594fSAndroid Build Coastguard Worker       flags |= kFlag_CritRelease;
3544*795d594fSAndroid Build Coastguard Worker     }
3545*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(flags, function_name);
3546*795d594fSAndroid Build Coastguard Worker     sc.CheckNonNull(chars);
3547*795d594fSAndroid Build Coastguard Worker     bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3548*795d594fSAndroid Build Coastguard Worker     if (force_copy_ok && soa.ForceCopy()) {
3549*795d594fSAndroid Build Coastguard Worker       chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3550*795d594fSAndroid Build Coastguard Worker     }
3551*795d594fSAndroid Build Coastguard Worker     if (force_copy_ok) {
3552*795d594fSAndroid Build Coastguard Worker       JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3553*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3554*795d594fSAndroid Build Coastguard Worker         if (utf) {
3555*795d594fSAndroid Build Coastguard Worker           CHECK(!critical);
3556*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3557*795d594fSAndroid Build Coastguard Worker         } else {
3558*795d594fSAndroid Build Coastguard Worker           if (critical) {
3559*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3560*795d594fSAndroid Build Coastguard Worker           } else {
3561*795d594fSAndroid Build Coastguard Worker             baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3562*795d594fSAndroid Build Coastguard Worker           }
3563*795d594fSAndroid Build Coastguard Worker         }
3564*795d594fSAndroid Build Coastguard Worker         JniValueType result;
3565*795d594fSAndroid Build Coastguard Worker         sc.Check(soa, false, "V", &result);
3566*795d594fSAndroid Build Coastguard Worker       }
3567*795d594fSAndroid Build Coastguard Worker     }
3568*795d594fSAndroid Build Coastguard Worker   }
3569*795d594fSAndroid Build Coastguard Worker 
NewPrimitiveArray(const char * function_name,JNIEnv * env,jsize length,Primitive::Type type)3570*795d594fSAndroid Build Coastguard Worker   static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3571*795d594fSAndroid Build Coastguard Worker                                   Primitive::Type type) {
3572*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(function_name, nullptr);
3573*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
3574*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, function_name);
3575*795d594fSAndroid Build Coastguard Worker     JniValueType args[2] = {{.E = env}, {.z = length}};
3576*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Ez", args)) {
3577*795d594fSAndroid Build Coastguard Worker       JniValueType result;
3578*795d594fSAndroid Build Coastguard Worker       switch (type) {
3579*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimBoolean:
3580*795d594fSAndroid Build Coastguard Worker           result.a = baseEnv(env)->NewBooleanArray(env, length);
3581*795d594fSAndroid Build Coastguard Worker           break;
3582*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimByte:
3583*795d594fSAndroid Build Coastguard Worker           result.a = baseEnv(env)->NewByteArray(env, length);
3584*795d594fSAndroid Build Coastguard Worker           break;
3585*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimChar:
3586*795d594fSAndroid Build Coastguard Worker           result.a = baseEnv(env)->NewCharArray(env, length);
3587*795d594fSAndroid Build Coastguard Worker           break;
3588*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimShort:
3589*795d594fSAndroid Build Coastguard Worker           result.a = baseEnv(env)->NewShortArray(env, length);
3590*795d594fSAndroid Build Coastguard Worker           break;
3591*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimInt:
3592*795d594fSAndroid Build Coastguard Worker           result.a = baseEnv(env)->NewIntArray(env, length);
3593*795d594fSAndroid Build Coastguard Worker           break;
3594*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimLong:
3595*795d594fSAndroid Build Coastguard Worker           result.a = baseEnv(env)->NewLongArray(env, length);
3596*795d594fSAndroid Build Coastguard Worker           break;
3597*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimFloat:
3598*795d594fSAndroid Build Coastguard Worker           result.a = baseEnv(env)->NewFloatArray(env, length);
3599*795d594fSAndroid Build Coastguard Worker           break;
3600*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimDouble:
3601*795d594fSAndroid Build Coastguard Worker           result.a = baseEnv(env)->NewDoubleArray(env, length);
3602*795d594fSAndroid Build Coastguard Worker           break;
3603*795d594fSAndroid Build Coastguard Worker         default:
3604*795d594fSAndroid Build Coastguard Worker           LOG(FATAL) << "Unexpected primitive type: " << type;
3605*795d594fSAndroid Build Coastguard Worker       }
3606*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "a", &result)) {
3607*795d594fSAndroid Build Coastguard Worker         return result.a;
3608*795d594fSAndroid Build Coastguard Worker       }
3609*795d594fSAndroid Build Coastguard Worker     }
3610*795d594fSAndroid Build Coastguard Worker     return nullptr;
3611*795d594fSAndroid Build Coastguard Worker   }
3612*795d594fSAndroid Build Coastguard Worker 
GetPrimitiveArrayElements(const char * function_name,Primitive::Type type,JNIEnv * env,jarray array,jboolean * is_copy)3613*795d594fSAndroid Build Coastguard Worker   static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3614*795d594fSAndroid Build Coastguard Worker                                          JNIEnv* env, jarray array, jboolean* is_copy) {
3615*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD(function_name, nullptr);
3616*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
3617*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, function_name);
3618*795d594fSAndroid Build Coastguard Worker     JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3619*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3620*795d594fSAndroid Build Coastguard Worker       JniValueType result;
3621*795d594fSAndroid Build Coastguard Worker       void* ptr = nullptr;
3622*795d594fSAndroid Build Coastguard Worker       switch (type) {
3623*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimBoolean:
3624*795d594fSAndroid Build Coastguard Worker           ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3625*795d594fSAndroid Build Coastguard Worker                                                       is_copy);
3626*795d594fSAndroid Build Coastguard Worker           break;
3627*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimByte:
3628*795d594fSAndroid Build Coastguard Worker           ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
3629*795d594fSAndroid Build Coastguard Worker           break;
3630*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimChar:
3631*795d594fSAndroid Build Coastguard Worker           ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
3632*795d594fSAndroid Build Coastguard Worker           break;
3633*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimShort:
3634*795d594fSAndroid Build Coastguard Worker           ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
3635*795d594fSAndroid Build Coastguard Worker           break;
3636*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimInt:
3637*795d594fSAndroid Build Coastguard Worker           ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
3638*795d594fSAndroid Build Coastguard Worker           break;
3639*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimLong:
3640*795d594fSAndroid Build Coastguard Worker           ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
3641*795d594fSAndroid Build Coastguard Worker           break;
3642*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimFloat:
3643*795d594fSAndroid Build Coastguard Worker           ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
3644*795d594fSAndroid Build Coastguard Worker           break;
3645*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimDouble:
3646*795d594fSAndroid Build Coastguard Worker           ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
3647*795d594fSAndroid Build Coastguard Worker           break;
3648*795d594fSAndroid Build Coastguard Worker         default:
3649*795d594fSAndroid Build Coastguard Worker           LOG(FATAL) << "Unexpected primitive type: " << type;
3650*795d594fSAndroid Build Coastguard Worker       }
3651*795d594fSAndroid Build Coastguard Worker       if (ptr != nullptr && soa.ForceCopy()) {
3652*795d594fSAndroid Build Coastguard Worker         ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
3653*795d594fSAndroid Build Coastguard Worker         if (is_copy != nullptr) {
3654*795d594fSAndroid Build Coastguard Worker           *is_copy = JNI_TRUE;
3655*795d594fSAndroid Build Coastguard Worker         }
3656*795d594fSAndroid Build Coastguard Worker       }
3657*795d594fSAndroid Build Coastguard Worker       result.p = ptr;
3658*795d594fSAndroid Build Coastguard Worker       if (sc.Check(soa, false, "p", &result)) {
3659*795d594fSAndroid Build Coastguard Worker         return const_cast<void*>(result.p);
3660*795d594fSAndroid Build Coastguard Worker       }
3661*795d594fSAndroid Build Coastguard Worker     }
3662*795d594fSAndroid Build Coastguard Worker     return nullptr;
3663*795d594fSAndroid Build Coastguard Worker   }
3664*795d594fSAndroid Build Coastguard Worker 
ReleasePrimitiveArrayElements(const char * function_name,Primitive::Type type,JNIEnv * env,jarray array,void * elems,jint mode)3665*795d594fSAndroid Build Coastguard Worker   static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3666*795d594fSAndroid Build Coastguard Worker                                             JNIEnv* env, jarray array, void* elems, jint mode) {
3667*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD_VOID(function_name);
3668*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
3669*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_ExcepOkay, function_name);
3670*795d594fSAndroid Build Coastguard Worker     if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3671*795d594fSAndroid Build Coastguard Worker       if (soa.ForceCopy()) {
3672*795d594fSAndroid Build Coastguard Worker         elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3673*795d594fSAndroid Build Coastguard Worker       }
3674*795d594fSAndroid Build Coastguard Worker       if (!soa.ForceCopy() || elems != nullptr) {
3675*795d594fSAndroid Build Coastguard Worker         JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3676*795d594fSAndroid Build Coastguard Worker         if (sc.Check(soa, true, "Eapr", args)) {
3677*795d594fSAndroid Build Coastguard Worker           switch (type) {
3678*795d594fSAndroid Build Coastguard Worker             case Primitive::kPrimBoolean:
3679*795d594fSAndroid Build Coastguard Worker               baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3680*795d594fSAndroid Build Coastguard Worker                                                         reinterpret_cast<jboolean*>(elems), mode);
3681*795d594fSAndroid Build Coastguard Worker               break;
3682*795d594fSAndroid Build Coastguard Worker             case Primitive::kPrimByte:
3683*795d594fSAndroid Build Coastguard Worker               baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3684*795d594fSAndroid Build Coastguard Worker                                                      reinterpret_cast<jbyte*>(elems), mode);
3685*795d594fSAndroid Build Coastguard Worker               break;
3686*795d594fSAndroid Build Coastguard Worker             case Primitive::kPrimChar:
3687*795d594fSAndroid Build Coastguard Worker               baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3688*795d594fSAndroid Build Coastguard Worker                                                      reinterpret_cast<jchar*>(elems), mode);
3689*795d594fSAndroid Build Coastguard Worker               break;
3690*795d594fSAndroid Build Coastguard Worker             case Primitive::kPrimShort:
3691*795d594fSAndroid Build Coastguard Worker               baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3692*795d594fSAndroid Build Coastguard Worker                                                       reinterpret_cast<jshort*>(elems), mode);
3693*795d594fSAndroid Build Coastguard Worker               break;
3694*795d594fSAndroid Build Coastguard Worker             case Primitive::kPrimInt:
3695*795d594fSAndroid Build Coastguard Worker               baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3696*795d594fSAndroid Build Coastguard Worker                                                     reinterpret_cast<jint*>(elems), mode);
3697*795d594fSAndroid Build Coastguard Worker               break;
3698*795d594fSAndroid Build Coastguard Worker             case Primitive::kPrimLong:
3699*795d594fSAndroid Build Coastguard Worker               baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3700*795d594fSAndroid Build Coastguard Worker                                                      reinterpret_cast<jlong*>(elems), mode);
3701*795d594fSAndroid Build Coastguard Worker               break;
3702*795d594fSAndroid Build Coastguard Worker             case Primitive::kPrimFloat:
3703*795d594fSAndroid Build Coastguard Worker               baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3704*795d594fSAndroid Build Coastguard Worker                                                       reinterpret_cast<jfloat*>(elems), mode);
3705*795d594fSAndroid Build Coastguard Worker               break;
3706*795d594fSAndroid Build Coastguard Worker             case Primitive::kPrimDouble:
3707*795d594fSAndroid Build Coastguard Worker               baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3708*795d594fSAndroid Build Coastguard Worker                                                        reinterpret_cast<jdouble*>(elems), mode);
3709*795d594fSAndroid Build Coastguard Worker               break;
3710*795d594fSAndroid Build Coastguard Worker             default:
3711*795d594fSAndroid Build Coastguard Worker               LOG(FATAL) << "Unexpected primitive type: " << type;
3712*795d594fSAndroid Build Coastguard Worker           }
3713*795d594fSAndroid Build Coastguard Worker           JniValueType result;
3714*795d594fSAndroid Build Coastguard Worker           result.V = nullptr;
3715*795d594fSAndroid Build Coastguard Worker           sc.Check(soa, false, "V", &result);
3716*795d594fSAndroid Build Coastguard Worker         }
3717*795d594fSAndroid Build Coastguard Worker       }
3718*795d594fSAndroid Build Coastguard Worker     }
3719*795d594fSAndroid Build Coastguard Worker   }
3720*795d594fSAndroid Build Coastguard Worker 
GetPrimitiveArrayRegion(const char * function_name,Primitive::Type type,JNIEnv * env,jarray array,jsize start,jsize len,void * buf)3721*795d594fSAndroid Build Coastguard Worker   static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3722*795d594fSAndroid Build Coastguard Worker                                       jarray array, jsize start, jsize len, void* buf) {
3723*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD_VOID(function_name);
3724*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
3725*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, function_name);
3726*795d594fSAndroid Build Coastguard Worker     JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3727*795d594fSAndroid Build Coastguard Worker     // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3728*795d594fSAndroid Build Coastguard Worker     // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3729*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3730*795d594fSAndroid Build Coastguard Worker       switch (type) {
3731*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimBoolean:
3732*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3733*795d594fSAndroid Build Coastguard Worker                                               reinterpret_cast<jboolean*>(buf));
3734*795d594fSAndroid Build Coastguard Worker           break;
3735*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimByte:
3736*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3737*795d594fSAndroid Build Coastguard Worker                                            reinterpret_cast<jbyte*>(buf));
3738*795d594fSAndroid Build Coastguard Worker           break;
3739*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimChar:
3740*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3741*795d594fSAndroid Build Coastguard Worker                                            reinterpret_cast<jchar*>(buf));
3742*795d594fSAndroid Build Coastguard Worker           break;
3743*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimShort:
3744*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3745*795d594fSAndroid Build Coastguard Worker                                             reinterpret_cast<jshort*>(buf));
3746*795d594fSAndroid Build Coastguard Worker           break;
3747*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimInt:
3748*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3749*795d594fSAndroid Build Coastguard Worker                                           reinterpret_cast<jint*>(buf));
3750*795d594fSAndroid Build Coastguard Worker           break;
3751*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimLong:
3752*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3753*795d594fSAndroid Build Coastguard Worker                                            reinterpret_cast<jlong*>(buf));
3754*795d594fSAndroid Build Coastguard Worker           break;
3755*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimFloat:
3756*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3757*795d594fSAndroid Build Coastguard Worker                                             reinterpret_cast<jfloat*>(buf));
3758*795d594fSAndroid Build Coastguard Worker           break;
3759*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimDouble:
3760*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3761*795d594fSAndroid Build Coastguard Worker                                              reinterpret_cast<jdouble*>(buf));
3762*795d594fSAndroid Build Coastguard Worker           break;
3763*795d594fSAndroid Build Coastguard Worker         default:
3764*795d594fSAndroid Build Coastguard Worker           LOG(FATAL) << "Unexpected primitive type: " << type;
3765*795d594fSAndroid Build Coastguard Worker       }
3766*795d594fSAndroid Build Coastguard Worker       JniValueType result;
3767*795d594fSAndroid Build Coastguard Worker       result.V = nullptr;
3768*795d594fSAndroid Build Coastguard Worker       sc.Check(soa, false, "V", &result);
3769*795d594fSAndroid Build Coastguard Worker     }
3770*795d594fSAndroid Build Coastguard Worker   }
3771*795d594fSAndroid Build Coastguard Worker 
SetPrimitiveArrayRegion(const char * function_name,Primitive::Type type,JNIEnv * env,jarray array,jsize start,jsize len,const void * buf)3772*795d594fSAndroid Build Coastguard Worker   static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3773*795d594fSAndroid Build Coastguard Worker                                       jarray array, jsize start, jsize len, const void* buf) {
3774*795d594fSAndroid Build Coastguard Worker     CHECK_ATTACHED_THREAD_VOID(function_name);
3775*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(env);
3776*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Default, function_name);
3777*795d594fSAndroid Build Coastguard Worker     JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3778*795d594fSAndroid Build Coastguard Worker     // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3779*795d594fSAndroid Build Coastguard Worker     // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3780*795d594fSAndroid Build Coastguard Worker     if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3781*795d594fSAndroid Build Coastguard Worker       switch (type) {
3782*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimBoolean:
3783*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3784*795d594fSAndroid Build Coastguard Worker                                               reinterpret_cast<const jboolean*>(buf));
3785*795d594fSAndroid Build Coastguard Worker           break;
3786*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimByte:
3787*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3788*795d594fSAndroid Build Coastguard Worker                                            reinterpret_cast<const jbyte*>(buf));
3789*795d594fSAndroid Build Coastguard Worker           break;
3790*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimChar:
3791*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3792*795d594fSAndroid Build Coastguard Worker                                            reinterpret_cast<const jchar*>(buf));
3793*795d594fSAndroid Build Coastguard Worker           break;
3794*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimShort:
3795*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3796*795d594fSAndroid Build Coastguard Worker                                               reinterpret_cast<const jshort*>(buf));
3797*795d594fSAndroid Build Coastguard Worker           break;
3798*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimInt:
3799*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3800*795d594fSAndroid Build Coastguard Worker                                           reinterpret_cast<const jint*>(buf));
3801*795d594fSAndroid Build Coastguard Worker           break;
3802*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimLong:
3803*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3804*795d594fSAndroid Build Coastguard Worker                                               reinterpret_cast<const jlong*>(buf));
3805*795d594fSAndroid Build Coastguard Worker           break;
3806*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimFloat:
3807*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3808*795d594fSAndroid Build Coastguard Worker                                             reinterpret_cast<const jfloat*>(buf));
3809*795d594fSAndroid Build Coastguard Worker           break;
3810*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimDouble:
3811*795d594fSAndroid Build Coastguard Worker           baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3812*795d594fSAndroid Build Coastguard Worker                                              reinterpret_cast<const jdouble*>(buf));
3813*795d594fSAndroid Build Coastguard Worker           break;
3814*795d594fSAndroid Build Coastguard Worker         default:
3815*795d594fSAndroid Build Coastguard Worker           LOG(FATAL) << "Unexpected primitive type: " << type;
3816*795d594fSAndroid Build Coastguard Worker       }
3817*795d594fSAndroid Build Coastguard Worker       JniValueType result;
3818*795d594fSAndroid Build Coastguard Worker       result.V = nullptr;
3819*795d594fSAndroid Build Coastguard Worker       sc.Check(soa, false, "V", &result);
3820*795d594fSAndroid Build Coastguard Worker     }
3821*795d594fSAndroid Build Coastguard Worker   }
3822*795d594fSAndroid Build Coastguard Worker };
3823*795d594fSAndroid Build Coastguard Worker 
3824*795d594fSAndroid Build Coastguard Worker const JNINativeInterface gCheckNativeInterface = {
3825*795d594fSAndroid Build Coastguard Worker   nullptr,  // reserved0.
3826*795d594fSAndroid Build Coastguard Worker   nullptr,  // reserved1.
3827*795d594fSAndroid Build Coastguard Worker   nullptr,  // reserved2.
3828*795d594fSAndroid Build Coastguard Worker   nullptr,  // reserved3.
3829*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetVersion,
3830*795d594fSAndroid Build Coastguard Worker   CheckJNI::DefineClass,
3831*795d594fSAndroid Build Coastguard Worker   CheckJNI::FindClass,
3832*795d594fSAndroid Build Coastguard Worker   CheckJNI::FromReflectedMethod,
3833*795d594fSAndroid Build Coastguard Worker   CheckJNI::FromReflectedField,
3834*795d594fSAndroid Build Coastguard Worker   CheckJNI::ToReflectedMethod,
3835*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetSuperclass,
3836*795d594fSAndroid Build Coastguard Worker   CheckJNI::IsAssignableFrom,
3837*795d594fSAndroid Build Coastguard Worker   CheckJNI::ToReflectedField,
3838*795d594fSAndroid Build Coastguard Worker   CheckJNI::Throw,
3839*795d594fSAndroid Build Coastguard Worker   CheckJNI::ThrowNew,
3840*795d594fSAndroid Build Coastguard Worker   CheckJNI::ExceptionOccurred,
3841*795d594fSAndroid Build Coastguard Worker   CheckJNI::ExceptionDescribe,
3842*795d594fSAndroid Build Coastguard Worker   CheckJNI::ExceptionClear,
3843*795d594fSAndroid Build Coastguard Worker   CheckJNI::FatalError,
3844*795d594fSAndroid Build Coastguard Worker   CheckJNI::PushLocalFrame,
3845*795d594fSAndroid Build Coastguard Worker   CheckJNI::PopLocalFrame,
3846*795d594fSAndroid Build Coastguard Worker   CheckJNI::NewGlobalRef,
3847*795d594fSAndroid Build Coastguard Worker   CheckJNI::DeleteGlobalRef,
3848*795d594fSAndroid Build Coastguard Worker   CheckJNI::DeleteLocalRef,
3849*795d594fSAndroid Build Coastguard Worker   CheckJNI::IsSameObject,
3850*795d594fSAndroid Build Coastguard Worker   CheckJNI::NewLocalRef,
3851*795d594fSAndroid Build Coastguard Worker   CheckJNI::EnsureLocalCapacity,
3852*795d594fSAndroid Build Coastguard Worker   CheckJNI::AllocObject,
3853*795d594fSAndroid Build Coastguard Worker   CheckJNI::NewObject,
3854*795d594fSAndroid Build Coastguard Worker   CheckJNI::NewObjectV,
3855*795d594fSAndroid Build Coastguard Worker   CheckJNI::NewObjectA,
3856*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetObjectClass,
3857*795d594fSAndroid Build Coastguard Worker   CheckJNI::IsInstanceOf,
3858*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetMethodID,
3859*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallObjectMethod,
3860*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallObjectMethodV,
3861*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallObjectMethodA,
3862*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallBooleanMethod,
3863*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallBooleanMethodV,
3864*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallBooleanMethodA,
3865*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallByteMethod,
3866*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallByteMethodV,
3867*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallByteMethodA,
3868*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallCharMethod,
3869*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallCharMethodV,
3870*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallCharMethodA,
3871*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallShortMethod,
3872*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallShortMethodV,
3873*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallShortMethodA,
3874*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallIntMethod,
3875*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallIntMethodV,
3876*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallIntMethodA,
3877*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallLongMethod,
3878*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallLongMethodV,
3879*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallLongMethodA,
3880*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallFloatMethod,
3881*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallFloatMethodV,
3882*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallFloatMethodA,
3883*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallDoubleMethod,
3884*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallDoubleMethodV,
3885*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallDoubleMethodA,
3886*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallVoidMethod,
3887*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallVoidMethodV,
3888*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallVoidMethodA,
3889*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualObjectMethod,
3890*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualObjectMethodV,
3891*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualObjectMethodA,
3892*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualBooleanMethod,
3893*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualBooleanMethodV,
3894*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualBooleanMethodA,
3895*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualByteMethod,
3896*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualByteMethodV,
3897*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualByteMethodA,
3898*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualCharMethod,
3899*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualCharMethodV,
3900*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualCharMethodA,
3901*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualShortMethod,
3902*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualShortMethodV,
3903*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualShortMethodA,
3904*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualIntMethod,
3905*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualIntMethodV,
3906*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualIntMethodA,
3907*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualLongMethod,
3908*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualLongMethodV,
3909*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualLongMethodA,
3910*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualFloatMethod,
3911*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualFloatMethodV,
3912*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualFloatMethodA,
3913*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualDoubleMethod,
3914*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualDoubleMethodV,
3915*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualDoubleMethodA,
3916*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualVoidMethod,
3917*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualVoidMethodV,
3918*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallNonvirtualVoidMethodA,
3919*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetFieldID,
3920*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetObjectField,
3921*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetBooleanField,
3922*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetByteField,
3923*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetCharField,
3924*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetShortField,
3925*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetIntField,
3926*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetLongField,
3927*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetFloatField,
3928*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetDoubleField,
3929*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetObjectField,
3930*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetBooleanField,
3931*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetByteField,
3932*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetCharField,
3933*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetShortField,
3934*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetIntField,
3935*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetLongField,
3936*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetFloatField,
3937*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetDoubleField,
3938*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetStaticMethodID,
3939*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticObjectMethod,
3940*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticObjectMethodV,
3941*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticObjectMethodA,
3942*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticBooleanMethod,
3943*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticBooleanMethodV,
3944*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticBooleanMethodA,
3945*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticByteMethod,
3946*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticByteMethodV,
3947*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticByteMethodA,
3948*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticCharMethod,
3949*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticCharMethodV,
3950*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticCharMethodA,
3951*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticShortMethod,
3952*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticShortMethodV,
3953*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticShortMethodA,
3954*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticIntMethod,
3955*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticIntMethodV,
3956*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticIntMethodA,
3957*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticLongMethod,
3958*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticLongMethodV,
3959*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticLongMethodA,
3960*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticFloatMethod,
3961*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticFloatMethodV,
3962*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticFloatMethodA,
3963*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticDoubleMethod,
3964*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticDoubleMethodV,
3965*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticDoubleMethodA,
3966*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticVoidMethod,
3967*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticVoidMethodV,
3968*795d594fSAndroid Build Coastguard Worker   CheckJNI::CallStaticVoidMethodA,
3969*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetStaticFieldID,
3970*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetStaticObjectField,
3971*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetStaticBooleanField,
3972*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetStaticByteField,
3973*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetStaticCharField,
3974*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetStaticShortField,
3975*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetStaticIntField,
3976*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetStaticLongField,
3977*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetStaticFloatField,
3978*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetStaticDoubleField,
3979*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetStaticObjectField,
3980*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetStaticBooleanField,
3981*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetStaticByteField,
3982*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetStaticCharField,
3983*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetStaticShortField,
3984*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetStaticIntField,
3985*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetStaticLongField,
3986*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetStaticFloatField,
3987*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetStaticDoubleField,
3988*795d594fSAndroid Build Coastguard Worker   CheckJNI::NewString,
3989*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetStringLength,
3990*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetStringChars,
3991*795d594fSAndroid Build Coastguard Worker   CheckJNI::ReleaseStringChars,
3992*795d594fSAndroid Build Coastguard Worker   CheckJNI::NewStringUTF,
3993*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetStringUTFLength,
3994*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetStringUTFChars,
3995*795d594fSAndroid Build Coastguard Worker   CheckJNI::ReleaseStringUTFChars,
3996*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetArrayLength,
3997*795d594fSAndroid Build Coastguard Worker   CheckJNI::NewObjectArray,
3998*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetObjectArrayElement,
3999*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetObjectArrayElement,
4000*795d594fSAndroid Build Coastguard Worker   CheckJNI::NewBooleanArray,
4001*795d594fSAndroid Build Coastguard Worker   CheckJNI::NewByteArray,
4002*795d594fSAndroid Build Coastguard Worker   CheckJNI::NewCharArray,
4003*795d594fSAndroid Build Coastguard Worker   CheckJNI::NewShortArray,
4004*795d594fSAndroid Build Coastguard Worker   CheckJNI::NewIntArray,
4005*795d594fSAndroid Build Coastguard Worker   CheckJNI::NewLongArray,
4006*795d594fSAndroid Build Coastguard Worker   CheckJNI::NewFloatArray,
4007*795d594fSAndroid Build Coastguard Worker   CheckJNI::NewDoubleArray,
4008*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetBooleanArrayElements,
4009*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetByteArrayElements,
4010*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetCharArrayElements,
4011*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetShortArrayElements,
4012*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetIntArrayElements,
4013*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetLongArrayElements,
4014*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetFloatArrayElements,
4015*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetDoubleArrayElements,
4016*795d594fSAndroid Build Coastguard Worker   CheckJNI::ReleaseBooleanArrayElements,
4017*795d594fSAndroid Build Coastguard Worker   CheckJNI::ReleaseByteArrayElements,
4018*795d594fSAndroid Build Coastguard Worker   CheckJNI::ReleaseCharArrayElements,
4019*795d594fSAndroid Build Coastguard Worker   CheckJNI::ReleaseShortArrayElements,
4020*795d594fSAndroid Build Coastguard Worker   CheckJNI::ReleaseIntArrayElements,
4021*795d594fSAndroid Build Coastguard Worker   CheckJNI::ReleaseLongArrayElements,
4022*795d594fSAndroid Build Coastguard Worker   CheckJNI::ReleaseFloatArrayElements,
4023*795d594fSAndroid Build Coastguard Worker   CheckJNI::ReleaseDoubleArrayElements,
4024*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetBooleanArrayRegion,
4025*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetByteArrayRegion,
4026*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetCharArrayRegion,
4027*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetShortArrayRegion,
4028*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetIntArrayRegion,
4029*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetLongArrayRegion,
4030*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetFloatArrayRegion,
4031*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetDoubleArrayRegion,
4032*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetBooleanArrayRegion,
4033*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetByteArrayRegion,
4034*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetCharArrayRegion,
4035*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetShortArrayRegion,
4036*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetIntArrayRegion,
4037*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetLongArrayRegion,
4038*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetFloatArrayRegion,
4039*795d594fSAndroid Build Coastguard Worker   CheckJNI::SetDoubleArrayRegion,
4040*795d594fSAndroid Build Coastguard Worker   CheckJNI::RegisterNatives,
4041*795d594fSAndroid Build Coastguard Worker   CheckJNI::UnregisterNatives,
4042*795d594fSAndroid Build Coastguard Worker   CheckJNI::MonitorEnter,
4043*795d594fSAndroid Build Coastguard Worker   CheckJNI::MonitorExit,
4044*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetJavaVM,
4045*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetStringRegion,
4046*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetStringUTFRegion,
4047*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetPrimitiveArrayCritical,
4048*795d594fSAndroid Build Coastguard Worker   CheckJNI::ReleasePrimitiveArrayCritical,
4049*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetStringCritical,
4050*795d594fSAndroid Build Coastguard Worker   CheckJNI::ReleaseStringCritical,
4051*795d594fSAndroid Build Coastguard Worker   CheckJNI::NewWeakGlobalRef,
4052*795d594fSAndroid Build Coastguard Worker   CheckJNI::DeleteWeakGlobalRef,
4053*795d594fSAndroid Build Coastguard Worker   CheckJNI::ExceptionCheck,
4054*795d594fSAndroid Build Coastguard Worker   CheckJNI::NewDirectByteBuffer,
4055*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetDirectBufferAddress,
4056*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetDirectBufferCapacity,
4057*795d594fSAndroid Build Coastguard Worker   CheckJNI::GetObjectRefType,
4058*795d594fSAndroid Build Coastguard Worker };
4059*795d594fSAndroid Build Coastguard Worker 
4060*795d594fSAndroid Build Coastguard Worker class CheckJII {
4061*795d594fSAndroid Build Coastguard Worker  public:
DestroyJavaVM(JavaVM * vm)4062*795d594fSAndroid Build Coastguard Worker   static jint DestroyJavaVM(JavaVM* vm) {
4063*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
4064*795d594fSAndroid Build Coastguard Worker     JniValueType args[1] = {{.v = vm}};
4065*795d594fSAndroid Build Coastguard Worker     sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
4066*795d594fSAndroid Build Coastguard Worker     JniValueType result;
4067*795d594fSAndroid Build Coastguard Worker     result.i = BaseVm(vm)->DestroyJavaVM(vm);
4068*795d594fSAndroid Build Coastguard Worker     // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
4069*795d594fSAndroid Build Coastguard Worker     // which will delete the JavaVMExt.
4070*795d594fSAndroid Build Coastguard Worker     sc.CheckNonHeap(nullptr, false, "i", &result);
4071*795d594fSAndroid Build Coastguard Worker     return result.i;
4072*795d594fSAndroid Build Coastguard Worker   }
4073*795d594fSAndroid Build Coastguard Worker 
AttachCurrentThread(JavaVM * vm,JNIEnv ** p_env,void * thr_args)4074*795d594fSAndroid Build Coastguard Worker   static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
4075*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
4076*795d594fSAndroid Build Coastguard Worker     JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
4077*795d594fSAndroid Build Coastguard Worker     sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
4078*795d594fSAndroid Build Coastguard Worker     JniValueType result;
4079*795d594fSAndroid Build Coastguard Worker     result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
4080*795d594fSAndroid Build Coastguard Worker     sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
4081*795d594fSAndroid Build Coastguard Worker     return result.i;
4082*795d594fSAndroid Build Coastguard Worker   }
4083*795d594fSAndroid Build Coastguard Worker 
AttachCurrentThreadAsDaemon(JavaVM * vm,JNIEnv ** p_env,void * thr_args)4084*795d594fSAndroid Build Coastguard Worker   static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
4085*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
4086*795d594fSAndroid Build Coastguard Worker     JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
4087*795d594fSAndroid Build Coastguard Worker     sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
4088*795d594fSAndroid Build Coastguard Worker     JniValueType result;
4089*795d594fSAndroid Build Coastguard Worker     result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
4090*795d594fSAndroid Build Coastguard Worker     sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
4091*795d594fSAndroid Build Coastguard Worker     return result.i;
4092*795d594fSAndroid Build Coastguard Worker   }
4093*795d594fSAndroid Build Coastguard Worker 
DetachCurrentThread(JavaVM * vm)4094*795d594fSAndroid Build Coastguard Worker   static jint DetachCurrentThread(JavaVM* vm) {
4095*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
4096*795d594fSAndroid Build Coastguard Worker     JniValueType args[1] = {{.v = vm}};
4097*795d594fSAndroid Build Coastguard Worker     sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
4098*795d594fSAndroid Build Coastguard Worker     JniValueType result;
4099*795d594fSAndroid Build Coastguard Worker     result.i = BaseVm(vm)->DetachCurrentThread(vm);
4100*795d594fSAndroid Build Coastguard Worker     sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
4101*795d594fSAndroid Build Coastguard Worker     return result.i;
4102*795d594fSAndroid Build Coastguard Worker   }
4103*795d594fSAndroid Build Coastguard Worker 
GetEnv(JavaVM * vm,void ** p_env,jint version)4104*795d594fSAndroid Build Coastguard Worker   static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
4105*795d594fSAndroid Build Coastguard Worker     ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
4106*795d594fSAndroid Build Coastguard Worker     JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
4107*795d594fSAndroid Build Coastguard Worker     sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
4108*795d594fSAndroid Build Coastguard Worker     JniValueType result;
4109*795d594fSAndroid Build Coastguard Worker     result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
4110*795d594fSAndroid Build Coastguard Worker     sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
4111*795d594fSAndroid Build Coastguard Worker     return result.i;
4112*795d594fSAndroid Build Coastguard Worker   }
4113*795d594fSAndroid Build Coastguard Worker 
4114*795d594fSAndroid Build Coastguard Worker  private:
BaseVm(JavaVM * vm)4115*795d594fSAndroid Build Coastguard Worker   static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
4116*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
4117*795d594fSAndroid Build Coastguard Worker   }
4118*795d594fSAndroid Build Coastguard Worker };
4119*795d594fSAndroid Build Coastguard Worker 
4120*795d594fSAndroid Build Coastguard Worker const JNIInvokeInterface gCheckInvokeInterface = {
4121*795d594fSAndroid Build Coastguard Worker   nullptr,  // reserved0
4122*795d594fSAndroid Build Coastguard Worker   nullptr,  // reserved1
4123*795d594fSAndroid Build Coastguard Worker   nullptr,  // reserved2
4124*795d594fSAndroid Build Coastguard Worker   CheckJII::DestroyJavaVM,
4125*795d594fSAndroid Build Coastguard Worker   CheckJII::AttachCurrentThread,
4126*795d594fSAndroid Build Coastguard Worker   CheckJII::DetachCurrentThread,
4127*795d594fSAndroid Build Coastguard Worker   CheckJII::GetEnv,
4128*795d594fSAndroid Build Coastguard Worker   CheckJII::AttachCurrentThreadAsDaemon
4129*795d594fSAndroid Build Coastguard Worker };
4130*795d594fSAndroid Build Coastguard Worker 
4131*795d594fSAndroid Build Coastguard Worker }  // anonymous namespace
4132*795d594fSAndroid Build Coastguard Worker 
GetCheckJniNativeInterface()4133*795d594fSAndroid Build Coastguard Worker const JNINativeInterface* GetCheckJniNativeInterface() {
4134*795d594fSAndroid Build Coastguard Worker   return &gCheckNativeInterface;
4135*795d594fSAndroid Build Coastguard Worker }
4136*795d594fSAndroid Build Coastguard Worker 
GetCheckJniInvokeInterface()4137*795d594fSAndroid Build Coastguard Worker const JNIInvokeInterface* GetCheckJniInvokeInterface() {
4138*795d594fSAndroid Build Coastguard Worker   return &gCheckInvokeInterface;
4139*795d594fSAndroid Build Coastguard Worker }
4140*795d594fSAndroid Build Coastguard Worker 
4141*795d594fSAndroid Build Coastguard Worker }  // namespace art
4142