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> 21eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier#include "handle_scope.h" 22e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "primitive.h" 23578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "thread.h" 24166db04e259ca51838c311891598664deeed85adIan Rogers#include "utils/managed_register.h" 25b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 26b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersnamespace art { 27b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 28790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers// Top-level abstraction for different calling conventions. 29b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersclass CallingConvention { 30b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers public: 31169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers bool IsReturnAReference() const { return shorty_[0] == 'L'; } 32169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers 3358136caeec7cb677bb83c2eafd1f4bab5afd96c8jeffhao Primitive::Type GetReturnType() const { 3458136caeec7cb677bb83c2eafd1f4bab5afd96c8jeffhao return Primitive::GetType(shorty_[0]); 3558136caeec7cb677bb83c2eafd1f4bab5afd96c8jeffhao } 3658136caeec7cb677bb83c2eafd1f4bab5afd96c8jeffhao 37169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t SizeOfReturnValue() const { 38169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t result = Primitive::ComponentSize(Primitive::GetType(shorty_[0])); 39169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers if (result >= 1 && result < 4) { 40169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers result = 4; 41169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 42169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return result; 43169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 44df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers 4500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Register that holds result of this method invocation. 462c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ManagedRegister ReturnRegister() = 0; 4700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Register reserved for scratch usage during procedure calls. 482c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ManagedRegister InterproceduralScratchRegister() = 0; 49668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao 50790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // Offset of Method within the frame. 51790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers FrameOffset MethodStackOffset() { 52790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers return displacement_; 53790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers } 54e2d373e6e09c1df9a47e73a26254048adb31ce82Carl Shapiro 55b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Iterator interface 56b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 57b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Place iterator at start of arguments. The displacement is applied to 58b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // frame offset methods to account for frames which may be on the stack 59b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // below the one being iterated over. 60b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers void ResetIterator(FrameOffset displacement) { 61b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers displacement_ = displacement; 625381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao itr_slots_ = 0; 635381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao itr_args_ = 0; 64668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao itr_refs_ = 0; 65b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers itr_longs_and_doubles_ = 0; 66fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko itr_float_and_doubles_ = 0; 67b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 68b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 692c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ~CallingConvention() {} 702c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 71b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers protected: 72790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers CallingConvention(bool is_static, bool is_synchronized, const char* shorty, 73790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers size_t frame_pointer_size) 74790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers : itr_slots_(0), itr_refs_(0), itr_args_(0), itr_longs_and_doubles_(0), 75790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers itr_float_and_doubles_(0), displacement_(0), 76790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers frame_pointer_size_(frame_pointer_size), 77eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier handle_scope_pointer_size_(sizeof(StackReference<mirror::Object>)), 78790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers is_static_(is_static), is_synchronized_(is_synchronized), 79169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers shorty_(shorty) { 80169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers num_args_ = (is_static ? 0 : 1) + strlen(shorty) - 1; 81169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers num_ref_args_ = is_static ? 0 : 1; // The implicit this pointer. 82fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko num_float_or_double_args_ = 0; 83169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers num_long_or_double_args_ = 0; 84169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers for (size_t i = 1; i < strlen(shorty); i++) { 85169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers char ch = shorty_[i]; 86fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko switch (ch) { 87fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko case 'L': 88169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers num_ref_args_++; 89fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko break; 90fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko case 'J': 91169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers num_long_or_double_args_++; 92fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko break; 93fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko case 'D': 94fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko num_long_or_double_args_++; 95fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko num_float_or_double_args_++; 96fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko break; 97fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko case 'F': 98fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko num_float_or_double_args_++; 99fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko break; 100169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 101169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 102169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 1032c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 104169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers bool IsStatic() const { 105169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return is_static_; 106169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 107169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers bool IsSynchronized() const { 108169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return is_synchronized_; 109169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 110169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers bool IsParamALongOrDouble(unsigned int param) const { 111169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers DCHECK_LT(param, NumArgs()); 112169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers if (IsStatic()) { 113169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers param++; // 0th argument must skip return value at start of the shorty 114169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } else if (param == 0) { 115169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return false; // this argument 116169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 117169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers char ch = shorty_[param]; 118169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return (ch == 'J' || ch == 'D'); 119169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 120fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko bool IsParamAFloatOrDouble(unsigned int param) const { 121fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko DCHECK_LT(param, NumArgs()); 122fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko if (IsStatic()) { 123fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko param++; // 0th argument must skip return value at start of the shorty 124fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko } else if (param == 0) { 125fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko return false; // this argument 126fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko } 127fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko char ch = shorty_[param]; 128fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko return (ch == 'F' || ch == 'D'); 129fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko } 13075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsParamADouble(unsigned int param) const { 13175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu DCHECK_LT(param, NumArgs()); 13275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu if (IsStatic()) { 13375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu param++; // 0th argument must skip return value at start of the shorty 13475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else if (param == 0) { 13575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu return false; // this argument 13675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 13775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu return shorty_[param] == 'D'; 13875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 13975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsParamALong(unsigned int param) const { 14075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu DCHECK_LT(param, NumArgs()); 14175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu if (IsStatic()) { 14275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu param++; // 0th argument must skip return value at start of the shorty 14375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else if (param == 0) { 14475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu return true; // this argument 14575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 14675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu return shorty_[param] == 'J'; 14775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 148169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers bool IsParamAReference(unsigned int param) const { 149169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers DCHECK_LT(param, NumArgs()); 150169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers if (IsStatic()) { 151169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers param++; // 0th argument must skip return value at start of the shorty 152169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } else if (param == 0) { 153169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return true; // this argument 154169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 155169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return shorty_[param] == 'L'; 156169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 157169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t NumArgs() const { 158169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return num_args_; 159169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 160169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t NumLongOrDoubleArgs() const { 161169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return num_long_or_double_args_; 162169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 163fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko size_t NumFloatOrDoubleArgs() const { 164fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko return num_float_or_double_args_; 165fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko } 166169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t NumReferenceArgs() const { 167169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return num_ref_args_; 168169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 169169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t ParamSize(unsigned int param) const { 170169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers DCHECK_LT(param, NumArgs()); 171169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers if (IsStatic()) { 172169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers param++; // 0th argument must skip return value at start of the shorty 173169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } else if (param == 0) { 174790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers return frame_pointer_size_; // this argument 175169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 176169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t result = Primitive::ComponentSize(Primitive::GetType(shorty_[param])); 177169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers if (result >= 1 && result < 4) { 178169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers result = 4; 179169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 180169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return result; 181169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 182169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers const char* GetShorty() const { 183169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return shorty_.c_str(); 184169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 1855381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao // The slot number for current calling_convention argument. 1865381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao // Note that each slot is 32-bit. When the current argument is bigger 1875381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao // than 32 bits, return the first slot number for this argument. 1885381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao unsigned int itr_slots_; 189790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // The number of references iterated past. 1907a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers unsigned int itr_refs_; 191790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // The argument number along argument list for current argument. 1925381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao unsigned int itr_args_; 193790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // Number of longs and doubles seen along argument list. 194b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers unsigned int itr_longs_and_doubles_; 195790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // Number of float and doubles seen along argument list. 196fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko unsigned int itr_float_and_doubles_; 197790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // Space for frames below this on the stack. 198b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers FrameOffset displacement_; 199790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // The size of a reference. 200790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers const size_t frame_pointer_size_; 201eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // The size of a reference entry within the handle scope. 202eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier const size_t handle_scope_pointer_size_; 203b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 204b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers private: 205169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers const bool is_static_; 206169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers const bool is_synchronized_; 207169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers std::string shorty_; 208169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t num_args_; 209169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t num_ref_args_; 210fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko size_t num_float_or_double_args_; 211169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t num_long_or_double_args_; 212b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}; 213b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 214b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Abstraction for managed code's calling conventions 215bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Incoming stack args } | 216bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Prior Method* } | <-- Prior SP 217bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Return address } | 218bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Callee saves } | 219bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Spills ... } | 220bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Outgoing stack args } | 221bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Method* } | <-- SP 222b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersclass ManagedRuntimeCallingConvention : public CallingConvention { 223b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers public: 224169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers static ManagedRuntimeCallingConvention* Create(bool is_static, bool is_synchronized, 225169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers const char* shorty, 2263320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom InstructionSet instruction_set); 227b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 2282c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers // Register that holds the incoming method argument 2292c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ManagedRegister MethodRegister() = 0; 2302c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 231b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Iterator interface 232b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers bool HasNext(); 233b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers void Next(); 234b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers bool IsCurrentParamAReference(); 235fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko bool IsCurrentParamAFloatOrDouble(); 23675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsCurrentParamADouble(); 23775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsCurrentParamALong(); 2387a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers bool IsCurrentArgExplicit(); // ie a non-implict argument such as this 2397a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers bool IsCurrentArgPossiblyNull(); 240df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers size_t CurrentParamSize(); 2412c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual bool IsCurrentParamInRegister() = 0; 2422c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual bool IsCurrentParamOnStack() = 0; 2432c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ManagedRegister CurrentParamRegister() = 0; 2442c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual FrameOffset CurrentParamStackOffset() = 0; 245b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 2462c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ~ManagedRuntimeCallingConvention() {} 2472c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 248b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers // Registers to spill to caller's out registers on entry. 249fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko virtual const ManagedRegisterEntrySpills& EntrySpills() = 0; 250b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers 2512c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers protected: 252790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers ManagedRuntimeCallingConvention(bool is_static, bool is_synchronized, const char* shorty, 253790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers size_t frame_pointer_size) 254790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers : CallingConvention(is_static, is_synchronized, shorty, frame_pointer_size) {} 255b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}; 256b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 257b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Abstraction for JNI calling conventions 258bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Incoming stack args } | <-- Prior SP 259bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Return address } | 260bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Callee saves } | ([1]) 261bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Return value spill } | (live on return slow paths) 262dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers// | { Local Ref. Table State } | 263bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Stack Indirect Ref. Table | 264bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | num. refs./link } | (here to prior SP is frame size) 265bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Method* } | <-- Anchor SP written to thread 266bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Outgoing stack args } | <-- SP at point of call 267bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | Native frame | 268bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// 269bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// [1] We must save all callee saves here to enable any exception throws to restore 270bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// callee saves for frames above this one. 271b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersclass JniCallingConvention : public CallingConvention { 272b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers public: 273169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers static JniCallingConvention* Create(bool is_static, bool is_synchronized, const char* shorty, 2742c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers InstructionSet instruction_set); 275b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 276b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Size of frame excluding space for outgoing args (its assumed Method* is 277b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // always at the bottom of a frame, but this doesn't work for outgoing 278b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // native args). Includes alignment. 2792c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual size_t FrameSize() = 0; 280b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Size of outgoing arguments, including alignment 2812c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual size_t OutArgSize() = 0; 282408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // Number of references in stack indirect reference table 283dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers size_t ReferenceCount() const; 284dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers // Location where the segment state of the local indirect reference table is saved 2855a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers FrameOffset SavedLocalReferenceCookieOffset() const; 286df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers // Location where the return value of a call can be squirreled if another 287df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers // call is made following the native call 288dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers FrameOffset ReturnValueSaveLocation() const; 28900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Register that holds result if it is integer. 29000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers virtual ManagedRegister IntReturnRegister() = 0; 291d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe // Whether the compiler needs to ensure zero-/sign-extension of a small result type 292d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe virtual bool RequiresSmallResultTypeExtension() const = 0; 293b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 294bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // Callee save registers to spill prior to native code (which may clobber) 295bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers virtual const std::vector<ManagedRegister>& CalleeSaveRegisters() const = 0; 296bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 297bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // Spill mask values 298bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers virtual uint32_t CoreSpillMask() const = 0; 299bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers virtual uint32_t FpSpillMask() const = 0; 3000d666d8769714dcbc2acc4dd5b06f0deffa6e0a1Ian Rogers 301dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers // An extra scratch register live after the call 302dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers virtual ManagedRegister ReturnScratchRegister() const = 0; 303dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers 304b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Iterator interface 305b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers bool HasNext(); 30667375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers virtual void Next(); 307b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers bool IsCurrentParamAReference(); 308fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko bool IsCurrentParamAFloatOrDouble(); 30975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsCurrentParamADouble(); 31075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsCurrentParamALong(); 31175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsCurrentParamJniEnv(); 312df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers size_t CurrentParamSize(); 3132c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual bool IsCurrentParamInRegister() = 0; 3142c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual bool IsCurrentParamOnStack() = 0; 3152c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ManagedRegister CurrentParamRegister() = 0; 3162c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual FrameOffset CurrentParamStackOffset() = 0; 317b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 318b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Iterator interface extension for JNI 319eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset CurrentParamHandleScopeEntryOffset(); 320b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 321eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // Position of handle scope and interior fields 322eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset HandleScopeOffset() const { 323cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe return FrameOffset(this->displacement_.Int32Value() + sizeof(StackReference<mirror::ArtMethod>)); 324cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe // above Method reference 325b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 326fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko 327eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset HandleScopeLinkOffset() const { 328eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier return FrameOffset(HandleScopeOffset().Int32Value() + HandleScope::LinkOffset(frame_pointer_size_)); 329fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko } 330fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko 331eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset HandleScopeNumRefsOffset() const { 332eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier return FrameOffset(HandleScopeOffset().Int32Value() + 333eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier HandleScope::NumberOfReferencesOffset(frame_pointer_size_)); 334b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 335fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko 336eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset HandleerencesOffset() const { 337eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier return FrameOffset(HandleScopeOffset().Int32Value() + 338eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier HandleScope::ReferencesOffset(frame_pointer_size_)); 339b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 340b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 3412c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ~JniCallingConvention() {} 3422c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 3432c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers protected: 344b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Named iterator positions 345b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers enum IteratorPos { 346b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers kJniEnv = 0, 347b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers kObjectOrClass = 1 348b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers }; 349b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 350790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers explicit JniCallingConvention(bool is_static, bool is_synchronized, const char* shorty, 351790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers size_t frame_pointer_size) 352790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers : CallingConvention(is_static, is_synchronized, shorty, frame_pointer_size) {} 3532c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 354eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // Number of stack slots for outgoing arguments, above which the handle scope is 355b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // located 3562c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual size_t NumberOfOutgoingStackArgs() = 0; 357b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 3582c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers protected: 359169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t NumberOfExtraArgumentsForJni(); 360b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}; 361b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 362b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} // namespace art 363b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 364fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#endif // ART_COMPILER_JNI_QUICK_CALLING_CONVENTION_H_ 365