blob: 0d3f9f186186900f6e2436fae3bc0792fe6654c5 [file] [log] [blame]
Narayan Kamath9823e782016-08-03 12:46:58 +01001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_RUNTIME_METHOD_HANDLES_H_
18#define ART_RUNTIME_METHOD_HANDLES_H_
19
20#include <ostream>
21
Narayan Kamath208f8572016-08-03 12:46:58 +010022#include "dex_instruction.h"
23#include "jvalue.h"
24
Narayan Kamath9823e782016-08-03 12:46:58 +010025namespace art {
26
Narayan Kamath208f8572016-08-03 12:46:58 +010027namespace mirror {
28 class MethodType;
29}
30
31class ShadowFrame;
32
Narayan Kamath9823e782016-08-03 12:46:58 +010033// Defines the behaviour of a given method handle. The behaviour
34// of a handle of a given kind is identical to the dex bytecode behaviour
35// of the equivalent instruction.
36//
37// NOTE: These must be kept in sync with the constants defined in
38// java.lang.invoke.MethodHandle.
39enum MethodHandleKind {
40 kInvokeVirtual = 0,
41 kInvokeSuper,
42 kInvokeDirect,
43 kInvokeStatic,
44 kInvokeInterface,
Narayan Kamathc3b7f1a2016-10-19 11:05:04 +010045 kInvokeTransform,
Narayan Kamath9823e782016-08-03 12:46:58 +010046 kInstanceGet,
47 kInstancePut,
48 kStaticGet,
49 kStaticPut,
50 kLastValidKind = kStaticPut,
Narayan Kamathc3b7f1a2016-10-19 11:05:04 +010051 kLastInvokeKind = kInvokeTransform
Narayan Kamath9823e782016-08-03 12:46:58 +010052};
53
54// Whether the given method handle kind is some variant of an invoke.
55inline bool IsInvoke(const MethodHandleKind handle_kind) {
56 return handle_kind <= kLastInvokeKind;
57}
58
Narayan Kamathda246502016-10-20 18:39:22 +010059// Performs a single argument conversion from type |from| to a distinct
60// type |to|. Returns true on success, false otherwise.
61REQUIRES_SHARED(Locks::mutator_lock_)
Narayan Kamath000e1882016-10-24 17:14:25 +010062inline bool ConvertJValue(Handle<mirror::Class> from,
63 Handle<mirror::Class> to,
64 const JValue& from_value,
65 JValue* to_value) ALWAYS_INLINE;
Narayan Kamathda246502016-10-20 18:39:22 +010066
Narayan Kamath208f8572016-08-03 12:46:58 +010067// Perform argument conversions between |callsite_type| (the type of the
68// incoming arguments) and |callee_type| (the type of the method being
69// invoked). These include widening and narrowing conversions as well as
70// boxing and unboxing. Returns true on success, on false on failure. A
71// pending exception will always be set on failure.
Narayan Kamath000e1882016-10-24 17:14:25 +010072//
73// The values to be converted are read from an input source (of type G)
74// that provides three methods :
75//
76// class G {
77// // Used to read the next boolean/short/int or float value from the
78// // source.
79// uint32_t Get();
80//
81// // Used to the read the next reference value from the source.
82// ObjPtr<mirror::Object> GetReference();
83//
84// // Used to read the next double or long value from the source.
85// int64_t GetLong();
86// }
87//
88// After conversion, the values are written to an output sink (of type S)
89// that provides three methods :
90//
91// class S {
92// void Set(uint32_t);
93// void SetReference(ObjPtr<mirror::Object>)
94// void SetLong(int64_t);
95// }
96//
97// The semantics and usage of the Set methods are analagous to the getter
98// class.
99//
100// This method is instantiated in three different scenarions :
101// - <S = ShadowFrameSetter, G = ShadowFrameGetter> : copying from shadow
102// frame to shadow frame, used in a regular polymorphic non-exact invoke.
103// - <S = EmulatedShadowFrameAccessor, G = ShadowFrameGetter> : entering into
104// a transformer method from a polymorphic invoke.
105// - <S = ShadowFrameStter, G = EmulatedStackFrameAccessor> : entering into
106// a regular poly morphic invoke from a transformer method.
107//
108// TODO(narayan): If we find that the instantiations of this function take
109// up too much space, we can make G / S abstract base classes that are
110// overridden by concrete classes.
111template <typename G, typename S>
112REQUIRES_SHARED(Locks::mutator_lock_)
113bool PerformConversions(Thread* self,
114 Handle<mirror::ObjectArray<mirror::Class>> from_types,
115 Handle<mirror::ObjectArray<mirror::Class>> to_types,
116 G* getter,
117 S* setter,
118 int32_t num_conversions);
119
120// A convenience wrapper around |PerformConversions|, for the case where
121// the setter and getter are both ShadowFrame based.
Narayan Kamath208f8572016-08-03 12:46:58 +0100122template <bool is_range> REQUIRES_SHARED(Locks::mutator_lock_)
Narayan Kamathc3b7f1a2016-10-19 11:05:04 +0100123bool ConvertAndCopyArgumentsFromCallerFrame(Thread* self,
124 Handle<mirror::MethodType> callsite_type,
125 Handle<mirror::MethodType> callee_type,
126 const ShadowFrame& caller_frame,
127 uint32_t first_src_reg,
128 uint32_t first_dest_reg,
129 const uint32_t (&arg)[Instruction::kMaxVarArgRegs],
130 ShadowFrame* callee_frame);
131
Narayan Kamath000e1882016-10-24 17:14:25 +0100132// A convenience class that allows for iteration through a list of
133// input argument registers |arg| for non-range invokes or a list of
134// consecutive registers starting with a given based for range
135// invokes.
136//
137// This is used to iterate over input arguments while performing standard
138// argument conversions.
139template <bool is_range> class ShadowFrameGetter {
140 public:
141 ShadowFrameGetter(size_t first_src_reg,
142 const uint32_t (&arg)[Instruction::kMaxVarArgRegs],
143 const ShadowFrame& shadow_frame) :
144 first_src_reg_(first_src_reg),
145 arg_(arg),
146 shadow_frame_(shadow_frame),
147 arg_index_(0) {
148 }
Narayan Kamathc3b7f1a2016-10-19 11:05:04 +0100149
Narayan Kamath000e1882016-10-24 17:14:25 +0100150 ALWAYS_INLINE uint32_t Get() REQUIRES_SHARED(Locks::mutator_lock_) {
151 const uint32_t next = (is_range ? first_src_reg_ + arg_index_ : arg_[arg_index_]);
152 ++arg_index_;
153
154 return shadow_frame_.GetVReg(next);
155 }
156
157 ALWAYS_INLINE int64_t GetLong() REQUIRES_SHARED(Locks::mutator_lock_) {
158 const uint32_t next = (is_range ? first_src_reg_ + arg_index_ : arg_[arg_index_]);
159 arg_index_ += 2;
160
161 return shadow_frame_.GetVRegLong(next);
162 }
163
164 ALWAYS_INLINE ObjPtr<mirror::Object> GetReference() REQUIRES_SHARED(Locks::mutator_lock_) {
165 const uint32_t next = (is_range ? first_src_reg_ + arg_index_ : arg_[arg_index_]);
166 ++arg_index_;
167
168 return shadow_frame_.GetVRegReference(next);
169 }
170
171 private:
172 const size_t first_src_reg_;
173 const uint32_t (&arg_)[Instruction::kMaxVarArgRegs];
174 const ShadowFrame& shadow_frame_;
175 size_t arg_index_;
176};
177
178// A convenience class that allows values to be written to a given shadow frame,
179// starting at location |first_dst_reg|.
180class ShadowFrameSetter {
181 public:
182 ShadowFrameSetter(ShadowFrame* shadow_frame,
183 size_t first_dst_reg) :
184 shadow_frame_(shadow_frame),
185 arg_index_(first_dst_reg) {
186 }
187
188 ALWAYS_INLINE void Set(uint32_t value) REQUIRES_SHARED(Locks::mutator_lock_) {
189 shadow_frame_->SetVReg(arg_index_++, value);
190 }
191
192 ALWAYS_INLINE void SetReference(ObjPtr<mirror::Object> value)
193 REQUIRES_SHARED(Locks::mutator_lock_) {
194 shadow_frame_->SetVRegReference(arg_index_++, value.Ptr());
195 }
196
197 ALWAYS_INLINE void SetLong(int64_t value) REQUIRES_SHARED(Locks::mutator_lock_) {
198 shadow_frame_->SetVRegLong(arg_index_, value);
199 arg_index_ += 2;
200 }
201
202 private:
203 ShadowFrame* shadow_frame_;
204 size_t arg_index_;
205};
Narayan Kamath208f8572016-08-03 12:46:58 +0100206
Narayan Kamath9823e782016-08-03 12:46:58 +0100207} // namespace art
208
209#endif // ART_RUNTIME_METHOD_HANDLES_H_