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