OSDN Git Service

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