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