check_jni.cc revision 277ccbd200ea43590dfc06a93ae184a765327ad0
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 2207ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h" 23c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers#include "base/to_str.h" 24a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include "class_linker.h" 252dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "class_linker-inl.h" 264f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h" 2722d5e735f403c57525fe868304c7123f0ce66399Ian Rogers#include "field_helper.h" 281d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/space.h" 2968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#include "java_vm_ext.h" 30277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#include "jni_internal.h" 31ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_field-inl.h" 32ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h" 332dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h" 342dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h" 352dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h" 36b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers#include "mirror/string-inl.h" 372dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/throwable.h" 3858df32711162823647356afe25ae2cde04133563Jeff Hao#include "runtime.h" 3900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h" 40a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include "thread.h" 4168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#include "well_known_classes.h" 42a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 43a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesnamespace art { 44a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 45a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/* 46a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * =========================================================================== 47a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * JNI function helpers 48a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * =========================================================================== 49a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 50a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 513f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes// Flags passed into ScopedCheck. 52a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define kFlag_Default 0x0000 53a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 543f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritBad 0x0000 // Calling while in critical is not allowed. 553f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritOkay 0x0001 // Calling while in critical is allowed. 563f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritGet 0x0002 // This is a critical "get". 573f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritRelease 0x0003 // This is a critical "release". 583f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritMask 0x0003 // Bit mask to get "crit" value. 59a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 603f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_ExcepBad 0x0000 // Raised exceptions are not allowed. 613f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_ExcepOkay 0x0004 // Raised exceptions are allowed. 62a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 633f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_Release 0x0010 // Are we in a non-critical release function? 643f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_NullableUtf 0x0020 // Are our UTF parameters nullable? 65a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 663f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_Invocation 0x8000 // Part of the invocation interface (JavaVM*). 67a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 68485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes#define kFlag_ForceTrace 0x80000000 // Add this to a JNI function's flags if you want to trace every call. 6968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers/* 7068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Java primitive types: 7168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * B - jbyte 7268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * C - jchar 7368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * D - jdouble 7468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * F - jfloat 7568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * I - jint 7668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * J - jlong 7768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * S - jshort 7868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Z - jboolean (shown as true and false) 7968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * V - void 8068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * 8168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Java reference types: 8268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * L - jobject 8368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * a - jarray 8468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * c - jclass 8568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * s - jstring 8668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * t - jthrowable 8768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * 8868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * JNI types: 8968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * b - jboolean (shown as JNI_TRUE and JNI_FALSE) 9068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * f - jfieldID 9168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION) 9268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * m - jmethodID 9368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * p - void* 9468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * r - jint (for release mode arguments) 9568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * u - const char* (Modified UTF-8) 9668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * z - jsize (for lengths; use i if negative values are okay) 9768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * v - JavaVM* 9868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * w - jobjectRefType 9968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * E - JNIEnv* 10068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * . - no argument; just print "..." (used for varargs JNI calls) 10168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * 10268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers */ 10368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogersunion JniValueType { 10468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jarray a; 10568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jboolean b; 10668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jclass c; 10768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jfieldID f; 10868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jint i; 10968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jmethodID m; 11068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const void* p; // Pointer. 11168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jint r; // Release mode. 11268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jstring s; 11368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jthrowable t; 11468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const char* u; // Modified UTF-8. 11568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JavaVM* v; 11668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jobjectRefType w; 11768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jsize z; 11868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jbyte B; 11968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jchar C; 12068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jdouble D; 12168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JNIEnv* E; 12268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jfloat F; 12368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jint I; 12468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jlong J; 12568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jobject L; 12668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jshort S; 12768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const void* V; // void 12868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jboolean Z; 129a09576416788b916095739e43a16917e7948f3a4Elliott Hughes}; 130a09576416788b916095739e43a16917e7948f3a4Elliott Hughes 131a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesclass ScopedCheck { 132ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes public: 13368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers explicit ScopedCheck(int flags, const char* functionName, bool has_method = true) 13468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers : function_name_(functionName), flags_(flags), indent_(0), has_method_(has_method) { 13500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 13600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 13768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ~ScopedCheck() {} 138a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 13981ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread" 14081ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of 14181ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some 14281ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes // circumstances, but this is incorrect. 14368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckClassName(const char* class_name) { 1442d10b206f9d0b97396b7dadb9a6415cd39efd341Ian Rogers if ((class_name == nullptr) || !IsValidJniClassName(class_name)) { 14568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("illegal class name '%s'\n" 14668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')", 14768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers class_name); 14868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 149a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 15068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 151a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 152a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 153a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 154a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Verify that this instance field ID is valid for this object. 155a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 156a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Assumes "jobj" has already been validated. 157a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 15868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid) 159b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 16068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Object* o = soa.Decode<mirror::Object*>(java_object); 16168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (o == nullptr) { 16268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("field operation on NULL object: %p", java_object); 16368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 16468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 16568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) { 1664c13a3ff475f206c4d0a86ee2595c45392fd942fMathieu Chartier Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR)); 16768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("field operation on invalid %s: %p", 16868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), 16968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers java_object); 17068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 171a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 172a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 17368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::ArtField* f = CheckFieldID(soa, fid); 174ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (f == nullptr) { 17568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 17632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 1772dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = o->GetClass(); 17861c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) { 17968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("jfieldID %s not valid for an object of class %s", 18068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PrettyField(f).c_str(), PrettyTypeOf(o).c_str()); 18168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 182a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 18368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 184a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 185a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 186a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 187a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Verify that the pointer value is non-NULL. 188a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 18968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckNonNull(const void* ptr) { 19068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (UNLIKELY(ptr == nullptr)) { 19168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("non-nullable argument was NULL"); 19268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 193a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 19468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 195a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 196a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 197a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 198a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Verify that the method's return type matches the type of call. 199a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 'expectedType' will be "L" for all objects, including arrays. 200a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 20168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc, 20268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jmethodID mid, Primitive::Type type, InvokeType invoke) 203b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 20468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::ArtMethod* m = CheckMethodID(soa, mid); 205ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (m == nullptr) { 20668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 20732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 20868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (type != Primitive::GetType(m->GetShorty()[0])) { 20968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("the return type of %s does not match %s", function_name_, PrettyMethod(m).c_str()); 21068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 2113f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes } 21268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool is_static = (invoke == kStatic); 21368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static != m->IsStatic()) { 21468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 21568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("calling non-static method %s with %s", 21668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PrettyMethod(m).c_str(), function_name_); 217a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 21868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("calling static method %s with %s", 21968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PrettyMethod(m).c_str(), function_name_); 22068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 22168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 22268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 22368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (invoke != kVirtual) { 22468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Class* c = soa.Decode<mirror::Class*>(jc); 22568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!m->GetDeclaringClass()->IsAssignableFrom(c)) { 22668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual", 22768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PrettyMethod(m).c_str(), PrettyClass(c).c_str()); 22868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 22968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 23068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 23168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (invoke != kStatic) { 23268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Object* o = soa.Decode<mirror::Object*>(jobj); 233a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier if (o == nullptr) { 234a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier AbortF("can't call %s on null object", PrettyMethod(m).c_str()); 235a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier return false; 236a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier } else if (!o->InstanceOf(m->GetDeclaringClass())) { 23768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str()); 23868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 239a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 240a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 24168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 242a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 243a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 244a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 245a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Verify that this static field ID is valid for this class. 246a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 247a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Assumes "java_class" has already been validated. 248a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 24968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid) 250b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 25168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Class* c = soa.Decode<mirror::Class*>(java_class); 25268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::ArtField* f = CheckFieldID(soa, fid); 253ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (f == nullptr) { 25468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 25532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 256a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (f->GetDeclaringClass() != c) { 25768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("static jfieldID %p not valid for class %s", fid, PrettyClass(c).c_str()); 25868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 259a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 26068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 261a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 262a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 263a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 264e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes * Verify that "mid" is appropriate for "java_class". 265a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 266a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * A mismatch isn't dangerous, because the jmethodID defines the class. In 267e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes * fact, java_class is unused in the implementation. It's best if we don't 268a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * allow bad code in the system though. 269a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 270e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes * Instances of "java_class" must be instances of the method's declaring class. 271a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 27268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid) 273b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 27468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::ArtMethod* m = CheckMethodID(soa, mid); 275ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (m == nullptr) { 27668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 27732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 27868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Class* c = soa.Decode<mirror::Class*>(java_class); 27967fe2b41a6afccf6ab1a58879eae3e0e8f3d6c7aBrian Carlstrom if (!m->GetDeclaringClass()->IsAssignableFrom(c)) { 28068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("can't call static %s on class %s", PrettyMethod(m).c_str(), PrettyClass(c).c_str()); 28168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 282a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 28368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 284a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 285a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 286a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 287a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Verify that "mid" is appropriate for "jobj". 288a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 289a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Make sure the object is an instance of the method's declaring class. 290a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * (Note the mid might point to a declaration in an interface; this 291a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * will be handled automatically by the instanceof check.) 292a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 29368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid) 294b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 29568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::ArtMethod* m = CheckMethodID(soa, mid); 296ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (m == nullptr) { 29768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 29832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 29968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Object* o = soa.Decode<mirror::Object*>(java_object); 300a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier if (o == nullptr) { 301a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier AbortF("can't call %s on null object", PrettyMethod(m).c_str()); 302a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier return false; 303a1e78fa763c9883af1c01a6c10fac5f5aa2f9659Mathieu Chartier } else if (!o->InstanceOf(m->GetDeclaringClass())) { 30468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str()); 30568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 306a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 30768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 308a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 309a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 310a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /** 311a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * The format string is a sequence of the following characters, 312a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * and must be followed by arguments of the corresponding types 313a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * in the same order. 314a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 315a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Java primitive types: 316a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * B - jbyte 317a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * C - jchar 318a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * D - jdouble 319a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * F - jfloat 320a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * I - jint 321a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * J - jlong 322a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * S - jshort 323a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Z - jboolean (shown as true and false) 324a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * V - void 325a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 326a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Java reference types: 327a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * L - jobject 328a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * a - jarray 329a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * c - jclass 330a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * s - jstring 331a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 332a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * JNI types: 333a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * b - jboolean (shown as JNI_TRUE and JNI_FALSE) 334a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * f - jfieldID 335a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * m - jmethodID 336a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * p - void* 337a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * r - jint (for release mode arguments) 33878090d119d5e23ff35ecddac1f4a98e4c050bb07Elliott Hughes * u - const char* (Modified UTF-8) 339a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * z - jsize (for lengths; use i if negative values are okay) 340a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * v - JavaVM* 341a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * E - JNIEnv* 342a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * . - no argument; just print "..." (used for varargs JNI calls) 343a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 344a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable. 345a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 34668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args) 34768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 348ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::ArtMethod* traceMethod = nullptr; 34968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (has_method_ && soa.Vm()->IsTracingEnabled()) { 350a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // We need to guard some of the invocation interface's calls: a bad caller might 351a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // use DetachCurrentThread or GetEnv on a thread that's not yet attached. 352a09576416788b916095739e43a16917e7948f3a4Elliott Hughes Thread* self = Thread::Current(); 353ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) { 354ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers traceMethod = self->GetCurrentMethod(nullptr); 355a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 356a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 357a09576416788b916095739e43a16917e7948f3a4Elliott Hughes 358ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (((flags_ & kFlag_ForceTrace) != 0) || 35968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) { 360a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes std::string msg; 36168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers for (size_t i = 0; fmt[i] != '\0'; ++i) { 36268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg); 36368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (fmt[i + 1] != '\0') { 36468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(&msg, ", "); 36568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 36668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 36768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 36868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if ((flags_ & kFlag_ForceTrace) != 0) { 36968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")"; 37068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else if (entry) { 37168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (has_method_) { 37268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers std::string methodName(PrettyMethod(traceMethod, false)); 37368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")"; 37468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers indent_ = methodName.size() + 1; 375a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 37668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")"; 37768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers indent_ = 0; 37868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 37968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 38068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str()); 38168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 38268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 38368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 38468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // We always do the thorough checks on entry, and never on exit... 38568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (entry) { 38668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers for (size_t i = 0; fmt[i] != '\0'; ++i) { 38768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) { 38868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 389a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 39068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 39168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 39268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 39368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 39468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 39568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) { 39668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool should_trace = (flags_ & kFlag_ForceTrace) != 0; 39768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!should_trace && vm->IsTracingEnabled()) { 39868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // We need to guard some of the invocation interface's calls: a bad caller might 39968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // use DetachCurrentThread or GetEnv on a thread that's not yet attached. 40068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers Thread* self = Thread::Current(); 40168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) { 40268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(self); 40368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::ArtMethod* traceMethod = self->GetCurrentMethod(nullptr); 40468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod)); 40568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 40668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 40768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (should_trace) { 40868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers std::string msg; 40968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers for (size_t i = 0; fmt[i] != '\0'; ++i) { 41068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers TraceNonHeapValue(fmt[i], args[i], &msg); 41168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (fmt[i + 1] != '\0') { 412a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, ", "); 413a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 414a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 415a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 416485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes if ((flags_ & kFlag_ForceTrace) != 0) { 417485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")"; 418485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes } else if (entry) { 41932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes if (has_method_) { 42068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers Thread* self = Thread::Current(); 42168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(self); 42268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::ArtMethod* traceMethod = self->GetCurrentMethod(nullptr); 423a09576416788b916095739e43a16917e7948f3a4Elliott Hughes std::string methodName(PrettyMethod(traceMethod, false)); 42432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")"; 42532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes indent_ = methodName.size() + 1; 426a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 42732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")"; 42832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes indent_ = 0; 429a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 430a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 43132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str()); 432a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 433a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 434a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 435a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // We always do the thorough checks on entry, and never on exit... 436a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (entry) { 43768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers for (size_t i = 0; fmt[i] != '\0'; ++i) { 43868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!CheckNonHeapValue(fmt[i], args[i])) { 43968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 440a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 441a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 442a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 44368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 44468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 44568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 44668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod) 44768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 44868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Object* method = soa.Decode<mirror::Object*>(jmethod); 44968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (method == nullptr) { 45068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("expected non-null method"); 45168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 45268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 45368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Class* c = method->GetClass(); 45468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Method) != c && 45568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Constructor) != c) { 45668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("expected java.lang.reflect.Method or " 45768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers "java.lang.reflect.Constructor but got object of type %s: %p", 45868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PrettyTypeOf(method).c_str(), jmethod); 45968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 46068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 46168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 46268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 46368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 46468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckConstructor(ScopedObjectAccess& soa, jmethodID mid) 46568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 46668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::ArtMethod* method = soa.DecodeMethod(mid); 46768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (method == nullptr) { 46868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("expected non-null constructor"); 46968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 47068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 47168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!method->IsConstructor() || method->IsStatic()) { 47268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("expected a constructor but %s: %p", PrettyTypeOf(method).c_str(), mid); 47368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 47468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 47568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 47668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 47768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 47868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield) 47968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 48068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Object* field = soa.Decode<mirror::Object*>(jfield); 48168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (field == nullptr) { 48268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("expected non-null java.lang.reflect.Field"); 48368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 48468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 48568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Class* c = field->GetClass(); 48668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Field) != c) { 48768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("expected java.lang.reflect.Field but got object of type %s: %p", 48868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PrettyTypeOf(field).c_str(), jfield); 48968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 49068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 49168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 49268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 49368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 49468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj) 49568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 49668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Object* obj = soa.Decode<mirror::Object*>(jobj); 49768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!obj->GetClass()->IsThrowableClass()) { 49868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("expected java.lang.Throwable but got object of type " 49968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers "%s: %p", PrettyTypeOf(obj).c_str(), obj); 50068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 50168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 50268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 50368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 50468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 50568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc) 50668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 50768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Class* c = soa.Decode<mirror::Class*>(jc); 50868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!c->IsThrowableClass()) { 50968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("expected java.lang.Throwable class but got object of " 51068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers "type %s: %p", PrettyDescriptor(c).c_str(), c); 51168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 51268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 51368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 51468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 51568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 5166a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) { 51768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers IndirectRefKind found_kind; 51868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (expected_kind == kLocal) { 51968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers found_kind = GetIndirectRefKind(obj); 52068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) { 52168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers found_kind = kLocal; 52268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 52368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 52468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers found_kind = GetIndirectRefKind(obj); 52568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 52668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (obj != nullptr && found_kind != expected_kind) { 52768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("expected reference of kind %s but found %s: %p", 52868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ToStr<IndirectRefKind>(expected_kind).c_str(), 52968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ToStr<IndirectRefKind>(GetIndirectRefKind(obj)).c_str(), 53068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers obj); 53168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 53268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 53368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 53468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 53568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 53668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc) 53768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 53868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Class* c = soa.Decode<mirror::Class*>(jc); 53968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!c->IsInstantiableNonArray()) { 54068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("can't make objects of type %s: %p", PrettyDescriptor(c).c_str(), c); 54168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 54268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 54368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 54468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 54568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 54668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type) 54768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 54868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!CheckArray(soa, array)) { 54968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 55068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 55168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Array* a = soa.Decode<mirror::Array*>(array); 55268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) { 55368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("incompatible array type %s expected %s[]: %p", 55468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PrettyDescriptor(a->GetClass()).c_str(), PrettyDescriptor(type).c_str(), array); 55568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 55668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 55768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 55868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 55968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 56068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static, 56168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers Primitive::Type type) 56268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 56368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) { 56468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 56568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 56668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) { 56768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 56868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 56968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::ArtField* field = soa.DecodeField(fid); 57068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers DCHECK(field != nullptr); // Already checked by Check. 57168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static != field->IsStatic()) { 57268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("attempt to access %s field %s: %p", 57368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers field->IsStatic() ? "static" : "non-static", PrettyField(field).c_str(), fid); 57468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 57568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 57668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (type != field->GetTypeAsPrimitiveType()) { 57768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("attempt to access field %s of type %s with the wrong type %s: %p", 57868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PrettyField(field).c_str(), PrettyDescriptor(field->GetTypeDescriptor()).c_str(), 57968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PrettyDescriptor(type).c_str(), fid); 58068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 58168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 58268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 58368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Object* o = soa.Decode<mirror::Object*>(obj); 58468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (o == nullptr || !o->IsClass()) { 58568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("attempt to access static field %s with a class argument of type %s: %p", 58668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid); 58768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 58868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 58968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Class* c = o->AsClass(); 59068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (field->GetDeclaringClass() != c) { 59168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("attempt to access static field %s with an incompatible class argument of %s: %p", 59268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PrettyField(field).c_str(), PrettyDescriptor(c).c_str(), fid); 59368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 59468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 59568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 59668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Object* o = soa.Decode<mirror::Object*>(obj); 59768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) { 59868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("attempt to access field %s from an object argument of type %s: %p", 59968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid); 60068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 60168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 60268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 60368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 604a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 605a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 60668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers private: 607a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes enum InstanceKind { 608a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes kClass, 6090f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes kDirectByteBuffer, 6100f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes kObject, 6110f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes kString, 6120f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes kThrowable, 613a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes }; 614a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes 615a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes /* 616a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes * Verify that "jobj" is a valid non-NULL object reference, and points to 617a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes * an instance of expectedClass. 618a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes * 619a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes * Because we're looking at an object on the GC heap, we have to switch 620a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes * to "running" mode before doing the checks. 621a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes */ 62268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok) 623b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 624ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const char* what = nullptr; 625a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes switch (kind) { 626a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kClass: 627a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes what = "jclass"; 628a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 629a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kDirectByteBuffer: 630a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes what = "direct ByteBuffer"; 631a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 632a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kObject: 633a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes what = "jobject"; 634a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 635a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kString: 636a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes what = "jstring"; 637a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 638a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kThrowable: 639a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes what = "jthrowable"; 640a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 641a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes default: 6427b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes LOG(FATAL) << "Unknown kind " << static_cast<int>(kind); 643a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes } 644a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes 645ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (java_object == nullptr) { 64668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (null_ok) { 64768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 64868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 64968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("%s received NULL %s", function_name_, what); 65068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 65168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 652a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes } 653a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes 65468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Object* obj = soa.Decode<mirror::Object*>(java_object); 655c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (obj == nullptr) { 656c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers // Either java_object is invalid or is a cleared weak. 657c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers IndirectRef ref = reinterpret_cast<IndirectRef>(java_object); 658c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers bool okay; 659c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (GetIndirectRefKind(ref) != kWeakGlobal) { 660c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers okay = false; 661c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers } else { 662c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref); 663c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers okay = Runtime::Current()->IsClearedJniWeakGlobal(obj); 664c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers } 665c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (!okay) { 666c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers AbortF("%s is an invalid %s: %p (%p)", 667c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), 668c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers java_object, obj); 669c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return false; 670c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers } 671c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers } 672c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers 673590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) { 6744c13a3ff475f206c4d0a86ee2595c45392fd942fMathieu Chartier Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR)); 67568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("%s is an invalid %s: %p (%p)", 67668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), 67768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers java_object, obj); 678a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes return false; 679a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes } 680a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes 681a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes bool okay = true; 682a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes switch (kind) { 683a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kClass: 684a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes okay = obj->IsClass(); 685a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 686a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kDirectByteBuffer: 687a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes UNIMPLEMENTED(FATAL); 688a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 689a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kString: 690a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes okay = obj->GetClass()->IsStringClass(); 691a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 692a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kThrowable: 693a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes okay = obj->GetClass()->IsThrowableClass(); 694a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 695a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kObject: 696a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 697a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes } 698a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes if (!okay) { 69968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("%s has wrong type: %s", what, PrettyTypeOf(obj).c_str()); 700a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes return false; 701a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes } 702a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes 703a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes return true; 704a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes } 705a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes 706a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 70768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Verify that the "mode" argument passed to a primitive array Release 70868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * function is one of the valid values. 709a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 71068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckReleaseMode(jint mode) { 71168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) { 71268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("unknown value for release mode: %d", mode); 71368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 714a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 71568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 716a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 717a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 71868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg) 71968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 72068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (fmt) { 72168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'a': // jarray 72268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CheckArray(soa, arg.a); 72368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'c': // jclass 72468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CheckInstance(soa, kClass, arg.c, false); 72568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'f': // jfieldID 72668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CheckFieldID(soa, arg.f) != nullptr; 72768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'm': // jmethodID 72868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CheckMethodID(soa, arg.m) != nullptr; 72968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'r': // release int 73068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CheckReleaseMode(arg.r); 73168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 's': // jstring 73268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CheckInstance(soa, kString, arg.s, false); 73368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 't': // jthrowable 73468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CheckInstance(soa, kThrowable, arg.t, false); 73568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'E': // JNIEnv* 73668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CheckThread(arg.E); 73768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'L': // jobject 73868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CheckInstance(soa, kObject, arg.L, true); 73968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 74068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CheckNonHeapValue(fmt, arg); 74168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 74268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 74368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 74468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckNonHeapValue(char fmt, JniValueType arg) { 74568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (fmt) { 74668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case '.': // ... 74768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'p': // TODO: pointer - null or readable? 74868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'v': // JavaVM* 74968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'B': // jbyte 75068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'C': // jchar 75168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'D': // jdouble 75268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'F': // jfloat 75368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'I': // jint 75468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'J': // jlong 75568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'S': // jshort 75668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; // Ignored. 75768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'b': // jboolean, why two? Fall-through. 75868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'Z': 75968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CheckBoolean(arg.Z); 76068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'u': // utf8 76168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if ((flags_ & kFlag_Release) != 0) { 76268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CheckNonNull(arg.u); 76368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 76468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool nullable = ((flags_ & kFlag_NullableUtf) != 0); 76568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CheckUtfString(arg.u, nullable); 76668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 76768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'w': // jobjectRefType 76868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (arg.w) { 76968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case JNIInvalidRefType: 77068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case JNILocalRefType: 77168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case JNIGlobalRefType: 77268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case JNIWeakGlobalRefType: 77368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 77468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 77568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("Unknown reference type"); 77668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 77768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 77868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 77968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'z': // jsize 78068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CheckLengthPositive(arg.z); 78168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 78268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("unknown format specifier: '%c'", fmt); 78368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 78432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 78568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 78632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 78732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes 78868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg, 78968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers std::string* msg) 79068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 79168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (fmt) { 79268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'L': // jobject fall-through. 79368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'a': // jarray fall-through. 79468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 's': // jstring fall-through. 79568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 't': // jthrowable fall-through. 79668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (arg.L == nullptr) { 79768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += "NULL"; 79868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 79968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, "%p", arg.L); 80068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 80168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 80268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'c': { // jclass 80368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jclass jc = arg.c; 80468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Class* c = soa.Decode<mirror::Class*>(jc); 80568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (c == nullptr) { 80668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += "NULL"; 807c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) { 80868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, "INVALID POINTER:%p", jc); 80968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else if (!c->IsClass()) { 81068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c); 81168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 81268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += PrettyClass(c); 81368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!entry) { 81468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, " (%p)", jc); 81568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 81668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 81768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 81868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 81968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'f': { // jfieldID 82068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jfieldID fid = arg.f; 82168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::ArtField* f = soa.DecodeField(fid); 82268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += PrettyField(f); 82368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!entry) { 82468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, " (%p)", fid); 82568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 82668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 82768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 82868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'm': { // jmethodID 82968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jmethodID mid = arg.m; 83068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::ArtMethod* m = soa.DecodeMethod(mid); 83168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += PrettyMethod(m); 83268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!entry) { 83368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, " (%p)", mid); 83468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 83568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 83668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 83768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 83868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers TraceNonHeapValue(fmt, arg, msg); 83968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 84032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 84132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 84232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes 84368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) { 84468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (fmt) { 84568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'B': // jbyte 84668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (arg.B >= 0 && arg.B < 10) { 84768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, "%d", arg.B); 84868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 84968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, "%#x (%d)", arg.B, arg.B); 85068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 85168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 85268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'C': // jchar 85368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (arg.C < 0x7f && arg.C >= ' ') { 85468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C); 85568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 85668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, "U+%x", arg.C); 85768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 85868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 85968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'F': // jfloat 86068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, "%g", arg.F); 86168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 86268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'D': // jdouble 86368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, "%g", arg.D); 86468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 86568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'S': // jshort 86668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, "%d", arg.S); 86768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 86868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'i': // jint - fall-through. 86968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'I': // jint 87068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, "%d", arg.I); 87168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 87268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'J': // jlong 87368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, "%" PRId64, arg.J); 87468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 87568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'Z': // jboolean 87668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'b': // jboolean (JNI-style) 87768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += arg.b == JNI_TRUE ? "true" : "false"; 87868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 87968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'V': // void 88068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers DCHECK(arg.V == nullptr); 88168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += "void"; 88268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 88368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'v': // JavaVM* 88468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, "(JavaVM*)%p", arg.v); 88568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 88668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'E': 88768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, "(JNIEnv*)%p", arg.E); 88868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 88968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'z': // non-negative jsize 89068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // You might expect jsize to be size_t, but it's not; it's the same as jint. 89168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // We only treat this specially so we can do the non-negative check. 89268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // TODO: maybe this wasn't worth it? 89368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, "%d", arg.z); 89468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 89568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'p': // void* ("pointer") 89668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (arg.p == nullptr) { 89768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += "NULL"; 89868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 89968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, "(void*) %p", arg.p); 90068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 90168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 90268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'r': { // jint (release mode) 90368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jint releaseMode = arg.r; 90468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (releaseMode == 0) { 90568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += "0"; 90668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else if (releaseMode == JNI_ABORT) { 90768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += "JNI_ABORT"; 90868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else if (releaseMode == JNI_COMMIT) { 90968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += "JNI_COMMIT"; 91068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 91168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, "invalid release mode %d", releaseMode); 91268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 91368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 91468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 91568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'u': // const char* (Modified UTF-8) 91668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (arg.u == nullptr) { 91768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += "NULL"; 91868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 91968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers StringAppendF(msg, "\"%s\"", arg.u); 92068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 92168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 92268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case 'w': // jobjectRefType 92368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (arg.w) { 92468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case JNIInvalidRefType: 92568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += "invalid reference type"; 92668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 92768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case JNILocalRefType: 92868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += "local ref type"; 92968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 93068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case JNIGlobalRefType: 93168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += "global ref type"; 93268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 93368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case JNIWeakGlobalRefType: 93468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += "weak global ref type"; 93568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 93668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 93768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += "unknown ref type"; 93868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 93968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 94068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 94168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case '.': 94268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *msg += "..."; 94368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 94468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 94568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'"; 94668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 94768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 948a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 94968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Verify that "array" is non-NULL and points to an Array object. 950a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 95168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Since we're dealing with objects, switch to "running" mode. 952a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 95368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckArray(ScopedObjectAccess& soa, jarray java_array) 954b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 95568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (UNLIKELY(java_array == nullptr)) { 95668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("jarray was NULL"); 95768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 958a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 959a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 96068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Array* a = soa.Decode<mirror::Array*>(java_array); 96168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a))) { 9624c13a3ff475f206c4d0a86ee2595c45392fd942fMathieu Chartier Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR)); 96368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("jarray is an invalid %s: %p (%p)", 96468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(), 96568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers java_array, a); 96668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 96768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else if (!a->IsArrayInstance()) { 96868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("jarray argument has non-array type: %s", PrettyTypeOf(a).c_str()); 96968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 970a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 97168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 972a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 973a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 97468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckBoolean(jboolean z) { 97568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (z != JNI_TRUE && z != JNI_FALSE) { 97668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("unexpected jboolean value: %d", z); 97768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 97868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 97968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 98068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 98168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 98268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckLengthPositive(jsize length) { 98368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (length < 0) { 98468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("negative jsize: %d", length); 98568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 98668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 98768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 98868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 98968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 99068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::ArtField* CheckFieldID(ScopedObjectAccess& soa, jfieldID fid) 99168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 99268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (fid == nullptr) { 99368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("jfieldID was NULL"); 99468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 99568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 99668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::ArtField* f = soa.DecodeField(fid); 99768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f) || !f->IsArtField()) { 99868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR)); 99968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("invalid jfieldID: %p", fid); 100068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 100168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 100268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return f; 100368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 100468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 100568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::ArtMethod* CheckMethodID(ScopedObjectAccess& soa, jmethodID mid) 100668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 100768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (mid == nullptr) { 100868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("jmethodID was NULL"); 100968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 101068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 101168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::ArtMethod* m = soa.DecodeMethod(mid); 101268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m) || !m->IsArtMethod()) { 101368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR)); 101468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("invalid jmethodID: %p", mid); 101568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 1016a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 101768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return m; 1018a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1019a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 102068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckThread(JNIEnv* env) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 1021a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes Thread* self = Thread::Current(); 1022ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (self == nullptr) { 102368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid()); 102468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 1025a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1026a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1027a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // Get the *correct* JNIEnv by going through our TLS pointer. 1028a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes JNIEnvExt* threadEnv = self->GetJniEnv(); 1029a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 10303f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Verify that the current thread is (a) attached and (b) associated with 10313f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // this particular instance of JNIEnv. 103268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (env != threadEnv) { 103368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("thread %s using JNIEnv* from thread %s", 103468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ToStr<Thread>(*self).c_str(), ToStr<Thread>(*self).c_str()); 103568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 1036a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1037a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 10383f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Verify that, if this thread previously made a critical "get" call, we 10393f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // do the corresponding "release" call before we try anything else. 104068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (flags_ & kFlag_CritMask) { 1041a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case kFlag_CritOkay: // okay to call this method 1042a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes break; 1043a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case kFlag_CritBad: // not okay to call 1044a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (threadEnv->critical) { 104568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("thread %s using JNI after critical get", 104668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ToStr<Thread>(*self).c_str()); 104768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 1048a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1049a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes break; 1050a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case kFlag_CritGet: // this is a "get" call 10513f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Don't check here; we allow nested gets. 1052a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes threadEnv->critical++; 1053a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes break; 10547934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom case kFlag_CritRelease: // this is a "release" call 1055a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes threadEnv->critical--; 1056a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (threadEnv->critical < 0) { 105768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("thread %s called too many critical releases", 105868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ToStr<Thread>(*self).c_str()); 105968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 1060a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1061a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes break; 1062a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes default: 106368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Bad flags (internal error): " << flags_; 1064a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1065a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 10663f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Verify that, if an exception has been raised, the native code doesn't 10673f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // make any JNI calls other than the Exception* methods. 106868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) { 106962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowLocation throw_location; 107062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers mirror::Throwable* exception = self->GetException(&throw_location); 107162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers std::string type(PrettyTypeOf(exception)); 107268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("JNI %s called with pending exception '%s' thrown in %s", 107368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers function_name_, type.c_str(), throw_location.Dump().c_str()); 107468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 1075a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 107668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 1077a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1078a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 10793f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Verifies that "bytes" points to valid Modified UTF-8 data. 108068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckUtfString(const char* bytes, bool nullable) { 1081ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (bytes == nullptr) { 1082a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (!nullable) { 108368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("non-nullable const char* was NULL"); 108468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 1085a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 108668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 1087a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1088a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1089ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const char* errorKind = nullptr; 109032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes uint8_t utf8 = CheckUtfBytes(bytes, &errorKind); 1091ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (errorKind != nullptr) { 109268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n" 109368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers " string: '%s'", errorKind, utf8, bytes); 109468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 1095a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 109668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 1097a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1098a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 109932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes static uint8_t CheckUtfBytes(const char* bytes, const char** errorKind) { 1100a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes while (*bytes != '\0') { 1101a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes uint8_t utf8 = *(bytes++); 1102a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // Switch on the high four bits. 1103a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes switch (utf8 >> 4) { 1104a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x00: 1105a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x01: 1106a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x02: 1107a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x03: 1108a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x04: 1109a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x05: 1110a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x06: 1111a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x07: 1112a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // Bit pattern 0xxx. No need for any extra bytes. 1113a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes break; 1114a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x08: 1115a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x09: 1116a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x0a: 1117a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x0b: 1118a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x0f: 1119a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 1120a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Bit pattern 10xx or 1111, which are illegal start bytes. 1121a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Note: 1111 is valid for normal UTF-8, but not the 112278090d119d5e23ff35ecddac1f4a98e4c050bb07Elliott Hughes * Modified UTF-8 used here. 1123a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 1124a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *errorKind = "start"; 1125a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return utf8; 1126a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x0e: 1127a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // Bit pattern 1110, so there are two additional bytes. 1128a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes utf8 = *(bytes++); 1129a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if ((utf8 & 0xc0) != 0x80) { 1130a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *errorKind = "continuation"; 1131a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return utf8; 1132a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1133fc787ecd91127b2c8458afd94e5148e2ae51a1f5Ian Rogers FALLTHROUGH_INTENDED; // Fall-through to take care of the final byte. 1134a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x0c: 1135a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x0d: 1136a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // Bit pattern 110x, so there is one additional byte. 1137a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes utf8 = *(bytes++); 1138a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if ((utf8 & 0xc0) != 0x80) { 1139a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *errorKind = "continuation"; 1140a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return utf8; 1141a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1142a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes break; 1143a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1144a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1145a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return 0; 1146a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1147a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 114868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) { 114968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_list args; 115068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_start(args, fmt); 115168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args); 115268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_end(args); 115368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 115468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 115568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // The name of the JNI function being checked. 115668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const char* const function_name_; 115768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 115868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const int flags_; 115992cb498ffd2185fc8f8da7cd25fe485d0e7e3355Elliott Hughes int indent_; 1160a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 116168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const bool has_method_; 116268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 1163a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes DISALLOW_COPY_AND_ASSIGN(ScopedCheck); 1164a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}; 1165a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1166a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/* 1167a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * =========================================================================== 1168a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Guarded arrays 1169a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * =========================================================================== 1170a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 1171a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1172a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/* this gets tucked in at the start of the buffer; struct size must be even */ 117368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogersclass GuardedCopy { 117468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers public: 1175a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 1176a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Create an over-sized buffer to hold the contents of "buf". Copy it in, 1177a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * filling in the area around it with guard data. 1178a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 117968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void* Create(const void* original_buf, size_t len, bool mod_okay) { 118068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const size_t new_len = LengthIncludingRedZones(len); 118168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers uint8_t* const new_buf = DebugAlloc(new_len); 1182a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 118368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // If modification is not expected, grab a checksum. 118468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers uLong adler = 0; 118568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!mod_okay) { 118668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len); 118768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 118868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 118968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler); 119068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 119168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Fill begin region with canary pattern. 119268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy); 119368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) { 119468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const_cast<char*>(copy->StartRedZone())[i] = kCanary[j]; 119568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (kCanary[j] == '\0') { 119668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers j = 0; 119768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 1198a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1199a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 12003f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Copy the data in; note "len" could be zero. 120168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len); 1202a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 120368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Fill end region with canary pattern. 120468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) { 120568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const_cast<char*>(copy->EndRedZone())[i] = kCanary[j]; 120668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (kCanary[j] == '\0') { 120768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers j = 0; 120868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 120968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 121068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 121168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return const_cast<uint8_t*>(copy->BufferWithinRedZones()); 121268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 121368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 121468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers /* 121568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Create a guarded copy of a primitive array. Modifications to the copied 121668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * data are allowed. Returns a pointer to the copied data. 121768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers */ 121868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy) { 121968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 122068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 122168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Array* a = soa.Decode<mirror::Array*>(java_array); 122268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers size_t component_size = a->GetClass()->GetComponentSize(); 122368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers size_t byte_count = a->GetLength() * component_size; 122468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers void* result = Create(a->GetRawData(component_size, 0), byte_count, true); 122568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_copy != nullptr) { 122668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *is_copy = JNI_TRUE; 1227a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 122868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result; 122968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 1230a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 123168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers /* 123268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * Perform the array "release" operation, which may or may not copy data 123368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers * back into the managed heap, and may or may not release the underlying storage. 123468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers */ 123568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env, jarray java_array, 123668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers void* embedded_buf, int mode) { 123768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 123868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers mirror::Array* a = soa.Decode<mirror::Array*>(java_array); 1239a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 124068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!GuardedCopy::Check(function_name, embedded_buf, true)) { 124168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 124268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 124368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (mode != JNI_ABORT) { 124468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers size_t len = FromEmbedded(embedded_buf)->original_length_; 124568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers memcpy(a->GetRawData(a->GetClass()->GetComponentSize(), 0), embedded_buf, len); 124668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 124768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (mode != JNI_COMMIT) { 124868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return Destroy(embedded_buf); 124968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 125068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return embedded_buf; 1251a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1252a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 125368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 1254a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 1255a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Free up the guard buffer, scrub it, and return the original pointer. 1256a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 125768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void* Destroy(void* embedded_buf) { 125868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers GuardedCopy* copy = FromEmbedded(embedded_buf); 125968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers void* original_ptr = const_cast<void*>(copy->original_ptr_); 126068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers size_t len = LengthIncludingRedZones(copy->original_length_); 126168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers DebugFree(copy, len); 126232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes return original_ptr; 1263a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1264a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1265a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 1266a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Verify the guard area and, if "modOkay" is false, that the data itself 1267a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * has not been altered. 1268a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 1269a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * The caller has already checked that "dataBuf" is non-NULL. 1270a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 127168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) { 127268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const GuardedCopy* copy = FromEmbedded(embedded_buf); 127368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name); 127468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 127568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 127668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers private: 127768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers GuardedCopy(const void* original_buf, size_t len, uLong adler) : 127868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) { 127968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 128068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 128168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static uint8_t* DebugAlloc(size_t len) { 128268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); 128368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (result == MAP_FAILED) { 128468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed"; 128568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 128668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return reinterpret_cast<uint8_t*>(result); 128768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 128868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 128968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void DebugFree(void* buf, size_t len) { 129068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (munmap(buf, len) != 0) { 129168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed"; 129268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 129368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 129468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 129568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static size_t LengthIncludingRedZones(size_t len) { 129668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return len + kRedZoneSize; 129768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 129868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 129968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Get the GuardedCopy from the interior pointer. 130068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static GuardedCopy* FromEmbedded(void* embedded_buf) { 130168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return reinterpret_cast<GuardedCopy*>( 130268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2)); 130368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 130468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 130568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static const GuardedCopy* FromEmbedded(const void* embedded_buf) { 130668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return reinterpret_cast<const GuardedCopy*>( 130768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2)); 130868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 130968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 131068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void AbortF(const char* jni_function_name, const char* fmt, ...) { 131168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_list args; 131268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_start(args, fmt); 131368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args); 131468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_end(args); 131568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 131668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 131768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckHeader(const char* function_name, bool mod_okay) const { 1318a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static const uint32_t kMagicCmp = kGuardMagic; 1319a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 13203f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Before we do anything with "pExtra", check the magic number. We 13213f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // do the check with memcmp rather than "==" in case the pointer is 13223f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // unaligned. If it points to completely bogus memory we're going 13233f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // to crash, but there's no easy way around that. 132468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) { 1325a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes uint8_t buf[4]; 132668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers memcpy(buf, &magic_, 4); 132768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF(function_name, 132868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?", 132968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian. 133068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 1331a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1332a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 133368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we 133468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // told the client that we made a copy, there's no reason they can't alter the buffer. 133568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!mod_okay) { 133668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers uLong computed_adler = 133768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_); 133868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (computed_adler != adler_) { 133968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p", 134068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers computed_adler, adler_, this); 134168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 1342a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1343a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 134468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 134568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 1346a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 134768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool CheckRedZones(const char* function_name) const { 134868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Check the begin red zone. 134968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy); 135068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) { 135168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (UNLIKELY(StartRedZone()[i] != kCanary[j])) { 135268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i); 135368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 1354a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 135568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (kCanary[j] == '\0') { 135668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers j = 0; 1357a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1358a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1359a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 136068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Check end region. 136168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) { 136268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (UNLIKELY(EndRedZone()[i] != kCanary[j])) { 136368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers size_t offset_from_buffer_start = 136468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]); 136568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this, 136668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers offset_from_buffer_start); 136768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return false; 136868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 136968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (kCanary[j] == '\0') { 137068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers j = 0; 1371a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1372a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 137368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return true; 1374a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1375a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 137668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Location that canary value will be written before the guarded region. 137768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const char* StartRedZone() const { 137868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const uint8_t* buf = reinterpret_cast<const uint8_t*>(this); 137968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy)); 1380a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1381a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 138268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Return the interior embedded buffer. 138368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const uint8_t* BufferWithinRedZones() const { 138468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2); 138568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return embedded_buf; 1386a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1387a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 138868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Location that canary value will be written after the guarded region. 138968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const char* EndRedZone() const { 139068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const uint8_t* buf = reinterpret_cast<const uint8_t*>(this); 139168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers size_t buf_len = LengthIncludingRedZones(original_length_); 139268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2))); 1393a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1394a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 139568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static constexpr size_t kRedZoneSize = 512; 139668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static constexpr size_t kEndCanaryLength = kRedZoneSize / 2; 1397a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 139868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Value written before and after the guarded array. 139968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static const char* const kCanary; 1400a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 140168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static constexpr uint32_t kGuardMagic = 0xffd5aa96; 1402a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 140368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const uint32_t magic_; 140468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const uLong adler_; 140568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const void* const original_ptr_; 140668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const size_t original_length_; 140768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers}; 140868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogersconst char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE"; 1409a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1410a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/* 1411a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * =========================================================================== 1412a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * JNI functions 1413a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * =========================================================================== 1414a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 1415a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1416a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesclass CheckJNI { 1417a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes public: 1418a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint GetVersion(JNIEnv* env) { 141968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 142068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 142168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[1] = {{.E = env }}; 142268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "E", args)) { 142368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 142468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.I = baseEnv(env)->GetVersion(env); 142568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "I", &result)) { 142668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.I; 142768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 142868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 142968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNI_ERR; 143068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 143168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 143268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jint GetJavaVM(JNIEnv *env, JavaVM **vm) { 143368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 143468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 143568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env }, {.p = vm}}; 143668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Ep", args)) { 143768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 143868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.i = baseEnv(env)->GetJavaVM(env, vm); 143968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "i", &result)) { 144068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.i; 144168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 144268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 144368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNI_ERR; 144468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 144568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 144668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) { 144768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 144868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 144968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}}; 145068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EcpI", args)) { 145168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 145268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods); 145368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "i", &result)) { 145468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.i; 145568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 145668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 145768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNI_ERR; 145868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 145968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 146068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jint UnregisterNatives(JNIEnv* env, jclass c) { 146168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 146268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 146368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env }, {.c = c}}; 146468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Ec", args)) { 146568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 146668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.i = baseEnv(env)->UnregisterNatives(env, c); 146768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "i", &result)) { 146868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.i; 146968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 147068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 147168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNI_ERR; 147268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 147368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 147468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) { 1475c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to 1476c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers // know the object is invalid. The spec says that passing invalid objects or even ones that 1477c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers // are deleted isn't supported. 147868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 147968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 1480c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JniValueType args[2] = {{.E = env }, {.L = obj}}; 1481c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (sc.Check(soa, true, "EL", args)) { 148268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 148368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.w = baseEnv(env)->GetObjectRefType(env, obj); 148468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "w", &result)) { 148568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.w; 148668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 148768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 148868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNIInvalidRefType; 1489a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1490a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 149168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf, 149268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jsize bufLen) { 149368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 149468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 149568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}}; 149668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) { 149768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 149868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen); 149968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "c", &result)) { 150068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.c; 150168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 150268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 150368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 1504a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1505a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1506a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jclass FindClass(JNIEnv* env, const char* name) { 150768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 150868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 150968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.u = name}}; 151068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) { 151168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 151268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.c = baseEnv(env)->FindClass(env, name); 151368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "c", &result)) { 151468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.c; 151568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 151668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 151768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 1518a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1519a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1520e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jclass GetSuperclass(JNIEnv* env, jclass c) { 152168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 152268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 152368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.c = c}}; 152468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Ec", args)) { 152568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 152668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.c = baseEnv(env)->GetSuperclass(env, c); 152768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "c", &result)) { 152868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.c; 152968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 153068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 153168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 1532a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1533a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1534e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) { 153568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 153668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 153768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}}; 153868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Ecc", args)) { 153968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 154068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2); 154168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "b", &result)) { 154268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.b; 154368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 154468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 154568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNI_FALSE; 1546a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1547a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1548a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) { 154968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 155068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 155168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.L = method}}; 155268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) { 155368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 155468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.m = baseEnv(env)->FromReflectedMethod(env, method); 155568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "m", &result)) { 155668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.m; 155768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 155868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 155968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 1560a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1561a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1562a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jfieldID FromReflectedField(JNIEnv* env, jobject field) { 156368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 156468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 156568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.L = field}}; 156668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) { 156768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 156868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.f = baseEnv(env)->FromReflectedField(env, field); 156968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "f", &result)) { 157068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.f; 157168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 157268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 157368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 1574a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1575a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1576a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) { 157768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 157868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 157968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}}; 158068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Ecmb", args)) { 158168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 158268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic); 158368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) { 158468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers DCHECK(sc.CheckReflectedMethod(soa, result.L)); 158568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.L; 158668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 158768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 158868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 1589a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1590a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1591a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) { 159268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 159368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 159468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}}; 159568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Ecfb", args)) { 159668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 159768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic); 159868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) { 159968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers DCHECK(sc.CheckReflectedField(soa, result.L)); 160068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.L; 160168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 160268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 160368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 1604a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1605a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1606a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint Throw(JNIEnv* env, jthrowable obj) { 160768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 160868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 160968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.t = obj}}; 161068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) { 161168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 161268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.i = baseEnv(env)->Throw(env, obj); 161368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "i", &result)) { 161468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.i; 161568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 161668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 161768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNI_ERR; 1618a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1619a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1620e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jint ThrowNew(JNIEnv* env, jclass c, const char* message) { 162168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 162268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__); 162368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[5] = {{.E = env}, {.c = c}, {.u = message}}; 162468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) { 162568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 162668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.i = baseEnv(env)->ThrowNew(env, c, message); 162768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "i", &result)) { 162868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.i; 162968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 163068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 163168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNI_ERR; 1632a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1633a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1634a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jthrowable ExceptionOccurred(JNIEnv* env) { 163568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 163668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 163768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[1] = {{.E = env}}; 163868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "E", args)) { 163968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 164068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.t = baseEnv(env)->ExceptionOccurred(env); 164168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "t", &result)) { 164268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.t; 164368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 164468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 164568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 1646a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1647a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1648a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void ExceptionDescribe(JNIEnv* env) { 164968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 165068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 165168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[1] = {{.E = env}}; 165268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "E", args)) { 165368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 165468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->ExceptionDescribe(env); 165568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.V = nullptr; 165668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.Check(soa, false, "V", &result); 165768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 1658a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1659a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1660a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void ExceptionClear(JNIEnv* env) { 166168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 166268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 166368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[1] = {{.E = env}}; 166468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "E", args)) { 166568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 166668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->ExceptionClear(env); 166768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.V = nullptr; 166868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.Check(soa, false, "V", &result); 166968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 167068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 167168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 167268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jboolean ExceptionCheck(JNIEnv* env) { 167368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 167468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__); 167568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[1] = {{.E = env}}; 167668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "E", args)) { 167768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 167868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.b = baseEnv(env)->ExceptionCheck(env); 167968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "b", &result)) { 168068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.b; 168168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 168268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 168368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNI_FALSE; 1684a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1685a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1686a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void FatalError(JNIEnv* env, const char* msg) { 1687c4378df76edd637273813fef4da7f01c4e637defElliott Hughes // The JNI specification doesn't say it's okay to call FatalError with a pending exception, 1688c4378df76edd637273813fef4da7f01c4e637defElliott Hughes // but you're about to abort anyway, and it's quite likely that you have a pending exception, 1689c4378df76edd637273813fef4da7f01c4e637defElliott Hughes // and it's not unimaginable that you don't know that you do. So we allow it. 169068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 169168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__); 169268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.u = msg}}; 169368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Eu", args)) { 169468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 169568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->FatalError(env, msg); 169668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Unreachable. 169768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.V = nullptr; 169868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.Check(soa, false, "V", &result); 169968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 1700a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1701a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1702a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint PushLocalFrame(JNIEnv* env, jint capacity) { 170368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 170468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 170568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.I = capacity}}; 170668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EI", args)) { 170768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 170868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.i = baseEnv(env)->PushLocalFrame(env, capacity); 170968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "i", &result)) { 171068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.i; 171168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 171268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 171368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNI_ERR; 1714a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1715a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1716a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jobject PopLocalFrame(JNIEnv* env, jobject res) { 171768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 171868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 171968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.L = res}}; 172068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EL", args)) { 172168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 172268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->PopLocalFrame(env, res); 172368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.Check(soa, false, "L", &result); 172468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.L; 172568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 172668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 1727a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1728a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1729a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jobject NewGlobalRef(JNIEnv* env, jobject obj) { 173068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return NewRef(__FUNCTION__, env, obj, kGlobal); 1731a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1732a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 173368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jobject NewLocalRef(JNIEnv* env, jobject obj) { 173468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return NewRef(__FUNCTION__, env, obj, kLocal); 1735a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1736a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 173768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) { 173868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return NewRef(__FUNCTION__, env, obj, kWeakGlobal); 1739a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1740a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 174168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void DeleteGlobalRef(JNIEnv* env, jobject obj) { 174268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers DeleteRef(__FUNCTION__, env, obj, kGlobal); 1743a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1744a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 174568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) { 174668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers DeleteRef(__FUNCTION__, env, obj, kWeakGlobal); 174768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 174868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 174968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void DeleteLocalRef(JNIEnv* env, jobject obj) { 175068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers DeleteRef(__FUNCTION__, env, obj, kLocal); 1751a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1752a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1753a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) { 175468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 175568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 175668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.I = capacity}}; 175768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EI", args)) { 175868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 175968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity); 176068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "i", &result)) { 176168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.i; 176268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 176368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 176468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNI_ERR; 1765a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1766a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1767a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) { 176868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 176968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 177068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}}; 177168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "ELL", args)) { 177268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 177368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.b = baseEnv(env)->IsSameObject(env, ref1, ref2); 177468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "b", &result)) { 177568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.b; 177668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 177768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 177868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNI_FALSE; 1779a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1780a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1781e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jobject AllocObject(JNIEnv* env, jclass c) { 178268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 178368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 178468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.c = c}}; 178568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) { 178668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 178768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->AllocObject(env, c); 178868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "L", &result)) { 178968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.L; 179068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 179168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 179268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 179368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 179468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 179568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { 179668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 179768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 179868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}}; 179968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) && 180068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.CheckConstructor(soa, mid)) { 180168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 180268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs); 180368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "L", &result)) { 180468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.L; 180568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 180668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 180768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 1808a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1809a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1810e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) { 1811a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_list args; 1812a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_start(args, mid); 181368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jobject result = NewObjectV(env, c, mid, args); 1814a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_end(args); 181568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result; 1816a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1817a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 181868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { 181968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 182068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 182168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}}; 182268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) && 182368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.CheckConstructor(soa, mid)) { 182468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 182568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs); 182668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "L", &result)) { 182768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.L; 182868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 182968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 183068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 1831a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1832a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1833a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jclass GetObjectClass(JNIEnv* env, jobject obj) { 183468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 183568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 183668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.L = obj}}; 183768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EL", args)) { 183868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 183968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.c = baseEnv(env)->GetObjectClass(env, obj); 184068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "c", &result)) { 184168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.c; 184268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 184368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 184468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 1845a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1846a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1847e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) { 184868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 184968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 185068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}}; 185168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "ELc", args)) { 185268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 185368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.b = baseEnv(env)->IsInstanceOf(env, obj, c); 185468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "b", &result)) { 185568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.b; 185668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 185768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 185868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNI_FALSE; 1859a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1860a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1861e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) { 186268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false); 1863a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1864a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 186568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) { 186668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true); 1867a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1868a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 186968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) { 187068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false); 1871a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1872a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1873e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) { 187468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true); 187568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 187668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 187768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \ 187868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \ 187968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \ 188068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } \ 188168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers \ 188268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \ 188368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \ 188468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } \ 188568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers \ 188668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \ 188768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType value; \ 188868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers value.shorty = v; \ 188968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers SetField(__FUNCTION__, env, c, fid, true, ptype, value); \ 189068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } \ 189168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers \ 189268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \ 189368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType value; \ 189468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers value.shorty = v; \ 189568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \ 189668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 189768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 189868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L) 189968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z) 190068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B) 190168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C) 190268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S) 190368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I) 190468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J) 190568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F) 190668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D) 190768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#undef FIELD_ACCESSORS 190868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 190968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { 191068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual); 191168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 191268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 191368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, 191468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jvalue* vargs) { 191568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect); 191668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 191768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 191868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { 191951be0a7158b62d6da6a3ccb6fce9f7f677ec3ce3Marcus Oakland CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic); 192068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 192168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 192268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { 192368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual); 192468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 192568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 192668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, 192768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_list vargs) { 192868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect); 192968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 193068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 193168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { 193268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic); 193368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 193468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 193568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { 193668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_list vargs; 193768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_start(vargs, mid); 193868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual); 193968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_end(vargs); 194068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 194168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 194268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) { 194368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_list vargs; 194468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_start(vargs, mid); 194568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect); 194668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_end(vargs); 194768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 194868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 194968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) { 195068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_list vargs; 195168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_start(vargs, mid); 195268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic); 195368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_end(vargs); 195468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 195568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 195668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#define CALL(rtype, name, ptype, shorty) \ 195768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \ 195868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \ 195968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } \ 196068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers \ 196168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \ 196268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jvalue* vargs) { \ 196368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \ 196468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } \ 196568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers \ 196668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \ 196768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \ 196868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } \ 196968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers \ 197068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \ 197168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \ 197268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } \ 197368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers \ 197468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \ 197568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_list vargs) { \ 197668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \ 197768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } \ 197868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers \ 197968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \ 198068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \ 198168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } \ 198268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers \ 198368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \ 198468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_list vargs; \ 198568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_start(vargs, mid); \ 198668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers rtype result = \ 198768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \ 198868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_end(vargs); \ 198968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result; \ 199068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } \ 199168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers \ 199268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \ 199368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ...) { \ 199468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_list vargs; \ 199568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_start(vargs, mid); \ 199668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers rtype result = \ 199768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \ 199868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_end(vargs); \ 199968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result; \ 200068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } \ 200168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers \ 200268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \ 200368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_list vargs; \ 200468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_start(vargs, mid); \ 200568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers rtype result = \ 200668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \ 200768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers va_end(vargs); \ 200868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result; \ 200968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 201068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 201168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CALL(jobject, Object, Primitive::kPrimNot, L) 201268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z) 201368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CALL(jbyte, Byte, Primitive::kPrimByte, B) 201468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CALL(jchar, Char, Primitive::kPrimChar, C) 201568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CALL(jshort, Short, Primitive::kPrimShort, S) 201668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CALL(jint, Int, Primitive::kPrimInt, I) 201768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CALL(jlong, Long, Primitive::kPrimLong, J) 201868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CALL(jfloat, Float, Primitive::kPrimFloat, F) 201968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CALL(jdouble, Double, Primitive::kPrimDouble, D) 202068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#undef CALL 202168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 202268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) { 202368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 202468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 202568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}}; 202668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Epz", args)) { 202768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 202868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.s = baseEnv(env)->NewString(env, unicode_chars, len); 202968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "s", &result)) { 203068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.s; 203168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 203268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 203368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 2034a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2035a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 203668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jstring NewStringUTF(JNIEnv* env, const char* chars) { 203768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 203868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__); 203968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.u = chars}}; 204068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Eu", args)) { 204168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 204268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // TODO: stale? show pointer and truncate string. 204368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.s = baseEnv(env)->NewStringUTF(env, chars); 204468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "s", &result)) { 204568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.s; 204668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 204768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 204868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 2049a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2050a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 205168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jsize GetStringLength(JNIEnv* env, jstring string) { 205268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 205368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 205468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.s = string}}; 205568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Es", args)) { 205668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 205768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.z = baseEnv(env)->GetStringLength(env, string); 205868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "z", &result)) { 205968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.z; 2060a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2061a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 206268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNI_ERR; 2063a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2064a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 206568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jsize GetStringUTFLength(JNIEnv* env, jstring string) { 206668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 206768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 206868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.s = string}}; 206968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Es", args)) { 207068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 207168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.z = baseEnv(env)->GetStringUTFLength(env, string); 207268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "z", &result)) { 207368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.z; 207468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 2075a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 207668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNI_ERR; 2077a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2078a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 207968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) { 208068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string, 208168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers is_copy, false, false)); 2082a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2083a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 208468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) { 208568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string, 208668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers is_copy, true, false)); 2087a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2088a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 208968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) { 209068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string, 209168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers is_copy, false, true)); 209268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 209368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 209468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) { 209568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false); 2096a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2097a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 2098a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) { 209968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false); 210068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 210168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 210268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) { 210368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true); 210468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 210568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 210668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) { 210768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 210868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 210968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}}; 211068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices 211168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // result in ArrayIndexOutOfBoundsExceptions in the base implementation. 211268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EsIIp", args)) { 211368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->GetStringRegion(env, string, start, len, buf); 211468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 211568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.V = nullptr; 211668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.Check(soa, false, "V", &result); 2117a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2118a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2119a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 212068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) { 212168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 212268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 212368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}}; 212468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices 212568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // result in ArrayIndexOutOfBoundsExceptions in the base implementation. 212668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EsIIp", args)) { 212768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf); 212868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 212968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.V = nullptr; 213068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.Check(soa, false, "V", &result); 213168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 2132a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2133a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 213468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jsize GetArrayLength(JNIEnv* env, jarray array) { 213568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 213668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 213768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.a = array}}; 213868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Ea", args)) { 213968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 214068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.z = baseEnv(env)->GetArrayLength(env, array); 214168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "z", &result)) { 214268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.z; 214368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 214468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 214568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNI_ERR; 214668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 214768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 214868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class, 214968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jobject initial_element) { 215068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 215168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 215268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[4] = 215368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}}; 215468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EzcL", args)) { 215568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 215668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Note: assignability tests of initial_element are done in the base implementation. 215768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element); 215868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "a", &result)) { 215968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return down_cast<jobjectArray>(result.a); 216068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 216168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 216268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 2163a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2164a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 2165a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) { 216668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 216768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 216868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}}; 216968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Eaz", args)) { 217068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 217168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->GetObjectArrayElement(env, array, index); 217268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "L", &result)) { 217368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.L; 217468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 217568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 217668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 2177a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2178a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 2179a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) { 218068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 218168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 218268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}}; 218368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in 218468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result 218568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // in ArrayStoreExceptions. 218668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EaIL", args)) { 218768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetObjectArrayElement(env, array, index, value); 218868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 218968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.V = nullptr; 219068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.Check(soa, false, "V", &result); 2191a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2192a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2193a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 219468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) { 219568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length, 219668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers Primitive::kPrimBoolean)); 2197a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2198a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 219968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jbyteArray NewByteArray(JNIEnv* env, jsize length) { 220068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length, 220168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers Primitive::kPrimByte)); 220268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 2203a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 220468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jcharArray NewCharArray(JNIEnv* env, jsize length) { 220568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length, 220668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers Primitive::kPrimChar)); 220768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 2208a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 220968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jshortArray NewShortArray(JNIEnv* env, jsize length) { 221068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length, 221168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers Primitive::kPrimShort)); 2212a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2213a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 221468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jintArray NewIntArray(JNIEnv* env, jsize length) { 221568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt)); 2216a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2217a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 221868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jlongArray NewLongArray(JNIEnv* env, jsize length) { 221968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length, 222068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers Primitive::kPrimLong)); 222168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 222268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 222368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jfloatArray NewFloatArray(JNIEnv* env, jsize length) { 222468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length, 222568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers Primitive::kPrimFloat)); 222668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 222768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 222868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) { 222968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length, 223068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers Primitive::kPrimDouble)); 223168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 223268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 223368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \ 223468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { \ 223568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return reinterpret_cast<ctype*>( \ 223668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \ 223768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } \ 223868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers \ 223968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, \ 224068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jint mode) { \ 224168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \ 224268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } \ 224368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers \ 224468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \ 224568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ctype* buf) { \ 224668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \ 224768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } \ 224868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers \ 224968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \ 225068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const ctype* buf) { \ 225168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \ 225268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 225368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 225468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean) 225568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte) 225668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar) 225768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort) 225868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt) 225968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong) 226068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat) 226168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble) 226268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#undef PRIMITIVE_ARRAY_FUNCTIONS 226368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 2264a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint MonitorEnter(JNIEnv* env, jobject obj) { 226568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 226668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 226768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.L = obj}}; 226868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EL", args)) { 226968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 227068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.i = baseEnv(env)->MonitorEnter(env, obj); 227168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "i", &result)) { 227268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.i; 227368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 2274a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes } 227568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNI_ERR; 2276a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2277a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 2278a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint MonitorExit(JNIEnv* env, jobject obj) { 227968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 228068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 228168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.L = obj}}; 228268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EL", args)) { 228368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 228468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.i = baseEnv(env)->MonitorExit(env, obj); 228568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "i", &result)) { 228668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.i; 228768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 2288a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes } 228968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNI_ERR; 2290a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2291a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 229268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) { 229368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 229468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_CritGet, __FUNCTION__); 229568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}}; 229668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Eap", args)) { 229768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 229868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.p = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy); 229968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (result.p != nullptr && soa.ForceCopy()) { 230068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.p = GuardedCopy::CreateGuardedPACopy(env, array, is_copy); 230168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 230268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "p", &result)) { 230368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return const_cast<void*>(result.p); 230468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 230568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 230668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 2307a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2308a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 230968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) { 231068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 231168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__); 231268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.CheckNonNull(carray); 231368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}}; 231468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Eapr", args)) { 231568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (soa.ForceCopy()) { 231668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode); 231768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 231868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode); 231968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 232068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.V = nullptr; 232168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.Check(soa, false, "V", &result); 232268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 2323a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2324a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 232568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) { 232668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 232768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 232868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}}; 232968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EpJ", args)) { 233068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 233168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Note: the validity of address and capacity are checked in the base implementation. 233268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity); 233368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "L", &result)) { 233468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.L; 233568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 233668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 233768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 2338a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2339a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 234068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) { 234168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 234268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 234368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.L = buf}}; 234468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EL", args)) { 234568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 234668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Note: this is implemented in the base environment by a GetLongField which will sanity 234768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // check the type of buf in GetLongField above. 234868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.p = baseEnv(env)->GetDirectBufferAddress(env, buf); 234968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "p", &result)) { 235068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return const_cast<void*>(result.p); 235168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 2352a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 235368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 2354a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2355a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 235668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) { 235768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 235868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, __FUNCTION__); 235968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.L = buf}}; 236068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EL", args)) { 236168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 236268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Note: this is implemented in the base environment by a GetIntField which will sanity 236368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // check the type of buf in GetIntField above. 236468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf); 236568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "J", &result)) { 236668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.J; 236768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 2368a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 236968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return JNI_ERR; 237068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 237168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 237268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers private: 237368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static JavaVMExt* GetJavaVMExt(JNIEnv* env) { 237468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return reinterpret_cast<JNIEnvExt*>(env)->vm; 2375a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2376a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 237768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static const JNINativeInterface* baseEnv(JNIEnv* env) { 237868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions; 237968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 238068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 238168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) { 238268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 238368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, function_name); 238468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.L = obj}}; 238568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EL", args)) { 238668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 238768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (kind) { 238868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kGlobal: 238968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->NewGlobalRef(env, obj); 239068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 239168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kLocal: 239268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->NewLocalRef(env, obj); 239368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 239468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kWeakGlobal: 239568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->NewWeakGlobalRef(env, obj); 239668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 239768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 239868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected reference kind: " << kind; 239968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 240068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "L", &result)) { 240168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE); 24026a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L)); 240368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.L; 2404a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2405a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 240668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 240768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 240868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 240968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) { 241068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 241168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_ExcepOkay, function_name); 241268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.L = obj}}; 241368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.Check(soa, true, "EL", args); 24146a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers if (sc.CheckReferenceKind(kind, soa.Self(), obj)) { 241568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 241668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (kind) { 241768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kGlobal: 241868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->DeleteGlobalRef(env, obj); 241968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 242068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kLocal: 242168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->DeleteLocalRef(env, obj); 242268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 242368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kWeakGlobal: 242468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->DeleteWeakGlobalRef(env, obj); 242568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 242668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 242768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected reference kind: " << kind; 242868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 242968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.V = nullptr; 243068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.Check(soa, false, "V", &result); 243168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 2432a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2433a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 243468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c, 243568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const char* name, const char* sig, bool is_static) { 243668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 243768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, function_name); 243868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}}; 243968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Ecuu", args)) { 244068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 244168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 244268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig); 244368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 244468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.m = baseEnv(env)->GetMethodID(env, c, name, sig); 244568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 244668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "m", &result)) { 244768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.m; 244868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 2449a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 245068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 2451a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2452a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 245368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c, 245468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const char* name, const char* sig, bool is_static) { 245568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 245668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, function_name); 245768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}}; 245868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Ecuu", args)) { 245968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 246068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 246168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig); 246268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 246368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.f = baseEnv(env)->GetFieldID(env, c, name, sig); 246468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 246568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "f", &result)) { 246668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.f; 246768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 246868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 246968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 247068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 247168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 247268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid, 247368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool is_static, Primitive::Type type) { 247468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 247568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, function_name); 247668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}}; 247768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 247868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) && 247968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.CheckFieldAccess(soa, obj, fid, is_static, type)) { 248068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const char* result_check = nullptr; 248168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (type) { 248268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimNot: 248368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 248468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid); 248568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 248668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->GetObjectField(env, obj, fid); 248768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 248868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "L"; 248968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 249068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimBoolean: 249168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 249268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid); 249368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 249468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.Z = baseEnv(env)->GetBooleanField(env, obj, fid); 249568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 249668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "Z"; 249768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 249868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimByte: 249968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 250068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid); 250168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 250268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.B = baseEnv(env)->GetByteField(env, obj, fid); 250368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 250468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "B"; 250568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 250668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimChar: 250768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 250868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid); 250968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 251068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.C = baseEnv(env)->GetCharField(env, obj, fid); 251168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 251268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "C"; 251368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 251468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimShort: 251568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 251668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid); 251768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 251868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.S = baseEnv(env)->GetShortField(env, obj, fid); 251968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 252068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "S"; 252168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 252268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimInt: 252368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 252468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid); 252568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 252668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.I = baseEnv(env)->GetIntField(env, obj, fid); 252768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 252868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "I"; 252968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 253068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimLong: 253168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 253268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid); 253368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 253468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.J = baseEnv(env)->GetLongField(env, obj, fid); 253568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 253668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "J"; 253768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 253868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimFloat: 253968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 254068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid); 254168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 254268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.F = baseEnv(env)->GetFloatField(env, obj, fid); 254368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 254468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "F"; 254568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 254668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimDouble: 254768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 254868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid); 254968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 255068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.D = baseEnv(env)->GetDoubleField(env, obj, fid); 255168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 255268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "D"; 255368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 255468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimVoid: 255568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected type: " << type; 255668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 255768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 255868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, result_check, &result)) { 255968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result; 256068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 256168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 256268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.J = 0; 256368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result; 2564a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2565a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 256668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid, 256768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool is_static, Primitive::Type type, JniValueType value) { 256868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 256968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, function_name); 257068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value}; 257168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers char sig[5] = { 'E', is_static ? 'c' : 'L', 'f', 257268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'}; 257368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, sig, args) && 257468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.CheckFieldAccess(soa, obj, fid, is_static, type)) { 257568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (type) { 257668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimNot: 257768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 257868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L); 257968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 258068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetObjectField(env, obj, fid, value.L); 258168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 258268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 258368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimBoolean: 258468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 258568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z); 258668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 258768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetBooleanField(env, obj, fid, value.Z); 258868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 258968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 259068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimByte: 259168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 259268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B); 259368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 259468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetByteField(env, obj, fid, value.B); 259568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 259668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 259768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimChar: 259868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 259968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C); 260068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 260168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetCharField(env, obj, fid, value.C); 260268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 260368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 260468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimShort: 260568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 260668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S); 260768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 260868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetShortField(env, obj, fid, value.S); 260968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 261068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 261168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimInt: 261268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 261368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I); 261468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 261568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetIntField(env, obj, fid, value.I); 261668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 261768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 261868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimLong: 261968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 262068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J); 262168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 262268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetLongField(env, obj, fid, value.J); 262368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 262468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 262568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimFloat: 262668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 262768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F); 262868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 262968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetFloatField(env, obj, fid, value.F); 263068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 263168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 263268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimDouble: 263368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_static) { 263468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D); 263568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 263668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetDoubleField(env, obj, fid, value.D); 263768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 263868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 263968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimVoid: 264068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected type: " << type; 264168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 264268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 264368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 264468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.V = nullptr; 264568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.Check(soa, false, "V", &result); 264668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 2647a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2648a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 264968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj, 265068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jclass c, jmethodID mid, InvokeType invoke) 265168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 265268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool checked; 265368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 265468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: { 265568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers DCHECK(c == nullptr); 265668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[3] = {{.E = env}, {.L = obj}, {.m = mid}}; 265768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers checked = sc.Check(soa, true, "ELm.", args); 265868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 265968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 266068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: { 266168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[4] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}}; 266268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers checked = sc.Check(soa, true, "ELcm.", args); 266368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 266468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 266568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: { 266668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers DCHECK(obj == nullptr); 266768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}}; 266868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers checked = sc.Check(soa, true, "Ecm.", args); 266968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 267068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 267168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 267268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected invoke: " << invoke; 267368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers checked = false; 267468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 267568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 267668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return checked; 267768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 267868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 267968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c, 268068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jmethodID mid, jvalue* vargs, Primitive::Type type, 268168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers InvokeType invoke) { 268268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 268368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, function_name); 268468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 268568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke) && 268668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) { 268768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const char* result_check; 268868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (type) { 268968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimNot: 269068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "L"; 269168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 269268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 269368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs); 269468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 269568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 269668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs); 269768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 269868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 269968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs); 270068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 270168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 270268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 270368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 270468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 270568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimBoolean: 270668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "Z"; 270768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 270868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 270968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs); 271068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 271168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 271268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs); 271368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 271468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 271568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs); 271668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 271768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 271868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 271968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 272068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 272168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimByte: 272268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "B"; 272368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 272468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 272568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs); 272668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 272768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 272868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs); 272968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 273068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 273168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs); 273268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 273368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 273468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 273568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 273668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 273768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimChar: 273868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "C"; 273968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 274068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 274168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs); 274268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 274368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 274468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs); 274568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 274668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 274768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs); 274868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 274968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 275068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 275168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 275268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 275368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimShort: 275468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "S"; 275568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 275668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 275768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs); 275868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 275968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 276068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs); 276168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 276268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 276368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs); 276468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 276568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 276668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 276768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 276868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 276968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimInt: 277068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "I"; 277168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 277268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 277368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs); 277468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 277568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 277668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs); 277768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 277868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 277968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs); 278068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 278168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 278268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 278368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 278468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 278568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimLong: 278668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "J"; 278768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 278868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 278968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs); 279068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 279168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 279268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs); 279368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 279468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 279568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs); 279668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 279768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 279868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 279968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 280068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 280168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimFloat: 280268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "F"; 280368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 280468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 280568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs); 280668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 280768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 280868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs); 280968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 281068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 281168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs); 281268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 281368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 281468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 281568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 281668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 281768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimDouble: 281868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "D"; 281968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 282068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 282168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs); 282268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 282368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 282468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs); 282568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 282668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 282768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs); 282868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 282968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 283068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 283168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 283268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 283368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimVoid: 283468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "V"; 283568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.V = nullptr; 283668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 283768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 283868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs); 283968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 284068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 284168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs); 284268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 284368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 284468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs); 284568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 284668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 284768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected invoke: " << invoke; 284868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 284968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 285068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 285168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected return type: " << type; 285268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = nullptr; 285368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 285468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, result_check, &result)) { 285568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result; 285668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 285768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 285868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.J = 0; 285968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result; 2860a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2861a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 286268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c, 286368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jmethodID mid, va_list vargs, Primitive::Type type, 286468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers InvokeType invoke) { 286568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 286668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, function_name); 286768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 286868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke) && 286968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) { 287068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const char* result_check; 287168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (type) { 287268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimNot: 287368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "L"; 287468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 287568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 287668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs); 287768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 287868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 287968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs); 288068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 288168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 288268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs); 288368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 288468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 288568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected invoke: " << invoke; 288668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 288768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 288868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimBoolean: 288968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "Z"; 289068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 289168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 289268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs); 289368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 289468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 289568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs); 289668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 289768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 289868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs); 289968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 290068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 290168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected invoke: " << invoke; 290268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 290368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 290468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimByte: 290568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "B"; 290668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 290768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 290868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs); 290968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 291068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 291168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs); 291268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 291368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 291468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs); 291568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 291668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 291768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected invoke: " << invoke; 291868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 291968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 292068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimChar: 292168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "C"; 292268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 292368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 292468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs); 292568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 292668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 292768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs); 292868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 292968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 293068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs); 293168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 293268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 293368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected invoke: " << invoke; 293468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 293568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 293668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimShort: 293768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "S"; 293868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 293968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 294068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs); 294168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 294268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 294368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs); 294468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 294568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 294668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs); 294768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 294868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 294968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected invoke: " << invoke; 295068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 295168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 295268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimInt: 295368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "I"; 295468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 295568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 295668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs); 295768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 295868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 295968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs); 296068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 296168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 296268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs); 296368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 296468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 296568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected invoke: " << invoke; 296668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 296768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 296868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimLong: 296968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "J"; 297068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 297168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 297268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs); 297368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 297468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 297568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs); 297668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 297768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 297868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs); 297968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 298068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 298168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected invoke: " << invoke; 298268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 298368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 298468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimFloat: 298568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "F"; 298668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 298768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 298868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs); 298968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 299068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 299168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs); 299268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 299368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 299468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs); 299568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 299668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 299768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected invoke: " << invoke; 299868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 299968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 300068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimDouble: 300168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "D"; 300268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 300368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 300468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs); 300568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 300668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 300768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs); 300868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 300968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 301068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs); 301168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 301268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 301368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected invoke: " << invoke; 301468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 301568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 301668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimVoid: 301768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = "V"; 301868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.V = nullptr; 301968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (invoke) { 302068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kVirtual: 302168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs); 302268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 302368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kDirect: 302468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs); 302568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 302668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case kStatic: 302768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs); 302868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 302968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 303068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected invoke: " << invoke; 303168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 303268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 303368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 303468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected return type: " << type; 303568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result_check = nullptr; 303668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 303768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, result_check, &result)) { 303868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result; 303968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 3040a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 304168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.J = 0; 304268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result; 3043a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 3044a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 304568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string, 304668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jboolean* is_copy, bool utf, bool critical) { 304768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 304868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers int flags = critical ? kFlag_CritGet : kFlag_CritOkay; 304968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(flags, function_name); 305068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}}; 305168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Esp", args)) { 305268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 305368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (utf) { 305468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CHECK(!critical); 305568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.u = baseEnv(env)->GetStringUTFChars(env, string, is_copy); 305668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 305768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (critical) { 305868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.p = baseEnv(env)->GetStringCritical(env, string, is_copy); 305968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 306068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.p = baseEnv(env)->GetStringChars(env, string, is_copy); 306168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 306268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 306368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // TODO: could we be smarter about not copying when local_is_copy? 306468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (result.p != nullptr && soa.ForceCopy()) { 306568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (utf) { 306668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers size_t length_in_bytes = strlen(result.u) + 1; 306768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.u = 306868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<const char*>(GuardedCopy::Create(result.u, length_in_bytes, false)); 306968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 307068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2; 307168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.p = 307268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<const jchar*>(GuardedCopy::Create(result.p, length_in_bytes, false)); 307368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 307468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_copy != nullptr) { 307568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *is_copy = JNI_TRUE; 307668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 307768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 307868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, utf ? "u" : "p", &result)) { 307968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return utf ? result.u : result.p; 308068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 308168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 308268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 3083a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 3084a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 308568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string, 308668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers const void* chars, bool utf, bool critical) { 308768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 308868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers int flags = kFlag_ExcepOkay | kFlag_Release; 308968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (critical) { 309068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers flags |= kFlag_CritRelease; 309168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 309268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(flags, function_name); 309368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.CheckNonNull(chars); 309468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false); 309568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (force_copy_ok && soa.ForceCopy()) { 309668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars))); 309768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 309868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (force_copy_ok) { 309968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}}; 310068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) { 310168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (utf) { 310268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers CHECK(!critical); 310368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars)); 310468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 310568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (critical) { 310668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars)); 310768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } else { 310868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars)); 310968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 311068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 311168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 311268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.Check(soa, false, "V", &result); 311368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 311468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 3115a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 3116a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 311768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length, 311868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers Primitive::Type type) { 311968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 31206a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers ScopedCheck sc(kFlag_Default, function_name); 312168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[2] = {{.E = env}, {.z = length}}; 312268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Ez", args)) { 312368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 312468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (type) { 312568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimBoolean: 312668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.a = baseEnv(env)->NewBooleanArray(env, length); 312768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 312868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimByte: 312968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.a = baseEnv(env)->NewByteArray(env, length); 313068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 313168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimChar: 313268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.a = baseEnv(env)->NewCharArray(env, length); 313368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 313468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimShort: 313568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.a = baseEnv(env)->NewShortArray(env, length); 313668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 313768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimInt: 313868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.a = baseEnv(env)->NewIntArray(env, length); 313968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 314068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimLong: 314168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.a = baseEnv(env)->NewLongArray(env, length); 314268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 314368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimFloat: 314468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.a = baseEnv(env)->NewFloatArray(env, length); 314568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 314668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimDouble: 314768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.a = baseEnv(env)->NewDoubleArray(env, length); 314868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 314968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 315068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected primitive type: " << type; 315168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 315268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "a", &result)) { 315368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.a; 315468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 315568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 315668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 315768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 315868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 315968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type, 316068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JNIEnv* env, jarray array, jboolean* is_copy) { 316168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 316268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, function_name); 316368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}}; 316468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) { 316568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 316668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (type) { 316768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimBoolean: 316868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.p = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array), 316968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers is_copy); 317068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 317168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimByte: 317268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.p = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), 317368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers is_copy); 317468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 317568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimChar: 317668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.p = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), 317768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers is_copy); 317868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 317968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimShort: 318068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.p = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), 318168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers is_copy); 318268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 318368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimInt: 318468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.p = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy); 318568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 318668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimLong: 318768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.p = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), 318868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers is_copy); 318968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 319068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimFloat: 319168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.p = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), 319268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers is_copy); 319368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 319468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimDouble: 319568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.p = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), 319668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers is_copy); 319768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 319868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 319968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected primitive type: " << type; 320068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 320168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (result.p != nullptr && soa.ForceCopy()) { 320268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.p = GuardedCopy::CreateGuardedPACopy(env, array, is_copy); 320368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (is_copy != nullptr) { 320468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers *is_copy = JNI_TRUE; 320568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 320668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 320768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, false, "p", &result)) { 320868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return const_cast<void*>(result.p); 320968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 321068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 321168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return nullptr; 321268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 321368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 321468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type, 321568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JNIEnv* env, jarray array, void* elems, jint mode) { 321668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 321768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_ExcepOkay, function_name); 321868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) { 321968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (soa.ForceCopy()) { 322068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode); 322168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 322268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (!soa.ForceCopy() || elems != nullptr) { 322368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}}; 322468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "Eapr", args)) { 322568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (type) { 322668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimBoolean: 322768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array), 322868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<jboolean*>(elems), mode); 322968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 323068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimByte: 323168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array), 323268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<jbyte*>(elems), mode); 323368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 323468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimChar: 323568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array), 323668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<jchar*>(elems), mode); 323768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 323868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimShort: 323968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array), 324068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<jshort*>(elems), mode); 324168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 324268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimInt: 324368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array), 324468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<jint*>(elems), mode); 324568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 324668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimLong: 324768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array), 324868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<jlong*>(elems), mode); 324968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 325068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimFloat: 325168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array), 325268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<jfloat*>(elems), mode); 325368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 325468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimDouble: 325568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array), 325668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<jdouble*>(elems), mode); 325768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 325868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 325968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected primitive type: " << type; 326068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 326168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 326268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.V = nullptr; 326368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.Check(soa, false, "V", &result); 326468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 326568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 326668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 326768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 326868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 326968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env, 327068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jarray array, jsize start, jsize len, void* buf) { 327168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 327268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, function_name); 327368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}}; 327468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices 327568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // result in ArrayIndexOutOfBoundsExceptions in the base implementation. 327668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) { 327768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (type) { 327868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimBoolean: 327968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len, 328068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<jboolean*>(buf)); 328168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 328268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimByte: 328368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len, 328468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<jbyte*>(buf)); 328568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 328668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimChar: 328768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len, 328868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<jchar*>(buf)); 328968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 329068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimShort: 329168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len, 329268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<jshort*>(buf)); 329368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 329468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimInt: 329568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len, 329668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<jint*>(buf)); 329768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 329868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimLong: 329968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len, 330068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<jlong*>(buf)); 330168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 330268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimFloat: 330368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len, 330468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<jfloat*>(buf)); 330568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 330668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimDouble: 330768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len, 330868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<jdouble*>(buf)); 330968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 331068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 331168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected primitive type: " << type; 331268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 331368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 331468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.V = nullptr; 331568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.Check(soa, false, "V", &result); 331668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 331768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 331868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 331968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env, 332068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers jarray array, jsize start, jsize len, const void* buf) { 332168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedObjectAccess soa(env); 332268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Default, function_name); 332368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}}; 332468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices 332568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers // result in ArrayIndexOutOfBoundsExceptions in the base implementation. 332668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) { 332768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers switch (type) { 332868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimBoolean: 332968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len, 333068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<const jboolean*>(buf)); 333168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 333268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimByte: 333368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len, 333468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<const jbyte*>(buf)); 333568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 333668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimChar: 333768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len, 333868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<const jchar*>(buf)); 333968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 334068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimShort: 334168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len, 334268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<const jshort*>(buf)); 334368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 334468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimInt: 334568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len, 334668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<const jint*>(buf)); 334768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 334868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimLong: 334968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len, 335068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<const jlong*>(buf)); 335168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 335268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimFloat: 335368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len, 335468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<const jfloat*>(buf)); 335568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 335668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers case Primitive::kPrimDouble: 335768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len, 335868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers reinterpret_cast<const jdouble*>(buf)); 335968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers break; 336068d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers default: 336168d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers LOG(FATAL) << "Unexpected primitive type: " << type; 336268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 336368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 336468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.V = nullptr; 336568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.Check(soa, false, "V", &result); 336668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers } 3367a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 3368a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}; 3369a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 3370a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNINativeInterface gCheckNativeInterface = { 3371ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers nullptr, // reserved0. 3372ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers nullptr, // reserved1. 3373ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers nullptr, // reserved2. 3374ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers nullptr, // reserved3. 3375a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetVersion, 3376a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::DefineClass, 3377a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::FindClass, 3378a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::FromReflectedMethod, 3379a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::FromReflectedField, 3380a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ToReflectedMethod, 3381a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetSuperclass, 3382a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::IsAssignableFrom, 3383a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ToReflectedField, 3384a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::Throw, 3385a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ThrowNew, 3386a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ExceptionOccurred, 3387a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ExceptionDescribe, 3388a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ExceptionClear, 3389a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::FatalError, 3390a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::PushLocalFrame, 3391a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::PopLocalFrame, 3392a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewGlobalRef, 3393a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::DeleteGlobalRef, 3394a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::DeleteLocalRef, 3395a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::IsSameObject, 3396a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewLocalRef, 3397a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::EnsureLocalCapacity, 3398a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::AllocObject, 3399a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewObject, 3400a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewObjectV, 3401a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewObjectA, 3402a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetObjectClass, 3403a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::IsInstanceOf, 3404a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetMethodID, 3405a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallObjectMethod, 3406a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallObjectMethodV, 3407a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallObjectMethodA, 3408a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallBooleanMethod, 3409a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallBooleanMethodV, 3410a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallBooleanMethodA, 3411a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallByteMethod, 3412a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallByteMethodV, 3413a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallByteMethodA, 3414a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallCharMethod, 3415a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallCharMethodV, 3416a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallCharMethodA, 3417a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallShortMethod, 3418a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallShortMethodV, 3419a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallShortMethodA, 3420a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallIntMethod, 3421a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallIntMethodV, 3422a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallIntMethodA, 3423a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallLongMethod, 3424a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallLongMethodV, 3425a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallLongMethodA, 3426a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallFloatMethod, 3427a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallFloatMethodV, 3428a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallFloatMethodA, 3429a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallDoubleMethod, 3430a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallDoubleMethodV, 3431a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallDoubleMethodA, 3432a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallVoidMethod, 3433a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallVoidMethodV, 3434a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallVoidMethodA, 3435a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualObjectMethod, 3436a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualObjectMethodV, 3437a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualObjectMethodA, 3438a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualBooleanMethod, 3439a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualBooleanMethodV, 3440a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualBooleanMethodA, 3441a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualByteMethod, 3442a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualByteMethodV, 3443a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualByteMethodA, 3444a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualCharMethod, 3445a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualCharMethodV, 3446a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualCharMethodA, 3447a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualShortMethod, 3448a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualShortMethodV, 3449a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualShortMethodA, 3450a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualIntMethod, 3451a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualIntMethodV, 3452a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualIntMethodA, 3453a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualLongMethod, 3454a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualLongMethodV, 3455a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualLongMethodA, 3456a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualFloatMethod, 3457a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualFloatMethodV, 3458a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualFloatMethodA, 3459a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualDoubleMethod, 3460a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualDoubleMethodV, 3461a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualDoubleMethodA, 3462a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualVoidMethod, 3463a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualVoidMethodV, 3464a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualVoidMethodA, 3465a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetFieldID, 3466a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetObjectField, 3467a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetBooleanField, 3468a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetByteField, 3469a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetCharField, 3470a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetShortField, 3471a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetIntField, 3472a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetLongField, 3473a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetFloatField, 3474a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetDoubleField, 3475a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetObjectField, 3476a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetBooleanField, 3477a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetByteField, 3478a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetCharField, 3479a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetShortField, 3480a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetIntField, 3481a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetLongField, 3482a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetFloatField, 3483a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetDoubleField, 3484a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticMethodID, 3485a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticObjectMethod, 3486a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticObjectMethodV, 3487a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticObjectMethodA, 3488a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticBooleanMethod, 3489a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticBooleanMethodV, 3490a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticBooleanMethodA, 3491a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticByteMethod, 3492a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticByteMethodV, 3493a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticByteMethodA, 3494a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticCharMethod, 3495a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticCharMethodV, 3496a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticCharMethodA, 3497a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticShortMethod, 3498a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticShortMethodV, 3499a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticShortMethodA, 3500a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticIntMethod, 3501a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticIntMethodV, 3502a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticIntMethodA, 3503a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticLongMethod, 3504a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticLongMethodV, 3505a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticLongMethodA, 3506a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticFloatMethod, 3507a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticFloatMethodV, 3508a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticFloatMethodA, 3509a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticDoubleMethod, 3510a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticDoubleMethodV, 3511a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticDoubleMethodA, 3512a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticVoidMethod, 3513a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticVoidMethodV, 3514a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticVoidMethodA, 3515a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticFieldID, 3516a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticObjectField, 3517a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticBooleanField, 3518a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticByteField, 3519a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticCharField, 3520a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticShortField, 3521a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticIntField, 3522a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticLongField, 3523a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticFloatField, 3524a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticDoubleField, 3525a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetStaticObjectField, 3526a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetStaticBooleanField, 3527a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetStaticByteField, 3528a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetStaticCharField, 3529a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetStaticShortField, 3530a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetStaticIntField, 3531a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetStaticLongField, 3532a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetStaticFloatField, 3533a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetStaticDoubleField, 3534a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewString, 3535a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStringLength, 3536a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStringChars, 3537a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseStringChars, 3538a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewStringUTF, 3539a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStringUTFLength, 3540a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStringUTFChars, 3541a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseStringUTFChars, 3542a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetArrayLength, 3543a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewObjectArray, 3544a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetObjectArrayElement, 3545a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetObjectArrayElement, 3546a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewBooleanArray, 3547a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewByteArray, 3548a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewCharArray, 3549a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewShortArray, 3550a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewIntArray, 3551a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewLongArray, 3552a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewFloatArray, 3553a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewDoubleArray, 3554a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetBooleanArrayElements, 3555a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetByteArrayElements, 3556a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetCharArrayElements, 3557a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetShortArrayElements, 3558a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetIntArrayElements, 3559a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetLongArrayElements, 3560a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetFloatArrayElements, 3561a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetDoubleArrayElements, 3562a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseBooleanArrayElements, 3563a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseByteArrayElements, 3564a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseCharArrayElements, 3565a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseShortArrayElements, 3566a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseIntArrayElements, 3567a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseLongArrayElements, 3568a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseFloatArrayElements, 3569a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseDoubleArrayElements, 3570a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetBooleanArrayRegion, 3571a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetByteArrayRegion, 3572a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetCharArrayRegion, 3573a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetShortArrayRegion, 3574a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetIntArrayRegion, 3575a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetLongArrayRegion, 3576a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetFloatArrayRegion, 3577a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetDoubleArrayRegion, 3578a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetBooleanArrayRegion, 3579a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetByteArrayRegion, 3580a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetCharArrayRegion, 3581a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetShortArrayRegion, 3582a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetIntArrayRegion, 3583a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetLongArrayRegion, 3584a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetFloatArrayRegion, 3585a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetDoubleArrayRegion, 3586a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::RegisterNatives, 3587a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::UnregisterNatives, 3588a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::MonitorEnter, 3589a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::MonitorExit, 3590a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetJavaVM, 3591a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStringRegion, 3592a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStringUTFRegion, 3593a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetPrimitiveArrayCritical, 3594a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleasePrimitiveArrayCritical, 3595a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStringCritical, 3596a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseStringCritical, 3597a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewWeakGlobalRef, 3598a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::DeleteWeakGlobalRef, 3599a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ExceptionCheck, 3600a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewDirectByteBuffer, 3601a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetDirectBufferAddress, 3602a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetDirectBufferCapacity, 3603a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetObjectRefType, 3604a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}; 3605a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 3606a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNINativeInterface* GetCheckJniNativeInterface() { 3607a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return &gCheckNativeInterface; 3608a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes} 3609a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 3610a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesclass CheckJII { 3611ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes public: 3612a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint DestroyJavaVM(JavaVM* vm) { 361368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false); 361468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[1] = {{.v = vm}}; 361568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args); 361668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 361768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.i = BaseVm(vm)->DestroyJavaVM(vm); 361868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result); 361968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.i; 3620a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 3621a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 3622a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) { 362368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Invocation, __FUNCTION__); 362468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}}; 362568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args); 362668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 362768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args); 362868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result); 362968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.i; 3630a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 3631a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 3632a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) { 363368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Invocation, __FUNCTION__); 363468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}}; 363568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args); 363668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 363768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args); 363868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result); 363968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.i; 3640a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 3641a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 3642a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint DetachCurrentThread(JavaVM* vm) { 364368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Invocation, __FUNCTION__); 364468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[1] = {{.v = vm}}; 364568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args); 364668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 364768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.i = BaseVm(vm)->DetachCurrentThread(vm); 364868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result); 364968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.i; 3650a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 3651a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 365268d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static jint GetEnv(JavaVM* vm, void** p_env, jint version) { 365368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers ScopedCheck sc(kFlag_Invocation, __FUNCTION__); 365468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}}; 365568d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args); 365668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers JniValueType result; 365768d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers result.i = BaseVm(vm)->GetEnv(vm, p_env, version); 365868d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result); 365968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return result.i; 3660a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 3661a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 3662a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes private: 366368d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers static const JNIInvokeInterface* BaseVm(JavaVM* vm) { 366468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions(); 3665a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 3666a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}; 3667a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 3668a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNIInvokeInterface gCheckInvokeInterface = { 3669ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers nullptr, // reserved0 3670ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers nullptr, // reserved1 3671ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers nullptr, // reserved2 3672a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJII::DestroyJavaVM, 3673a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJII::AttachCurrentThread, 3674a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJII::DetachCurrentThread, 3675a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJII::GetEnv, 3676a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJII::AttachCurrentThreadAsDaemon 3677a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}; 3678a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 3679a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNIInvokeInterface* GetCheckJniInvokeInterface() { 3680a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return &gCheckInvokeInterface; 3681a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes} 3682a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 3683a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes} // namespace art 3684