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