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