12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/* 22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project 32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License. 62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at 72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software 112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and 142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License. 152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */ 16578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom 1753c913bb71b218714823c8c87a1f92830c336f61Andreas Gampe#include "jni_compiler.h" 1853c913bb71b218714823c8c87a1f92830c336f61Andreas Gampe 19fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom#include <algorithm> 20700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers#include <memory> 210cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers#include <vector> 2265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#include <fstream> 23578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom 243d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier#include "art_method.h" 2507ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h" 26761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/macros.h" 27578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "calling_convention.h" 280571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers#include "class_linker.h" 293320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom#include "compiled_method.h" 304f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h" 317940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "driver/compiler_driver.h" 32c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#include "driver/compiler_options.h" 33166db04e259ca51838c311891598664deeed85adIan Rogers#include "entrypoints/quick/quick_entrypoints.h" 3468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#include "jni_env_ext.h" 35166db04e259ca51838c311891598664deeed85adIan Rogers#include "utils/assembler.h" 36166db04e259ca51838c311891598664deeed85adIan Rogers#include "utils/managed_register.h" 37166db04e259ca51838c311891598664deeed85adIan Rogers#include "utils/arm/managed_register_arm.h" 3875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu#include "utils/arm64/managed_register_arm64.h" 39166db04e259ca51838c311891598664deeed85adIan Rogers#include "utils/mips/managed_register_mips.h" 406ea651f0f4c7de4580beb2e887d86802c1ae0738Maja Gagic#include "utils/mips64/managed_register_mips64.h" 41166db04e259ca51838c311891598664deeed85adIan Rogers#include "utils/x86/managed_register_x86.h" 42578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "thread.h" 43b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 4446f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes#define __ jni_asm-> 4546f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes 46b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersnamespace art { 47b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 4846f060a53fffc14333096f0a48f95730ee4768eeElliott Hughesstatic void CopyParameter(Assembler* jni_asm, 4946f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes ManagedRuntimeCallingConvention* mr_conv, 5046f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes JniCallingConvention* jni_conv, 5100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers size_t frame_size, size_t out_arg_size); 5246f060a53fffc14333096f0a48f95730ee4768eeElliott Hughesstatic void SetNativeParameter(Assembler* jni_asm, 5346f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes JniCallingConvention* jni_conv, 5400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ManagedRegister in_reg); 553e778f7ee62fe75912379531022a09230c25f5f8Elliott Hughes 56b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Generate the JNI bridge for the given method, general contract: 57b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// - Arguments are in the managed runtime format, either on stack or in 58b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// registers, a reference to the method object is supplied as part of this 59b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// convention. 60b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// 6172d32629303f8f39362a4099481f48646aed042fIan RogersCompiledMethod* ArtJniCompileMethodInternal(CompilerDriver* driver, 6246f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes uint32_t access_flags, uint32_t method_idx, 6346f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes const DexFile& dex_file) { 64748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes const bool is_native = (access_flags & kAccNative) != 0; 65748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes CHECK(is_native); 66169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers const bool is_static = (access_flags & kAccStatic) != 0; 67169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers const bool is_synchronized = (access_flags & kAccSynchronized) != 0; 68169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx)); 6972d32629303f8f39362a4099481f48646aed042fIan Rogers InstructionSet instruction_set = driver->GetInstructionSet(); 70af13ad9fd18b6f75fe82e7995224c55654594f93Andreas Gampe const bool is_64_bit_target = Is64BitInstructionSet(instruction_set); 712c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers // Calling conventions used to iterate over parameters to method 72700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<JniCallingConvention> main_jni_conv( 7346f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes JniCallingConvention::Create(is_static, is_synchronized, shorty, instruction_set)); 74fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom bool reference_return = main_jni_conv->IsReturnAReference(); 75fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom 76700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<ManagedRuntimeCallingConvention> mr_conv( 7746f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes ManagedRuntimeCallingConvention::Create(is_static, is_synchronized, shorty, instruction_set)); 782c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 79fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom // Calling conventions to call into JNI method "end" possibly passing a returned reference, the 80fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom // method and the current thread. 8175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu const char* jni_end_shorty; 8275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu if (reference_return && is_synchronized) { 8375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu jni_end_shorty = "ILL"; 8475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else if (reference_return) { 8575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu jni_end_shorty = "IL"; 8675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else if (is_synchronized) { 8775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu jni_end_shorty = "VL"; 8875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else { 8975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu jni_end_shorty = "V"; 9075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 9175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu 92700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<JniCallingConvention> end_jni_conv( 93fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom JniCallingConvention::Create(is_static, is_synchronized, jni_end_shorty, instruction_set)); 94fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom 952c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers // Assembler that holds generated instructions 96700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<Assembler> jni_asm(Assembler::Create(instruction_set)); 97a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky jni_asm->cfi().SetEnabled(driver->GetCompilerOptions().GetGenerateDebugInfo()); 982c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 992c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers // Offsets into data structures 1002c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers // TODO: if cross compiling these offsets are for the host not the target 1012c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers const Offset functions(OFFSETOF_MEMBER(JNIEnvExt, functions)); 1022c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers const Offset monitor_enter(OFFSETOF_MEMBER(JNINativeInterface, MonitorEnter)); 1032c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers const Offset monitor_exit(OFFSETOF_MEMBER(JNINativeInterface, MonitorExit)); 1042c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 105bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // 1. Build the frame saving all callee saves 106fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom const size_t frame_size(main_jni_conv->FrameSize()); 107fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom const std::vector<ManagedRegister>& callee_save_regs = main_jni_conv->CalleeSaveRegisters(); 108b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers __ BuildFrame(frame_size, mr_conv->MethodRegister(), callee_save_regs, mr_conv->EntrySpills()); 109dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky DCHECK_EQ(jni_asm->cfi().GetCurrentCFAOffset(), static_cast<int>(frame_size)); 110b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 111eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // 2. Set up the HandleScope 1122c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers mr_conv->ResetIterator(FrameOffset(frame_size)); 113fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->ResetIterator(FrameOffset(0)); 114eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier __ StoreImmediateToFrame(main_jni_conv->HandleScopeNumRefsOffset(), 115fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->ReferenceCount(), 1162c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers mr_conv->InterproceduralScratchRegister()); 11775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu 118af13ad9fd18b6f75fe82e7995224c55654594f93Andreas Gampe if (is_64_bit_target) { 119eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier __ CopyRawPtrFromThread64(main_jni_conv->HandleScopeLinkOffset(), 1203d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier Thread::TopHandleScopeOffset<8>(), 1213d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier mr_conv->InterproceduralScratchRegister()); 122eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier __ StoreStackOffsetToThread64(Thread::TopHandleScopeOffset<8>(), 1233d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier main_jni_conv->HandleScopeOffset(), 1243d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier mr_conv->InterproceduralScratchRegister()); 12575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else { 126eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier __ CopyRawPtrFromThread32(main_jni_conv->HandleScopeLinkOffset(), 1273d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier Thread::TopHandleScopeOffset<4>(), 1283d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier mr_conv->InterproceduralScratchRegister()); 129eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier __ StoreStackOffsetToThread32(Thread::TopHandleScopeOffset<4>(), 1303d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier main_jni_conv->HandleScopeOffset(), 1313d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier mr_conv->InterproceduralScratchRegister()); 13275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 133b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 134eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // 3. Place incoming reference arguments into handle scope 135fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->Next(); // Skip JNIEnv* 136bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // 3.5. Create Class argument for static methods out of passed method 137b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers if (is_static) { 138eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset handle_scope_offset = main_jni_conv->CurrentParamHandleScopeEntryOffset(); 139eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // Check handle scope offset is within frame 140eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier CHECK_LT(handle_scope_offset.Uint32Value(), frame_size); 1413d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier // Note this LoadRef() doesn't need heap poisoning since its from the ArtMethod. 1421cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi // Note this LoadRef() does not include read barrier. It will be handled below. 143fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom __ LoadRef(main_jni_conv->InterproceduralScratchRegister(), 1443d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier mr_conv->MethodRegister(), ArtMethod::DeclaringClassOffset(), false); 145fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom __ VerifyObject(main_jni_conv->InterproceduralScratchRegister(), false); 146eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier __ StoreRef(handle_scope_offset, main_jni_conv->InterproceduralScratchRegister()); 147eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier main_jni_conv->Next(); // in handle scope so move to next argument 148b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 1492c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers while (mr_conv->HasNext()) { 150fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom CHECK(main_jni_conv->HasNext()); 151fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom bool ref_param = main_jni_conv->IsCurrentParamAReference(); 1522c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers CHECK(!ref_param || mr_conv->IsCurrentParamAReference()); 153eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // References need placing in handle scope and the entry value passing 154b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers if (ref_param) { 155eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // Compute handle scope entry, note null is placed in the handle scope but its boxed value 1562cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier // must be null. 157eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset handle_scope_offset = main_jni_conv->CurrentParamHandleScopeEntryOffset(); 1582cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier // Check handle scope offset is within frame and doesn't run into the saved segment state. 159eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier CHECK_LT(handle_scope_offset.Uint32Value(), frame_size); 160eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier CHECK_NE(handle_scope_offset.Uint32Value(), 161fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->SavedLocalReferenceCookieOffset().Uint32Value()); 1622c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers bool input_in_reg = mr_conv->IsCurrentParamInRegister(); 1632c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers bool input_on_stack = mr_conv->IsCurrentParamOnStack(); 1645381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao CHECK(input_in_reg || input_on_stack); 1655381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao 166b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers if (input_in_reg) { 1672c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers ManagedRegister in_reg = mr_conv->CurrentParamRegister(); 1682c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers __ VerifyObject(in_reg, mr_conv->IsCurrentArgPossiblyNull()); 169eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier __ StoreRef(handle_scope_offset, in_reg); 1705381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao } else if (input_on_stack) { 1712c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers FrameOffset in_off = mr_conv->CurrentParamStackOffset(); 1722c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers __ VerifyObject(in_off, mr_conv->IsCurrentArgPossiblyNull()); 173eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier __ CopyRef(handle_scope_offset, in_off, 1742c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers mr_conv->InterproceduralScratchRegister()); 175b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 176b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 1772c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers mr_conv->Next(); 178fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->Next(); 179b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 180b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 18100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // 4. Write out the end of the quick frames. 182af13ad9fd18b6f75fe82e7995224c55654594f93Andreas Gampe if (is_64_bit_target) { 18375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu __ StoreStackPointerToThread64(Thread::TopOfManagedStackOffset<8>()); 18475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else { 18575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu __ StoreStackPointerToThread32(Thread::TopOfManagedStackOffset<4>()); 18675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 187b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 18800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // 5. Move frame down to allow space for out going args. 189fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom const size_t main_out_arg_size = main_jni_conv->OutArgSize(); 1904e24b9da7c5ea6e517ecdbc09aa14a0995100b7eVladimir Marko size_t current_out_arg_size = main_out_arg_size; 1914e24b9da7c5ea6e517ecdbc09aa14a0995100b7eVladimir Marko __ IncreaseFrameSize(main_out_arg_size); 192b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 1931cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi // Call the read barrier for the declaring class loaded from the method for a static call. 1941cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi // Note that we always have outgoing param space available for at least two params. 1951cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi if (kUseReadBarrier && is_static) { 1961cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi ThreadOffset<4> read_barrier32 = QUICK_ENTRYPOINT_OFFSET(4, pReadBarrierJni); 1971cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi ThreadOffset<8> read_barrier64 = QUICK_ENTRYPOINT_OFFSET(8, pReadBarrierJni); 1981cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size)); 1991cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi main_jni_conv->Next(); // Skip JNIEnv. 2001cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi FrameOffset class_handle_scope_offset = main_jni_conv->CurrentParamHandleScopeEntryOffset(); 2011cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size)); 2021cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi // Pass the handle for the class as the first argument. 2031cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi if (main_jni_conv->IsCurrentParamOnStack()) { 2041cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi FrameOffset out_off = main_jni_conv->CurrentParamStackOffset(); 2051cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi __ CreateHandleScopeEntry(out_off, class_handle_scope_offset, 2061cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi mr_conv->InterproceduralScratchRegister(), 2071cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi false); 2081cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi } else { 2091cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi ManagedRegister out_reg = main_jni_conv->CurrentParamRegister(); 2101cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi __ CreateHandleScopeEntry(out_reg, class_handle_scope_offset, 2111cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi ManagedRegister::NoRegister(), false); 2121cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi } 2131cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi main_jni_conv->Next(); 2141cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi // Pass the current thread as the second argument and call. 2151cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi if (main_jni_conv->IsCurrentParamInRegister()) { 2161cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi __ GetCurrentThread(main_jni_conv->CurrentParamRegister()); 2171cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi if (is_64_bit_target) { 2181cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi __ Call(main_jni_conv->CurrentParamRegister(), Offset(read_barrier64), 2191cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi main_jni_conv->InterproceduralScratchRegister()); 2201cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi } else { 2211cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi __ Call(main_jni_conv->CurrentParamRegister(), Offset(read_barrier32), 2221cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi main_jni_conv->InterproceduralScratchRegister()); 2231cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi } 2241cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi } else { 2251cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi __ GetCurrentThread(main_jni_conv->CurrentParamStackOffset(), 2261cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi main_jni_conv->InterproceduralScratchRegister()); 2271cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi if (is_64_bit_target) { 2281cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi __ CallFromThread64(read_barrier64, main_jni_conv->InterproceduralScratchRegister()); 2291cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi } else { 2301cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi __ CallFromThread32(read_barrier32, main_jni_conv->InterproceduralScratchRegister()); 2311cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi } 2321cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi } 2331cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size)); // Reset. 2341cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi } 2351cc71ebf333ca323ae0e130fefbce4593e385c10Hiroshi Yamauchi 23600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // 6. Call into appropriate JniMethodStart passing Thread* so that transition out of Runnable 23700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // can occur. The result is the saved JNI local state that is restored by the exit call. We 23800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // abuse the JNI calling convention here, that is guaranteed to support passing 2 pointer 23900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // arguments. 24075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu ThreadOffset<4> jni_start32 = is_synchronized ? QUICK_ENTRYPOINT_OFFSET(4, pJniMethodStartSynchronized) 24175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu : QUICK_ENTRYPOINT_OFFSET(4, pJniMethodStart); 24275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu ThreadOffset<8> jni_start64 = is_synchronized ? QUICK_ENTRYPOINT_OFFSET(8, pJniMethodStartSynchronized) 24375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu : QUICK_ENTRYPOINT_OFFSET(8, pJniMethodStart); 244fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size)); 245eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset locked_object_handle_scope_offset(0); 24600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (is_synchronized) { 24700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Pass object for locking. 248fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->Next(); // Skip JNIEnv. 249eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier locked_object_handle_scope_offset = main_jni_conv->CurrentParamHandleScopeEntryOffset(); 250fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size)); 251fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom if (main_jni_conv->IsCurrentParamOnStack()) { 252fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom FrameOffset out_off = main_jni_conv->CurrentParamStackOffset(); 253eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier __ CreateHandleScopeEntry(out_off, locked_object_handle_scope_offset, 2543d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier mr_conv->InterproceduralScratchRegister(), false); 255df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers } else { 256fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom ManagedRegister out_reg = main_jni_conv->CurrentParamRegister(); 257eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier __ CreateHandleScopeEntry(out_reg, locked_object_handle_scope_offset, 2583d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier ManagedRegister::NoRegister(), false); 259bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers } 260fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->Next(); 26100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 262fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom if (main_jni_conv->IsCurrentParamInRegister()) { 263fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom __ GetCurrentThread(main_jni_conv->CurrentParamRegister()); 264af13ad9fd18b6f75fe82e7995224c55654594f93Andreas Gampe if (is_64_bit_target) { 26575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu __ Call(main_jni_conv->CurrentParamRegister(), Offset(jni_start64), 2663d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier main_jni_conv->InterproceduralScratchRegister()); 26775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else { 26875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu __ Call(main_jni_conv->CurrentParamRegister(), Offset(jni_start32), 2693d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier main_jni_conv->InterproceduralScratchRegister()); 27075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 27100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else { 272fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom __ GetCurrentThread(main_jni_conv->CurrentParamStackOffset(), 273fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->InterproceduralScratchRegister()); 274af13ad9fd18b6f75fe82e7995224c55654594f93Andreas Gampe if (is_64_bit_target) { 27575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu __ CallFromThread64(jni_start64, main_jni_conv->InterproceduralScratchRegister()); 27675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else { 27775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu __ CallFromThread32(jni_start32, main_jni_conv->InterproceduralScratchRegister()); 27875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 27900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 28000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (is_synchronized) { // Check for exceptions from monitor enter. 281fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom __ ExceptionPoll(main_jni_conv->InterproceduralScratchRegister(), main_out_arg_size); 282df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers } 283fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom FrameOffset saved_cookie_offset = main_jni_conv->SavedLocalReferenceCookieOffset(); 284fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom __ Store(saved_cookie_offset, main_jni_conv->IntReturnRegister(), 4); 285df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers 286bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // 7. Iterate over arguments placing values from managed calling convention in 287b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // to the convention required for a native call (shuffling). For references 288b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // place an index/pointer to the reference after checking whether it is 2892cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier // null (which must be encoded as null). 29020cde9033d51103f31e21436e88f80e1170c78adElliott Hughes // Note: we do this prior to materializing the JNIEnv* and static's jclass to 2912cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier // give as many free registers for the shuffle as possible. 2924e24b9da7c5ea6e517ecdbc09aa14a0995100b7eVladimir Marko mr_conv->ResetIterator(FrameOffset(frame_size + main_out_arg_size)); 29382da44b625a1af03c0b768c71f1cef29831127c3Shih-wei Liao uint32_t args_count = 0; 2942c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers while (mr_conv->HasNext()) { 29582da44b625a1af03c0b768c71f1cef29831127c3Shih-wei Liao args_count++; 2962c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers mr_conv->Next(); 297e2d373e6e09c1df9a47e73a26254048adb31ce82Carl Shapiro } 29882da44b625a1af03c0b768c71f1cef29831127c3Shih-wei Liao 29982da44b625a1af03c0b768c71f1cef29831127c3Shih-wei Liao // Do a backward pass over arguments, so that the generated code will be "mov 30082da44b625a1af03c0b768c71f1cef29831127c3Shih-wei Liao // R2, R3; mov R1, R2" instead of "mov R1, R2; mov R2, R3." 30182da44b625a1af03c0b768c71f1cef29831127c3Shih-wei Liao // TODO: A reverse iterator to improve readability. 30282da44b625a1af03c0b768c71f1cef29831127c3Shih-wei Liao for (uint32_t i = 0; i < args_count; ++i) { 303fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom mr_conv->ResetIterator(FrameOffset(frame_size + main_out_arg_size)); 304fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size)); 305fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->Next(); // Skip JNIEnv*. 30682da44b625a1af03c0b768c71f1cef29831127c3Shih-wei Liao if (is_static) { 307fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->Next(); // Skip Class for now. 30882da44b625a1af03c0b768c71f1cef29831127c3Shih-wei Liao } 30900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Skip to the argument we're interested in. 31082da44b625a1af03c0b768c71f1cef29831127c3Shih-wei Liao for (uint32_t j = 0; j < args_count - i - 1; ++j) { 3112c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers mr_conv->Next(); 312fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->Next(); 31382da44b625a1af03c0b768c71f1cef29831127c3Shih-wei Liao } 314fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom CopyParameter(jni_asm.get(), mr_conv.get(), main_jni_conv.get(), frame_size, main_out_arg_size); 31582da44b625a1af03c0b768c71f1cef29831127c3Shih-wei Liao } 316e2d373e6e09c1df9a47e73a26254048adb31ce82Carl Shapiro if (is_static) { 317e2d373e6e09c1df9a47e73a26254048adb31ce82Carl Shapiro // Create argument for Class 3184e24b9da7c5ea6e517ecdbc09aa14a0995100b7eVladimir Marko mr_conv->ResetIterator(FrameOffset(frame_size + main_out_arg_size)); 319fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size)); 320fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->Next(); // Skip JNIEnv* 321eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset handle_scope_offset = main_jni_conv->CurrentParamHandleScopeEntryOffset(); 322fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom if (main_jni_conv->IsCurrentParamOnStack()) { 323fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom FrameOffset out_off = main_jni_conv->CurrentParamStackOffset(); 324eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier __ CreateHandleScopeEntry(out_off, handle_scope_offset, 3252c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers mr_conv->InterproceduralScratchRegister(), 3262c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers false); 327b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } else { 328fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom ManagedRegister out_reg = main_jni_conv->CurrentParamRegister(); 329eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier __ CreateHandleScopeEntry(out_reg, handle_scope_offset, 3302c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers ManagedRegister::NoRegister(), false); 331b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 332b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 33300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 33400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // 8. Create 1st argument, the JNI environment ptr. 335fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size)); 336dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers // Register that will hold local indirect reference table 337fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom if (main_jni_conv->IsCurrentParamInRegister()) { 338fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom ManagedRegister jni_env = main_jni_conv->CurrentParamRegister(); 339fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom DCHECK(!jni_env.Equals(main_jni_conv->InterproceduralScratchRegister())); 340af13ad9fd18b6f75fe82e7995224c55654594f93Andreas Gampe if (is_64_bit_target) { 34175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu __ LoadRawPtrFromThread64(jni_env, Thread::JniEnvOffset<8>()); 34275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else { 34375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu __ LoadRawPtrFromThread32(jni_env, Thread::JniEnvOffset<4>()); 34475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 345b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } else { 346fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom FrameOffset jni_env = main_jni_conv->CurrentParamStackOffset(); 347af13ad9fd18b6f75fe82e7995224c55654594f93Andreas Gampe if (is_64_bit_target) { 34875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu __ CopyRawPtrFromThread64(jni_env, Thread::JniEnvOffset<8>(), 3493d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier main_jni_conv->InterproceduralScratchRegister()); 35075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else { 35175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu __ CopyRawPtrFromThread32(jni_env, Thread::JniEnvOffset<4>(), 3523d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier main_jni_conv->InterproceduralScratchRegister()); 35375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 354b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 355b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 35600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // 9. Plant call to native code associated with method. 3573d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier MemberOffset jni_entrypoint_offset = ArtMethod::EntryPointFromJniOffset( 3582d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier InstructionSetPointerSize(instruction_set)); 3592d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier __ Call(main_jni_conv->MethodStackOffset(), jni_entrypoint_offset, 36000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mr_conv->InterproceduralScratchRegister()); 361bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 36200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // 10. Fix differences in result widths. 363d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe if (main_jni_conv->RequiresSmallResultTypeExtension()) { 364fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom if (main_jni_conv->GetReturnType() == Primitive::kPrimByte || 365fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->GetReturnType() == Primitive::kPrimShort) { 366fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom __ SignExtend(main_jni_conv->ReturnRegister(), 367fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom Primitive::ComponentSize(main_jni_conv->GetReturnType())); 368fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom } else if (main_jni_conv->GetReturnType() == Primitive::kPrimBoolean || 369fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom main_jni_conv->GetReturnType() == Primitive::kPrimChar) { 370fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom __ ZeroExtend(main_jni_conv->ReturnRegister(), 371fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom Primitive::ComponentSize(main_jni_conv->GetReturnType())); 372cee4d0c1c2faacf0eae748a24cc7e455e067d977jeffhao } 373b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 374b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 37500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // 11. Save return value 376fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom FrameOffset return_save_location = main_jni_conv->ReturnValueSaveLocation(); 377fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom if (main_jni_conv->SizeOfReturnValue() != 0 && !reference_return) { 3786ea651f0f4c7de4580beb2e887d86802c1ae0738Maja Gagic if ((instruction_set == kMips || instruction_set == kMips64) && 3796ea651f0f4c7de4580beb2e887d86802c1ae0738Maja Gagic main_jni_conv->GetReturnType() == Primitive::kPrimDouble && 3800703060875166106af3d490c6c264611aea67ec8jeffhao return_save_location.Uint32Value() % 8 != 0) { 3810703060875166106af3d490c6c264611aea67ec8jeffhao // Ensure doubles are 8-byte aligned for MIPS 382af13ad9fd18b6f75fe82e7995224c55654594f93Andreas Gampe return_save_location = FrameOffset(return_save_location.Uint32Value() + kMipsPointerSize); 3830703060875166106af3d490c6c264611aea67ec8jeffhao } 3844e24b9da7c5ea6e517ecdbc09aa14a0995100b7eVladimir Marko CHECK_LT(return_save_location.Uint32Value(), frame_size + main_out_arg_size); 385fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom __ Store(return_save_location, main_jni_conv->ReturnRegister(), main_jni_conv->SizeOfReturnValue()); 3865a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers } 387726079d3e2e50854cd6ca4c393f4529a796dba58Elliott Hughes 3884e24b9da7c5ea6e517ecdbc09aa14a0995100b7eVladimir Marko // Increase frame size for out args if needed by the end_jni_conv. 3894e24b9da7c5ea6e517ecdbc09aa14a0995100b7eVladimir Marko const size_t end_out_arg_size = end_jni_conv->OutArgSize(); 3904e24b9da7c5ea6e517ecdbc09aa14a0995100b7eVladimir Marko if (end_out_arg_size > current_out_arg_size) { 3914e24b9da7c5ea6e517ecdbc09aa14a0995100b7eVladimir Marko size_t out_arg_size_diff = end_out_arg_size - current_out_arg_size; 3924e24b9da7c5ea6e517ecdbc09aa14a0995100b7eVladimir Marko current_out_arg_size = end_out_arg_size; 3934e24b9da7c5ea6e517ecdbc09aa14a0995100b7eVladimir Marko __ IncreaseFrameSize(out_arg_size_diff); 3944e24b9da7c5ea6e517ecdbc09aa14a0995100b7eVladimir Marko saved_cookie_offset = FrameOffset(saved_cookie_offset.SizeValue() + out_arg_size_diff); 3954e24b9da7c5ea6e517ecdbc09aa14a0995100b7eVladimir Marko locked_object_handle_scope_offset = 3964e24b9da7c5ea6e517ecdbc09aa14a0995100b7eVladimir Marko FrameOffset(locked_object_handle_scope_offset.SizeValue() + out_arg_size_diff); 3974e24b9da7c5ea6e517ecdbc09aa14a0995100b7eVladimir Marko return_save_location = FrameOffset(return_save_location.SizeValue() + out_arg_size_diff); 3984e24b9da7c5ea6e517ecdbc09aa14a0995100b7eVladimir Marko } 39900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // thread. 400fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom end_jni_conv->ResetIterator(FrameOffset(end_out_arg_size)); 40175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu ThreadOffset<4> jni_end32(-1); 40275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu ThreadOffset<8> jni_end64(-1); 40300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (reference_return) { 40400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Pass result. 40575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu jni_end32 = is_synchronized ? QUICK_ENTRYPOINT_OFFSET(4, pJniMethodEndWithReferenceSynchronized) 40675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu : QUICK_ENTRYPOINT_OFFSET(4, pJniMethodEndWithReference); 40775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu jni_end64 = is_synchronized ? QUICK_ENTRYPOINT_OFFSET(8, pJniMethodEndWithReferenceSynchronized) 40875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu : QUICK_ENTRYPOINT_OFFSET(8, pJniMethodEndWithReference); 409fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom SetNativeParameter(jni_asm.get(), end_jni_conv.get(), end_jni_conv->ReturnRegister()); 410fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom end_jni_conv->Next(); 41100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else { 41275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu jni_end32 = is_synchronized ? QUICK_ENTRYPOINT_OFFSET(4, pJniMethodEndSynchronized) 41375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu : QUICK_ENTRYPOINT_OFFSET(4, pJniMethodEnd); 41475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu jni_end64 = is_synchronized ? QUICK_ENTRYPOINT_OFFSET(8, pJniMethodEndSynchronized) 41575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu : QUICK_ENTRYPOINT_OFFSET(8, pJniMethodEnd); 41600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 41700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Pass saved local reference state. 418fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom if (end_jni_conv->IsCurrentParamOnStack()) { 419fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom FrameOffset out_off = end_jni_conv->CurrentParamStackOffset(); 420fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom __ Copy(out_off, saved_cookie_offset, end_jni_conv->InterproceduralScratchRegister(), 4); 42100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else { 422fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom ManagedRegister out_reg = end_jni_conv->CurrentParamRegister(); 42300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers __ Load(out_reg, saved_cookie_offset, 4); 42400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 425fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom end_jni_conv->Next(); 426169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers if (is_synchronized) { 42700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Pass object for unlocking. 428fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom if (end_jni_conv->IsCurrentParamOnStack()) { 429fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom FrameOffset out_off = end_jni_conv->CurrentParamStackOffset(); 430eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier __ CreateHandleScopeEntry(out_off, locked_object_handle_scope_offset, 431fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom end_jni_conv->InterproceduralScratchRegister(), 43200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers false); 43300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else { 434fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom ManagedRegister out_reg = end_jni_conv->CurrentParamRegister(); 435eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier __ CreateHandleScopeEntry(out_reg, locked_object_handle_scope_offset, 43600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ManagedRegister::NoRegister(), false); 43700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 438fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom end_jni_conv->Next(); 43900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 440fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom if (end_jni_conv->IsCurrentParamInRegister()) { 441fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom __ GetCurrentThread(end_jni_conv->CurrentParamRegister()); 442af13ad9fd18b6f75fe82e7995224c55654594f93Andreas Gampe if (is_64_bit_target) { 44375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu __ Call(end_jni_conv->CurrentParamRegister(), Offset(jni_end64), 44475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu end_jni_conv->InterproceduralScratchRegister()); 44575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else { 44675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu __ Call(end_jni_conv->CurrentParamRegister(), Offset(jni_end32), 44775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu end_jni_conv->InterproceduralScratchRegister()); 44875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 449bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers } else { 450fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom __ GetCurrentThread(end_jni_conv->CurrentParamStackOffset(), 451fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom end_jni_conv->InterproceduralScratchRegister()); 452af13ad9fd18b6f75fe82e7995224c55654594f93Andreas Gampe if (is_64_bit_target) { 45375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu __ CallFromThread64(ThreadOffset<8>(jni_end64), end_jni_conv->InterproceduralScratchRegister()); 45475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else { 45575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu __ CallFromThread32(ThreadOffset<4>(jni_end32), end_jni_conv->InterproceduralScratchRegister()); 45675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 457bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers } 458b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 45900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // 13. Reload return value 460fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom if (main_jni_conv->SizeOfReturnValue() != 0 && !reference_return) { 46100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers __ Load(mr_conv->ReturnRegister(), return_save_location, mr_conv->SizeOfReturnValue()); 46200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 46300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 46400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // 14. Move frame up now we're done with the out arg space. 4654e24b9da7c5ea6e517ecdbc09aa14a0995100b7eVladimir Marko __ DecreaseFrameSize(current_out_arg_size); 46600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 46700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // 15. Process pending exceptions from JNI call or monitor exit. 468fc7120c0293b96218d55abee29882f101acbc79bBrian Carlstrom __ ExceptionPoll(main_jni_conv->InterproceduralScratchRegister(), 0); 46900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 4708770e5c77868dd3c6c832ba9ea68140f70e73088Mathieu Chartier // 16. Remove activation - need to restore callee save registers since the GC may have changed 47100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // them. 472dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky DCHECK_EQ(jni_asm->cfi().GetCurrentCFAOffset(), static_cast<int>(frame_size)); 4738770e5c77868dd3c6c832ba9ea68140f70e73088Mathieu Chartier __ RemoveFrame(frame_size, callee_save_regs); 474dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky DCHECK_EQ(jni_asm->cfi().GetCurrentCFAOffset(), static_cast<int>(frame_size)); 47500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 476e5de95b3f9609e02fefd7cda7b21f30c9412eb4cIan Rogers // 17. Finalize code generation 4772c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers __ EmitSlowPaths(); 4782c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers size_t cs = __ CodeSize(); 4793320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom std::vector<uint8_t> managed_code(cs); 4803320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom MemoryRegion code(&managed_code[0], managed_code.size()); 4812c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers __ FinalizeInstructions(code); 4828c57831b2b07185ee1986b9af68a351e1ca584c3David Srbecky 483c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky return CompiledMethod::SwapAllocCompiledMethod(driver, 484c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky instruction_set, 485c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ArrayRef<const uint8_t>(managed_code), 486c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky frame_size, 487c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky main_jni_conv->CoreSpillMask(), 488c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky main_jni_conv->FpSpillMask(), 489c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky nullptr, // src_mapping_table. 490c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ArrayRef<const uint8_t>(), // mapping_table. 491c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ArrayRef<const uint8_t>(), // vmap_table. 492c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ArrayRef<const uint8_t>(), // native_gc_map. 493c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ArrayRef<const uint8_t>(*jni_asm->cfi().data()), 494c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky ArrayRef<const LinkerPatch>()); 495b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} 496b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 4972cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier// Copy a single parameter from the managed to the JNI calling convention. 49800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic void CopyParameter(Assembler* jni_asm, 49900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ManagedRuntimeCallingConvention* mr_conv, 50000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JniCallingConvention* jni_conv, 50100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers size_t frame_size, size_t out_arg_size) { 50200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool input_in_reg = mr_conv->IsCurrentParamInRegister(); 50300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool output_in_reg = jni_conv->IsCurrentParamInRegister(); 504eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset handle_scope_offset(0); 50500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool null_allowed = false; 50600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool ref_param = jni_conv->IsCurrentParamAReference(); 50700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK(!ref_param || mr_conv->IsCurrentParamAReference()); 50800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // input may be in register, on stack or both - but not none! 50900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK(input_in_reg || mr_conv->IsCurrentParamOnStack()); 51000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (output_in_reg) { // output shouldn't straddle registers and stack 51100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK(!jni_conv->IsCurrentParamOnStack()); 51200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else { 51300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK(jni_conv->IsCurrentParamOnStack()); 51400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 5152cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier // References need placing in handle scope and the entry address passing. 51600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (ref_param) { 51700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers null_allowed = mr_conv->IsCurrentArgPossiblyNull(); 518eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // Compute handle scope offset. Note null is placed in the handle scope but the jobject 519eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // passed to the native code must be null (not a pointer into the handle scope 52000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // as with regular references). 521eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier handle_scope_offset = jni_conv->CurrentParamHandleScopeEntryOffset(); 522eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // Check handle scope offset is within frame. 523eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier CHECK_LT(handle_scope_offset.Uint32Value(), (frame_size + out_arg_size)); 52400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 52500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (input_in_reg && output_in_reg) { 52600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ManagedRegister in_reg = mr_conv->CurrentParamRegister(); 52700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ManagedRegister out_reg = jni_conv->CurrentParamRegister(); 52800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (ref_param) { 529eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier __ CreateHandleScopeEntry(out_reg, handle_scope_offset, in_reg, null_allowed); 53000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else { 53100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (!mr_conv->IsCurrentParamOnStack()) { 53200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // regular non-straddling move 53300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers __ Move(out_reg, in_reg, mr_conv->CurrentParamSize()); 53400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else { 53500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers UNIMPLEMENTED(FATAL); // we currently don't expect to see this case 53600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 53700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 53800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else if (!input_in_reg && !output_in_reg) { 53900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers FrameOffset out_off = jni_conv->CurrentParamStackOffset(); 54000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (ref_param) { 541eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier __ CreateHandleScopeEntry(out_off, handle_scope_offset, mr_conv->InterproceduralScratchRegister(), 54200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers null_allowed); 54300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else { 54400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers FrameOffset in_off = mr_conv->CurrentParamStackOffset(); 54500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers size_t param_size = mr_conv->CurrentParamSize(); 54600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK_EQ(param_size, jni_conv->CurrentParamSize()); 54700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers __ Copy(out_off, in_off, mr_conv->InterproceduralScratchRegister(), param_size); 54800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 54900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else if (!input_in_reg && output_in_reg) { 55000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers FrameOffset in_off = mr_conv->CurrentParamStackOffset(); 55100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ManagedRegister out_reg = jni_conv->CurrentParamRegister(); 55200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Check that incoming stack arguments are above the current stack frame. 55300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK_GT(in_off.Uint32Value(), frame_size); 55400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (ref_param) { 555eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier __ CreateHandleScopeEntry(out_reg, handle_scope_offset, ManagedRegister::NoRegister(), null_allowed); 55600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else { 55700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers size_t param_size = mr_conv->CurrentParamSize(); 55800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK_EQ(param_size, jni_conv->CurrentParamSize()); 55900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers __ Load(out_reg, in_off, param_size); 56000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 56100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else { 56200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK(input_in_reg && !output_in_reg); 56300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ManagedRegister in_reg = mr_conv->CurrentParamRegister(); 56400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers FrameOffset out_off = jni_conv->CurrentParamStackOffset(); 56500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Check outgoing argument is within frame 56600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK_LT(out_off.Uint32Value(), frame_size); 56700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (ref_param) { 568eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // TODO: recycle value in in_reg rather than reload from handle scope 569eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier __ CreateHandleScopeEntry(out_off, handle_scope_offset, mr_conv->InterproceduralScratchRegister(), 57000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers null_allowed); 57100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else { 57200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers size_t param_size = mr_conv->CurrentParamSize(); 57300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK_EQ(param_size, jni_conv->CurrentParamSize()); 57400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (!mr_conv->IsCurrentParamOnStack()) { 57500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // regular non-straddling store 57600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers __ Store(out_off, in_reg, param_size); 57700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else { 57800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // store where input straddles registers and stack 57900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK_EQ(param_size, 8u); 58000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers FrameOffset in_off = mr_conv->CurrentParamStackOffset(); 58100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers __ StoreSpanning(out_off, in_reg, in_off, mr_conv->InterproceduralScratchRegister()); 58200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 58300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 58400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 58500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers} 58600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 58700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic void SetNativeParameter(Assembler* jni_asm, 58800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JniCallingConvention* jni_conv, 58900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ManagedRegister in_reg) { 59000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (jni_conv->IsCurrentParamOnStack()) { 59100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers FrameOffset dest = jni_conv->CurrentParamStackOffset(); 59200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers __ StoreRawPtr(dest, in_reg); 59300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else { 59400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (!jni_conv->CurrentParamRegister().Equals(in_reg)) { 59500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers __ Move(jni_conv->CurrentParamRegister(), in_reg, jni_conv->CurrentParamSize()); 59600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 59700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 59800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers} 59900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 60053c913bb71b218714823c8c87a1f92830c336f61Andreas GampeCompiledMethod* ArtQuickJniCompileMethod(CompilerDriver* compiler, uint32_t access_flags, 60153c913bb71b218714823c8c87a1f92830c336f61Andreas Gampe uint32_t method_idx, const DexFile& dex_file) { 60257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return ArtJniCompileMethodInternal(compiler, access_flags, method_idx, dex_file); 603e5de95b3f9609e02fefd7cda7b21f30c9412eb4cIan Rogers} 60453c913bb71b218714823c8c87a1f92830c336f61Andreas Gampe 60553c913bb71b218714823c8c87a1f92830c336f61Andreas Gampe} // namespace art 606