calling_convention.h revision eb8167a4f4d27fce0530f6724ab8032610cd146b
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" 22578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "thread.h" 23166db04e259ca51838c311891598664deeed85adIan Rogers#include "utils/managed_register.h" 24b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 25b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersnamespace art { 26b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 27790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers// Top-level abstraction for different calling conventions. 28b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersclass CallingConvention { 29b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers public: 30169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers bool IsReturnAReference() const { return shorty_[0] == 'L'; } 31169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers 3258136caeec7cb677bb83c2eafd1f4bab5afd96c8jeffhao Primitive::Type GetReturnType() const { 3358136caeec7cb677bb83c2eafd1f4bab5afd96c8jeffhao return Primitive::GetType(shorty_[0]); 3458136caeec7cb677bb83c2eafd1f4bab5afd96c8jeffhao } 3558136caeec7cb677bb83c2eafd1f4bab5afd96c8jeffhao 36169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t SizeOfReturnValue() const { 37169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t result = Primitive::ComponentSize(Primitive::GetType(shorty_[0])); 38169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers if (result >= 1 && result < 4) { 39169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers result = 4; 40169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 41169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return result; 42169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 43df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers 4400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Register that holds result of this method invocation. 452c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ManagedRegister ReturnRegister() = 0; 4600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Register reserved for scratch usage during procedure calls. 472c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ManagedRegister InterproceduralScratchRegister() = 0; 48668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao 49790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // Offset of Method within the frame. 50790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers FrameOffset MethodStackOffset() { 51790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers return displacement_; 52790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers } 53e2d373e6e09c1df9a47e73a26254048adb31ce82Carl Shapiro 54b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Iterator interface 55b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 56b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Place iterator at start of arguments. The displacement is applied to 57b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // frame offset methods to account for frames which may be on the stack 58b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // below the one being iterated over. 59b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers void ResetIterator(FrameOffset displacement) { 60b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers displacement_ = displacement; 615381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao itr_slots_ = 0; 625381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao itr_args_ = 0; 63668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao itr_refs_ = 0; 64b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers itr_longs_and_doubles_ = 0; 65fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko itr_float_and_doubles_ = 0; 66b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 67b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 682c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ~CallingConvention() {} 692c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 70b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers protected: 71790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers CallingConvention(bool is_static, bool is_synchronized, const char* shorty, 72790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers size_t frame_pointer_size) 73790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers : itr_slots_(0), itr_refs_(0), itr_args_(0), itr_longs_and_doubles_(0), 74790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers itr_float_and_doubles_(0), displacement_(0), 75790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers frame_pointer_size_(frame_pointer_size), 76eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier handle_scope_pointer_size_(sizeof(StackReference<mirror::Object>)), 77790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers is_static_(is_static), is_synchronized_(is_synchronized), 78169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers shorty_(shorty) { 79169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers num_args_ = (is_static ? 0 : 1) + strlen(shorty) - 1; 80169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers num_ref_args_ = is_static ? 0 : 1; // The implicit this pointer. 81fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko num_float_or_double_args_ = 0; 82169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers num_long_or_double_args_ = 0; 83169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers for (size_t i = 1; i < strlen(shorty); i++) { 84169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers char ch = shorty_[i]; 85fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko switch (ch) { 86fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko case 'L': 87169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers num_ref_args_++; 88fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko break; 89fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko case 'J': 90169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers num_long_or_double_args_++; 91fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko break; 92fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko case 'D': 93fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko num_long_or_double_args_++; 94fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko num_float_or_double_args_++; 95fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko break; 96fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko case 'F': 97fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko num_float_or_double_args_++; 98fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko break; 99169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 100169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 101169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 1022c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 103169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers bool IsStatic() const { 104169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return is_static_; 105169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 106169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers bool IsSynchronized() const { 107169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return is_synchronized_; 108169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 109169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers bool IsParamALongOrDouble(unsigned int param) const { 110169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers DCHECK_LT(param, NumArgs()); 111169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers if (IsStatic()) { 112169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers param++; // 0th argument must skip return value at start of the shorty 113169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } else if (param == 0) { 114169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return false; // this argument 115169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 116169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers char ch = shorty_[param]; 117169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return (ch == 'J' || ch == 'D'); 118169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 119fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko bool IsParamAFloatOrDouble(unsigned int param) const { 120fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko DCHECK_LT(param, NumArgs()); 121fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko if (IsStatic()) { 122fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko param++; // 0th argument must skip return value at start of the shorty 123fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko } else if (param == 0) { 124fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko return false; // this argument 125fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko } 126fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko char ch = shorty_[param]; 127fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko return (ch == 'F' || ch == 'D'); 128fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko } 12975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsParamADouble(unsigned int param) const { 13075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu DCHECK_LT(param, NumArgs()); 13175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu if (IsStatic()) { 13275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu param++; // 0th argument must skip return value at start of the shorty 13375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else if (param == 0) { 13475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu return false; // this argument 13575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 13675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu return shorty_[param] == 'D'; 13775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 13875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsParamALong(unsigned int param) const { 13975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu DCHECK_LT(param, NumArgs()); 14075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu if (IsStatic()) { 14175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu param++; // 0th argument must skip return value at start of the shorty 14275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else if (param == 0) { 14375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu return true; // this argument 14475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 14575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu return shorty_[param] == 'J'; 14675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 147169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers bool IsParamAReference(unsigned int param) const { 148169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers DCHECK_LT(param, NumArgs()); 149169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers if (IsStatic()) { 150169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers param++; // 0th argument must skip return value at start of the shorty 151169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } else if (param == 0) { 152169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return true; // this argument 153169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 154169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return shorty_[param] == 'L'; 155169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 156169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t NumArgs() const { 157169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return num_args_; 158169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 159169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t NumLongOrDoubleArgs() const { 160169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return num_long_or_double_args_; 161169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 162fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko size_t NumFloatOrDoubleArgs() const { 163fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko return num_float_or_double_args_; 164fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko } 165169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t NumReferenceArgs() const { 166169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return num_ref_args_; 167169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 168169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t ParamSize(unsigned int param) const { 169169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers DCHECK_LT(param, NumArgs()); 170169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers if (IsStatic()) { 171169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers param++; // 0th argument must skip return value at start of the shorty 172169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } else if (param == 0) { 173790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers return frame_pointer_size_; // this argument 174169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 175169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t result = Primitive::ComponentSize(Primitive::GetType(shorty_[param])); 176169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers if (result >= 1 && result < 4) { 177169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers result = 4; 178169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 179169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return result; 180169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 181169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers const char* GetShorty() const { 182169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers return shorty_.c_str(); 183169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers } 1845381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao // The slot number for current calling_convention argument. 1855381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao // Note that each slot is 32-bit. When the current argument is bigger 1865381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao // than 32 bits, return the first slot number for this argument. 1875381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao unsigned int itr_slots_; 188790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // The number of references iterated past. 1897a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers unsigned int itr_refs_; 190790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // The argument number along argument list for current argument. 1915381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao unsigned int itr_args_; 192790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // Number of longs and doubles seen along argument list. 193b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers unsigned int itr_longs_and_doubles_; 194790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // Number of float and doubles seen along argument list. 195fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko unsigned int itr_float_and_doubles_; 196790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // Space for frames below this on the stack. 197b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers FrameOffset displacement_; 198790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers // The size of a reference. 199790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers const size_t frame_pointer_size_; 200eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // The size of a reference entry within the handle scope. 201eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier const size_t handle_scope_pointer_size_; 202b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 203b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers private: 204169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers const bool is_static_; 205169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers const bool is_synchronized_; 206169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers std::string shorty_; 207169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t num_args_; 208169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t num_ref_args_; 209fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko size_t num_float_or_double_args_; 210169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t num_long_or_double_args_; 211b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}; 212b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 213b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Abstraction for managed code's calling conventions 214bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Incoming stack args } | 215bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Prior Method* } | <-- Prior SP 216bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Return address } | 217bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Callee saves } | 218bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Spills ... } | 219bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Outgoing stack args } | 220bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Method* } | <-- SP 221b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersclass ManagedRuntimeCallingConvention : public CallingConvention { 222b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers public: 223169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers static ManagedRuntimeCallingConvention* Create(bool is_static, bool is_synchronized, 224169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers const char* shorty, 2253320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom InstructionSet instruction_set); 226b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 2272c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers // Register that holds the incoming method argument 2282c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ManagedRegister MethodRegister() = 0; 2292c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 230b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Iterator interface 231b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers bool HasNext(); 232b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers void Next(); 233b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers bool IsCurrentParamAReference(); 234fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko bool IsCurrentParamAFloatOrDouble(); 23575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsCurrentParamADouble(); 23675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsCurrentParamALong(); 2377a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers bool IsCurrentArgExplicit(); // ie a non-implict argument such as this 2387a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers bool IsCurrentArgPossiblyNull(); 239df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers size_t CurrentParamSize(); 2402c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual bool IsCurrentParamInRegister() = 0; 2412c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual bool IsCurrentParamOnStack() = 0; 2422c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ManagedRegister CurrentParamRegister() = 0; 2432c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual FrameOffset CurrentParamStackOffset() = 0; 244b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 2452c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ~ManagedRuntimeCallingConvention() {} 2462c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 247b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers // Registers to spill to caller's out registers on entry. 248fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko virtual const ManagedRegisterEntrySpills& EntrySpills() = 0; 249b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers 2502c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers protected: 251790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers ManagedRuntimeCallingConvention(bool is_static, bool is_synchronized, const char* shorty, 252790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers size_t frame_pointer_size) 253790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers : CallingConvention(is_static, is_synchronized, shorty, frame_pointer_size) {} 254b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}; 255b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 256b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Abstraction for JNI calling conventions 257bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Incoming stack args } | <-- Prior SP 258bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Return address } | 259bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Callee saves } | ([1]) 260bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Return value spill } | (live on return slow paths) 261dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers// | { Local Ref. Table State } | 262bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Stack Indirect Ref. Table | 263bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | num. refs./link } | (here to prior SP is frame size) 264bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Method* } | <-- Anchor SP written to thread 265bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | { Outgoing stack args } | <-- SP at point of call 266bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// | Native frame | 267bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// 268bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// [1] We must save all callee saves here to enable any exception throws to restore 269bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers// callee saves for frames above this one. 270b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersclass JniCallingConvention : public CallingConvention { 271b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers public: 272169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers static JniCallingConvention* Create(bool is_static, bool is_synchronized, const char* shorty, 2732c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers InstructionSet instruction_set); 274b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 275b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Size of frame excluding space for outgoing args (its assumed Method* is 276b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // always at the bottom of a frame, but this doesn't work for outgoing 277b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // native args). Includes alignment. 2782c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual size_t FrameSize() = 0; 279b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Size of outgoing arguments, including alignment 2802c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual size_t OutArgSize() = 0; 281408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // Number of references in stack indirect reference table 282dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers size_t ReferenceCount() const; 283dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers // Location where the segment state of the local indirect reference table is saved 2845a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers FrameOffset SavedLocalReferenceCookieOffset() const; 285df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers // Location where the return value of a call can be squirreled if another 286df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers // call is made following the native call 287dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers FrameOffset ReturnValueSaveLocation() const; 28800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Register that holds result if it is integer. 28900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers virtual ManagedRegister IntReturnRegister() = 0; 290d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe // Whether the compiler needs to ensure zero-/sign-extension of a small result type 291d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe virtual bool RequiresSmallResultTypeExtension() const = 0; 292b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 293bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // Callee save registers to spill prior to native code (which may clobber) 294bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers virtual const std::vector<ManagedRegister>& CalleeSaveRegisters() const = 0; 295bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers 296bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers // Spill mask values 297bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers virtual uint32_t CoreSpillMask() const = 0; 298bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers virtual uint32_t FpSpillMask() const = 0; 2990d666d8769714dcbc2acc4dd5b06f0deffa6e0a1Ian Rogers 300dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers // An extra scratch register live after the call 301dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers virtual ManagedRegister ReturnScratchRegister() const = 0; 302dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers 303b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Iterator interface 304b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers bool HasNext(); 30567375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers virtual void Next(); 306b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers bool IsCurrentParamAReference(); 307fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko bool IsCurrentParamAFloatOrDouble(); 30875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsCurrentParamADouble(); 30975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsCurrentParamALong(); 31075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu bool IsCurrentParamJniEnv(); 311df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers size_t CurrentParamSize(); 3122c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual bool IsCurrentParamInRegister() = 0; 3132c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual bool IsCurrentParamOnStack() = 0; 3142c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ManagedRegister CurrentParamRegister() = 0; 3152c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual FrameOffset CurrentParamStackOffset() = 0; 316b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 317b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Iterator interface extension for JNI 318eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset CurrentParamHandleScopeEntryOffset(); 319b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 320eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // Position of handle scope and interior fields 321eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset HandleScopeOffset() const { 322790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers return FrameOffset(this->displacement_.Int32Value() + frame_pointer_size_); // above Method* 323b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 324fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko 325eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset HandleScopeLinkOffset() const { 326eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier return FrameOffset(HandleScopeOffset().Int32Value() + HandleScope::LinkOffset(frame_pointer_size_)); 327fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko } 328fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko 329eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset HandleScopeNumRefsOffset() const { 330eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier return FrameOffset(HandleScopeOffset().Int32Value() + 331eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier HandleScope::NumberOfReferencesOffset(frame_pointer_size_)); 332b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 333fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko 334eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier FrameOffset HandleerencesOffset() const { 335eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier return FrameOffset(HandleScopeOffset().Int32Value() + 336eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier HandleScope::ReferencesOffset(frame_pointer_size_)); 337b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 338b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 3392c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual ~JniCallingConvention() {} 3402c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 3412c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers protected: 342b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Named iterator positions 343b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers enum IteratorPos { 344b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers kJniEnv = 0, 345b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers kObjectOrClass = 1 346b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers }; 347b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 348790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers explicit JniCallingConvention(bool is_static, bool is_synchronized, const char* shorty, 349790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers size_t frame_pointer_size) 350790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers : CallingConvention(is_static, is_synchronized, shorty, frame_pointer_size) {} 3512c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers 352eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // Number of stack slots for outgoing arguments, above which the handle scope is 353b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // located 3542c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers virtual size_t NumberOfOutgoingStackArgs() = 0; 355b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 3562c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers protected: 357169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers size_t NumberOfExtraArgumentsForJni(); 358b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}; 359b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 360b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} // namespace art 361b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 362fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#endif // ART_COMPILER_JNI_QUICK_CALLING_CONVENTION_H_ 363