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 */ 16b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 17fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#ifndef ART_COMPILER_JNI_QUICK_CALLING_CONVENTION_H_ 18fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#define ART_COMPILER_JNI_QUICK_CALLING_CONVENTION_H_ 19b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 200d666d8769714dcbc2acc4dd5b06f0deffa6e0a1Ian Rogers#include <vector> 21d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko 22d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko#include "base/arena_object.h" 23eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier#include "handle_scope.h" 24e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "primitive.h" 25578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "thread.h" 26166db04e259ca51838c311891598664deeed85adIan Rogers#include "utils/managed_register.h" 27b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 28b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersnamespace art { 29b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 30790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers// Top-level abstraction for different calling conventions. 31d1ee80948144526b985afb44a0574248cf7da58aVladimir Markoclass CallingConvention : public DeletableArenaObject<kArenaAllocCallingConvention> { 32b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers public: 33169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers bool IsReturnAReference() const { return shorty_[0] == 'L'; } 34169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers 3558136caeec7cb677bb83c2eafd1f4bab5afd96c8jeffhao Primitive::Type GetReturnType() const { 3658136caeec7cb677bb83c2eafd1f4bab5afd96c8jeffhao return Primitive::GetType(shorty_[0]); 3758136caeec7cb677bb83c2eafd1f4bab5afd96c8jeffhao } 3858136caeec7cb677bb83c2eafd1f4bab5afd96c8jeffhao 39169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t SizeOfReturnValue() const { 40169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t result = Primitive::ComponentSize(Primitive::GetType(shorty_[0])); 41169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers if (result >= 1 && result < 4) { 42169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers result = 4; 43169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 44169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return result; 45169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 46df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers 4700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Register that holds result of this method invocation. 482c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ManagedRegister ReturnRegister() = 0; 4900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Register reserved for scratch usage during procedure calls. 502c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ManagedRegister InterproceduralScratchRegister() = 0; 51668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao 52790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // Offset of Method within the frame. 53790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers FrameOffset MethodStackOffset() { 54790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers return displacement_; 55790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers } 56e2d373e6e09c1df9a47e73a26254048adb31ce82Carl Shapiro 57b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Iterator interface 58b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 59b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Place iterator at start of arguments. The displacement is applied to 60b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // frame offset methods to account for frames which may be on the stack 61b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // below the one being iterated over. 62b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers void ResetIterator(FrameOffset displacement) { 63b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers displacement_ = displacement; 645381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao itr_slots_ = 0; 655381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao itr_args_ = 0; 66668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao itr_refs_ = 0; 67b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers itr_longs_and_doubles_ = 0; 68fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko itr_float_and_doubles_ = 0; 69b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 70b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 712c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ~CallingConvention() {} 722c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 73b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers protected: 74790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers CallingConvention(bool is_static, bool is_synchronized, const char* shorty, 75790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers size_t frame_pointer_size) 76790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers : itr_slots_(0), itr_refs_(0), itr_args_(0), itr_longs_and_doubles_(0), 77790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers itr_float_and_doubles_(0), displacement_(0), 78790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers frame_pointer_size_(frame_pointer_size), 79eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier handle_scope_pointer_size_(sizeof(StackReference<mirror::Object>)), 80790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers is_static_(is_static), is_synchronized_(is_synchronized), 81169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers shorty_(shorty) { 82169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers num_args_ = (is_static ? 0 : 1) + strlen(shorty) - 1; 83169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers num_ref_args_ = is_static ? 0 : 1; // The implicit this pointer. 84fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko num_float_or_double_args_ = 0; 85169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers num_long_or_double_args_ = 0; 86169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers for (size_t i = 1; i < strlen(shorty); i++) { 87169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers char ch = shorty_[i]; 88fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko switch (ch) { 89fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko case 'L': 90169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers num_ref_args_++; 91fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko break; 92fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko case 'J': 93169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers num_long_or_double_args_++; 94fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko break; 95fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko case 'D': 96fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko num_long_or_double_args_++; 97fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko num_float_or_double_args_++; 98fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko break; 99fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko case 'F': 100fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko num_float_or_double_args_++; 101fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko break; 102169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 103169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 104169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 1052c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 106169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers bool IsStatic() const { 107169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return is_static_; 108169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 109169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers bool IsSynchronized() const { 110169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return is_synchronized_; 111169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 112169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers bool IsParamALongOrDouble(unsigned int param) const { 113169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers DCHECK_LT(param, NumArgs()); 114169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers if (IsStatic()) { 115169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers param++; // 0th argument must skip return value at start of the shorty 116169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } else if (param == 0) { 117169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return false; // this argument 118169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 119169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers char ch = shorty_[param]; 120169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return (ch == 'J' || ch == 'D'); 121169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 122fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko bool IsParamAFloatOrDouble(unsigned int param) const { 123fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko DCHECK_LT(param, NumArgs()); 124fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko if (IsStatic()) { 125fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko param++; // 0th argument must skip return value at start of the shorty 126fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko } else if (param == 0) { 127fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko return false; // this argument 128fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko } 129fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko char ch = shorty_[param]; 130fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko return (ch == 'F' || ch == 'D'); 131fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko } 13275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsParamADouble(unsigned int param) const { 13375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu DCHECK_LT(param, NumArgs()); 13475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu if (IsStatic()) { 13575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu param++; // 0th argument must skip return value at start of the shorty 13675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else if (param == 0) { 13775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu return false; // this argument 13875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 13975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu return shorty_[param] == 'D'; 14075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 14175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsParamALong(unsigned int param) const { 14275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu DCHECK_LT(param, NumArgs()); 14375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu if (IsStatic()) { 14475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu param++; // 0th argument must skip return value at start of the shorty 14575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else if (param == 0) { 1463e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell return false; // this argument 14775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 14875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu return shorty_[param] == 'J'; 14975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 150169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers bool IsParamAReference(unsigned int param) const { 151169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers DCHECK_LT(param, NumArgs()); 152169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers if (IsStatic()) { 153169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers param++; // 0th argument must skip return value at start of the shorty 154169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } else if (param == 0) { 155169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return true; // this argument 156169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 157169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return shorty_[param] == 'L'; 158169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 159169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t NumArgs() const { 160169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return num_args_; 161169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 162169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t NumLongOrDoubleArgs() const { 163169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return num_long_or_double_args_; 164169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 165fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko size_t NumFloatOrDoubleArgs() const { 166fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko return num_float_or_double_args_; 167fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko } 168169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t NumReferenceArgs() const { 169169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return num_ref_args_; 170169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 171169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t ParamSize(unsigned int param) const { 172169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers DCHECK_LT(param, NumArgs()); 173169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers if (IsStatic()) { 174169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers param++; // 0th argument must skip return value at start of the shorty 175169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } else if (param == 0) { 176e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier return sizeof(mirror::HeapReference<mirror::Object>); // this argument 177169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 178169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t result = Primitive::ComponentSize(Primitive::GetType(shorty_[param])); 179169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers if (result >= 1 && result < 4) { 180169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers result = 4; 181169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 182169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return result; 183169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 184169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers const char* GetShorty() const { 185169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return shorty_.c_str(); 186169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 1875381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao // The slot number for current calling_convention argument. 1885381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao // Note that each slot is 32-bit. When the current argument is bigger 1895381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao // than 32 bits, return the first slot number for this argument. 1905381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao unsigned int itr_slots_; 191790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // The number of references iterated past. 1927a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers unsigned int itr_refs_; 193790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // The argument number along argument list for current argument. 1945381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao unsigned int itr_args_; 195790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // Number of longs and doubles seen along argument list. 196b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers unsigned int itr_longs_and_doubles_; 197790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // Number of float and doubles seen along argument list. 198fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko unsigned int itr_float_and_doubles_; 199790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // Space for frames below this on the stack. 200b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers FrameOffset displacement_; 201e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier // The size of a pointer. 202790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers const size_t frame_pointer_size_; 203eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // The size of a reference entry within the handle scope. 204eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier const size_t handle_scope_pointer_size_; 205b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 206b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers private: 207169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers const bool is_static_; 208169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers const bool is_synchronized_; 209169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers std::string shorty_; 210169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t num_args_; 211169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t num_ref_args_; 212fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko size_t num_float_or_double_args_; 213169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t num_long_or_double_args_; 214b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}; 215b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 216b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Abstraction for managed code's calling conventions 217bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Incoming stack args } | 218bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Prior Method* } | <-- Prior SP 219bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Return address } | 220bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Callee saves } | 221bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Spills ... } | 222bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Outgoing stack args } | 223bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Method* } | <-- SP 224b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersclass ManagedRuntimeCallingConvention : public CallingConvention { 225b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers public: 226d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko static std::unique_ptr<ManagedRuntimeCallingConvention> Create(ArenaAllocator* arena, 227d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko bool is_static, 228d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko bool is_synchronized, 229d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko const char* shorty, 230d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko InstructionSet instruction_set); 231b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 2322c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers // Register that holds the incoming method argument 2332c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ManagedRegister MethodRegister() = 0; 2342c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 235b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Iterator interface 236b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers bool HasNext(); 237b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers void Next(); 238b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers bool IsCurrentParamAReference(); 239fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko bool IsCurrentParamAFloatOrDouble(); 24075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsCurrentParamADouble(); 24175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsCurrentParamALong(); 2427a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers bool IsCurrentArgExplicit(); // ie a non-implict argument such as this 2437a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers bool IsCurrentArgPossiblyNull(); 244df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers size_t CurrentParamSize(); 2452c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual bool IsCurrentParamInRegister() = 0; 2462c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual bool IsCurrentParamOnStack() = 0; 2472c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ManagedRegister CurrentParamRegister() = 0; 2482c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual FrameOffset CurrentParamStackOffset() = 0; 249b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 2502c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ~ManagedRuntimeCallingConvention() {} 2512c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 252b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers // Registers to spill to caller's out registers on entry. 253fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko virtual const ManagedRegisterEntrySpills& EntrySpills() = 0; 254b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers 2552c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers protected: 256d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko ManagedRuntimeCallingConvention(bool is_static, 257d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko bool is_synchronized, 258d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko const char* shorty, 259790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers size_t frame_pointer_size) 260790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers : CallingConvention(is_static, is_synchronized, shorty, frame_pointer_size) {} 261b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}; 262b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 263b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Abstraction for JNI calling conventions 264bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Incoming stack args } | <-- Prior SP 265bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Return address } | 266bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Callee saves } | ([1]) 267bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Return value spill } | (live on return slow paths) 268dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers// | { Local Ref. Table State } | 269bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Stack Indirect Ref. Table | 270bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | num. refs./link } | (here to prior SP is frame size) 271bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Method* } | <-- Anchor SP written to thread 272bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Outgoing stack args } | <-- SP at point of call 273bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | Native frame | 274bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// 275bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// [1] We must save all callee saves here to enable any exception throws to restore 276bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// callee saves for frames above this one. 277b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersclass JniCallingConvention : public CallingConvention { 278b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers public: 279d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko static std::unique_ptr<JniCallingConvention> Create(ArenaAllocator* arena, 280d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko bool is_static, 281d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko bool is_synchronized, 282d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko const char* shorty, 283d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko InstructionSet instruction_set); 284b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 285b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Size of frame excluding space for outgoing args (its assumed Method* is 286b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // always at the bottom of a frame, but this doesn't work for outgoing 287b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // native args). Includes alignment. 2882c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual size_t FrameSize() = 0; 289b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Size of outgoing arguments, including alignment 2902c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual size_t OutArgSize() = 0; 291408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // Number of references in stack indirect reference table 292dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers size_t ReferenceCount() const; 293dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers // Location where the segment state of the local indirect reference table is saved 2945a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers FrameOffset SavedLocalReferenceCookieOffset() const; 295df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers // Location where the return value of a call can be squirreled if another 296df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers // call is made following the native call 297dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers FrameOffset ReturnValueSaveLocation() const; 29800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Register that holds result if it is integer. 29900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers virtual ManagedRegister IntReturnRegister() = 0; 300d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe // Whether the compiler needs to ensure zero-/sign-extension of a small result type 301d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe virtual bool RequiresSmallResultTypeExtension() const = 0; 302b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 303bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // Callee save registers to spill prior to native code (which may clobber) 304bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers virtual const std::vector<ManagedRegister>& CalleeSaveRegisters() const = 0; 305bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 306bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // Spill mask values 307bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers virtual uint32_t CoreSpillMask() const = 0; 308bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers virtual uint32_t FpSpillMask() const = 0; 3090d666d8769714dcbc2acc4dd5b06f0deffa6e0a1Ian Rogers 310dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers // An extra scratch register live after the call 311dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers virtual ManagedRegister ReturnScratchRegister() const = 0; 312dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers 313b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Iterator interface 314b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers bool HasNext(); 31567375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers virtual void Next(); 316b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers bool IsCurrentParamAReference(); 317fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko bool IsCurrentParamAFloatOrDouble(); 31875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsCurrentParamADouble(); 31975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsCurrentParamALong(); 32075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsCurrentParamJniEnv(); 321df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers size_t CurrentParamSize(); 3222c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual bool IsCurrentParamInRegister() = 0; 3232c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual bool IsCurrentParamOnStack() = 0; 3242c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ManagedRegister CurrentParamRegister() = 0; 3252c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual FrameOffset CurrentParamStackOffset() = 0; 326b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 327b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Iterator interface extension for JNI 328eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset CurrentParamHandleScopeEntryOffset(); 329b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 330eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // Position of handle scope and interior fields 331eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset HandleScopeOffset() const { 332e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier return FrameOffset(this->displacement_.Int32Value() + frame_pointer_size_); 333cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe // above Method reference 334b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 335fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko 336eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset HandleScopeLinkOffset() const { 337e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier return FrameOffset(HandleScopeOffset().Int32Value() + 338e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier HandleScope::LinkOffset(frame_pointer_size_)); 339fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko } 340fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko 341eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset HandleScopeNumRefsOffset() const { 342eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier return FrameOffset(HandleScopeOffset().Int32Value() + 343eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier HandleScope::NumberOfReferencesOffset(frame_pointer_size_)); 344b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 345fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko 346e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier FrameOffset HandleReferencesOffset() const { 347eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier return FrameOffset(HandleScopeOffset().Int32Value() + 348eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier HandleScope::ReferencesOffset(frame_pointer_size_)); 349b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 350b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 3512c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ~JniCallingConvention() {} 3522c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 3532c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers protected: 354b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Named iterator positions 355b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers enum IteratorPos { 356b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers kJniEnv = 0, 357b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers kObjectOrClass = 1 358b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers }; 359b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 3603887c468d731420e929e6ad3acf190d5431e94fcRoland Levillain JniCallingConvention(bool is_static, bool is_synchronized, const char* shorty, 3613887c468d731420e929e6ad3acf190d5431e94fcRoland Levillain size_t frame_pointer_size) 362790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers : CallingConvention(is_static, is_synchronized, shorty, frame_pointer_size) {} 3632c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 364eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // Number of stack slots for outgoing arguments, above which the handle scope is 365b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // located 3662c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual size_t NumberOfOutgoingStackArgs() = 0; 367b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 3682c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers protected: 369169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t NumberOfExtraArgumentsForJni(); 370b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}; 371b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 372b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} // namespace art 373b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 374fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#endif // ART_COMPILER_JNI_QUICK_CALLING_CONVENTION_H_ 375