calling_convention.h revision df20fe0c097073f75f22d16e72fd3636a31d3ca1
1b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Copyright 2011 Google Inc. All Rights Reserved.
2b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Author: irogers@google.com (Ian Rogers)
3b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
4b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#ifndef ART_SRC_CALLING_CONVENTION_H_
5b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#define ART_SRC_CALLING_CONVENTION_H_
6b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
7b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include "src/managed_register.h"
8b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include "src/object.h"
9b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include "src/thread.h"
10b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
11b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersnamespace art {
12b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
13b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Top-level abstraction for different calling conventions
14b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersclass CallingConvention {
15b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers public:
16b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  CallingConvention* GetCallingConvention(Method* method);
17b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
18b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  bool IsReturnAReference() const { return method_->IsReturnAReference(); }
19b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
20df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  size_t SizeOfReturnValue() const { return method_->ReturnSize(); }
21df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers
22b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Register that holds the incoming method argument
23b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  ManagedRegister MethodRegister();
24b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Register that holds result of this method
25b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  ManagedRegister ReturnRegister();
26b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Register reserved for scratch usage during procedure calls
27b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  ManagedRegister InterproceduralScratchRegister();
28b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
29b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Iterator interface
30b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
31b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Place iterator at start of arguments. The displacement is applied to
32b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // frame offset methods to account for frames which may be on the stack
33b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // below the one being iterated over.
34b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  void ResetIterator(FrameOffset displacement) {
35b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    displacement_ = displacement;
36b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    itr_position_ = 0;
37b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    itr_longs_and_doubles_ = 0;
38b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
39b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
40b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers protected:
41b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  explicit CallingConvention(Method* method) : displacement_(0),
42b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers                                               method_(method) {}
43b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  const Method* GetMethod() const { return method_; }
44b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
45b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // position along argument list
46b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  unsigned int itr_position_;
47b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // number of longs and doubles seen along argument list
48b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  unsigned int itr_longs_and_doubles_;
49b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Space for frames below this on the stack
50b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  FrameOffset displacement_;
51b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
52b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers private:
53b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  const Method* method_;
54b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers};
55b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
56b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Abstraction for managed code's calling conventions
57b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersclass ManagedRuntimeCallingConvention : public CallingConvention {
58b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers public:
59b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  explicit ManagedRuntimeCallingConvention(Method* method) :
60b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers                                          CallingConvention(method) {}
61b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
62b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  size_t FrameSize();
63b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
64b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Iterator interface
65b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  bool HasNext();
66b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  void Next();
67b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  bool IsCurrentParamAReference();
68b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  bool IsCurrentParamInRegister();
69b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  bool IsCurrentParamOnStack();
70b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  bool IsCurrentParamPossiblyNull();
71df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  size_t CurrentParamSize();
72b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  ManagedRegister CurrentParamRegister();
73b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  FrameOffset CurrentParamStackOffset();
74b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
75b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  DISALLOW_COPY_AND_ASSIGN(ManagedRuntimeCallingConvention);
76b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers};
77b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
78b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Abstraction for JNI calling conventions
79b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// | incoming stack args    | <-- Prior SP
80b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// | { Spilled registers    |
81b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// |   & return address }   |
82df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers// | { Return value spill } |     (live on return slow paths)
83b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// | { Stack Handle Block   |
84b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// |   ...                  |
85df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers// |   num. refs./link }    |     (here to prior SP is frame size)
86b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// | Method*                | <-- Anchor SP written to thread
87b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// | { Outgoing stack args  |
88b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// |   ... }                | <-- SP at point of call
89b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// | Native frame           |
90b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersclass JniCallingConvention : public CallingConvention {
91b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers public:
92b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  explicit JniCallingConvention(Method* native_method) :
93b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers                      CallingConvention(native_method) {}
94b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
95b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Size of frame excluding space for outgoing args (its assumed Method* is
96b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // always at the bottom of a frame, but this doesn't work for outgoing
97b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // native args). Includes alignment.
98b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  size_t FrameSize();
99b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Size of outgoing arguments, including alignment
100b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  size_t OutArgSize();
101b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Number of handles in stack handle block
102b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  size_t HandleCount();
103df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  // Location where the return value of a call can be squirreled if another
104df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  // call is made following the native call
105df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  FrameOffset ReturnValueSaveLocation();
106b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
107b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Iterator interface
108b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  bool HasNext();
109b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  void Next();
110b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  bool IsCurrentParamAReference();
111b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  bool IsCurrentParamInRegister();
112b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  bool IsCurrentParamOnStack();
113df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers  size_t CurrentParamSize();
114b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  ManagedRegister CurrentParamRegister();
115b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  FrameOffset CurrentParamStackOffset();
116b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
117b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Iterator interface extension for JNI
118b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  FrameOffset CurrentParamHandleOffset();
119b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
120b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Position of stack handle block and interior fields
121b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  FrameOffset ShbOffset() {
122b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return FrameOffset(displacement_.Int32Value() +
123b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers                       kPointerSize);  // above Method*
124b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
125b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  FrameOffset ShbNumRefsOffset() {
126b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return FrameOffset(ShbOffset().Int32Value() +
127b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers                       StackHandleBlock::NumberOfReferencesOffset());
128b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
129b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  FrameOffset ShbLinkOffset() {
130b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return FrameOffset(ShbOffset().Int32Value() +
131b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers                       StackHandleBlock::LinkOffset());
132b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
133b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
134b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers private:
135b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Named iterator positions
136b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  enum IteratorPos {
137b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    kJniEnv = 0,
138b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    kObjectOrClass = 1
139b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  };
140b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
141b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // Number of stack slots for outgoing arguments, above which handles are
142b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  // located
143b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  size_t NumberOfOutgoingStackArgs();
144b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
145b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  DISALLOW_COPY_AND_ASSIGN(JniCallingConvention);
146b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers};
147b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
148b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}  // namespace art
149b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
150b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#endif  // ART_SRC_CALLING_CONVENTION_H_
151