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