blob: d4d0ca1034951ef62f8710ce97045b757505b410 [file] [log] [blame]
Ian Rogers57b86d42012-03-27 16:05:41 -07001/*
Elliott Hughes0f3c5532012-03-30 14:51:51 -07002 * Copyright (C) 2012 The Android Open Source Project
Ian Rogers57b86d42012-03-27 16:05:41 -07003 *
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
Ian Rogersaf6e67a2013-01-16 08:38:37 -080017#include "argument_visitor.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070018#include "dex_file-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080019#include "mirror/abstract_method-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080020#include "mirror/object_array-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070021#include "mirror/object-inl.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070022#include "object_utils.h"
23#include "reflection.h"
TDYa1275bb86012012-04-11 05:57:28 -070024#include "runtime_support.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070025#include "scoped_thread_state_change.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070026#include "thread.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070027#include "well_known_classes.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070028
29#include "ScopedLocalRef.h"
30
31namespace art {
32
Ian Rogersaf6e67a2013-01-16 08:38:37 -080033// Visits arguments on the stack placing them into the args vector, Object* arguments are converted
34// to jobjects.
Jeff Hao5fa60c32013-04-04 17:57:01 -070035class BuildPortableArgumentVisitor : public PortableArgumentVisitor {
Ian Rogersaf6e67a2013-01-16 08:38:37 -080036 public:
Jeff Hao5fa60c32013-04-04 17:57:01 -070037 BuildPortableArgumentVisitor(MethodHelper& caller_mh, mirror::AbstractMethod** sp,
38 ScopedObjectAccessUnchecked& soa, std::vector<jvalue>& args) :
39 PortableArgumentVisitor(caller_mh, sp), soa_(soa), args_(args) {}
40
41 virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
42 jvalue val;
43 Primitive::Type type = GetParamPrimitiveType();
44 switch (type) {
45 case Primitive::kPrimNot: {
46 mirror::Object* obj = *reinterpret_cast<mirror::Object**>(GetParamAddress());
47 val.l = soa_.AddLocalReference<jobject>(obj);
48 break;
49 }
50 case Primitive::kPrimLong: // Fall-through.
51 case Primitive::kPrimDouble:
52 val.j = *reinterpret_cast<jlong*>(GetParamAddress());
53 break;
54 case Primitive::kPrimBoolean: // Fall-through.
55 case Primitive::kPrimByte: // Fall-through.
56 case Primitive::kPrimChar: // Fall-through.
57 case Primitive::kPrimShort: // Fall-through.
58 case Primitive::kPrimInt: // Fall-through.
59 case Primitive::kPrimFloat:
60 val.i = *reinterpret_cast<jint*>(GetParamAddress());
61 break;
62 case Primitive::kPrimVoid:
63 LOG(FATAL) << "UNREACHABLE";
64 val.j = 0;
65 break;
66 }
67 args_.push_back(val);
68 }
69
70 private:
71 ScopedObjectAccessUnchecked& soa_;
72 std::vector<jvalue>& args_;
73
74 DISALLOW_COPY_AND_ASSIGN(BuildPortableArgumentVisitor);
75};
76
77// Visits arguments on the stack placing them into the args vector, Object* arguments are converted
78// to jobjects.
79class BuildQuickArgumentVisitor : public QuickArgumentVisitor {
80 public:
81 BuildQuickArgumentVisitor(MethodHelper& caller_mh, mirror::AbstractMethod** sp,
82 ScopedObjectAccessUnchecked& soa, std::vector<jvalue>& args) :
83 QuickArgumentVisitor(caller_mh, sp), soa_(soa), args_(args) {}
Ian Rogersaf6e67a2013-01-16 08:38:37 -080084
85 virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
86 jvalue val;
87 Primitive::Type type = GetParamPrimitiveType();
88 switch (type) {
89 case Primitive::kPrimNot: {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080090 mirror::Object* obj = *reinterpret_cast<mirror::Object**>(GetParamAddress());
Ian Rogersaf6e67a2013-01-16 08:38:37 -080091 val.l = soa_.AddLocalReference<jobject>(obj);
92 break;
93 }
94 case Primitive::kPrimLong: // Fall-through.
95 case Primitive::kPrimDouble:
96 if (IsSplitLongOrDouble()) {
97 val.j = ReadSplitLongParam();
98 } else {
99 val.j = *reinterpret_cast<jlong*>(GetParamAddress());
100 }
101 break;
Ian Rogers7db619b2013-01-16 18:35:48 -0800102 case Primitive::kPrimBoolean: // Fall-through.
103 case Primitive::kPrimByte: // Fall-through.
104 case Primitive::kPrimChar: // Fall-through.
105 case Primitive::kPrimShort: // Fall-through.
106 case Primitive::kPrimInt: // Fall-through.
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800107 case Primitive::kPrimFloat:
108 val.i = *reinterpret_cast<jint*>(GetParamAddress());
109 break;
110 case Primitive::kPrimVoid:
111 LOG(FATAL) << "UNREACHABLE";
112 val.j = 0;
113 break;
114 }
115 args_.push_back(val);
116 }
117
118 private:
119 ScopedObjectAccessUnchecked& soa_;
120 std::vector<jvalue>& args_;
Ian Rogers7db619b2013-01-16 18:35:48 -0800121
Jeff Hao5fa60c32013-04-04 17:57:01 -0700122 DISALLOW_COPY_AND_ASSIGN(BuildQuickArgumentVisitor);
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800123};
124
Ian Rogers57b86d42012-03-27 16:05:41 -0700125// Handler for invocation on proxy methods. On entry a frame will exist for the proxy object method
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800126// which is responsible for recording callee save registers. We explicitly place into jobjects the
127// incoming reference arguments (so they survive GC). We invoke the invocation handler, which is a
128// field within the proxy object, which will box the primitive arguments and deal with error cases.
Jeff Hao5fa60c32013-04-04 17:57:01 -0700129extern "C" uint64_t artPortableProxyInvokeHandler(mirror::AbstractMethod* proxy_method,
130 mirror::Object* receiver,
131 Thread* self, mirror::AbstractMethod** sp)
132 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
133 // Ensure we don't get thread suspension until the object arguments are safely in jobjects.
134 const char* old_cause =
135 self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments");
136 self->VerifyStack();
137 // Start new JNI local reference state.
138 JNIEnvExt* env = self->GetJniEnv();
139 ScopedObjectAccessUnchecked soa(env);
140 ScopedJniEnvLocalRefState env_state(env);
141 // Create local ref. copies of proxy method and the receiver.
142 jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver);
143
144 // Placing arguments into args vector and remove the receiver.
145 MethodHelper proxy_mh(proxy_method);
146 std::vector<jvalue> args;
147 BuildPortableArgumentVisitor local_ref_visitor(proxy_mh, sp, soa, args);
148 local_ref_visitor.VisitArguments();
149 args.erase(args.begin());
150
151 // Convert proxy method into expected interface method.
152 mirror::AbstractMethod* interface_method = proxy_method->FindOverriddenMethod();
153 DCHECK(interface_method != NULL);
154 DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
155 jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method);
156
157 // All naked Object*s should now be in jobjects, so its safe to go into the main invoke code
158 // that performs allocations.
159 self->EndAssertNoThreadSuspension(old_cause);
160 JValue result = InvokeProxyInvocationHandler(soa, proxy_mh.GetShorty(),
161 rcvr_jobj, interface_method_jobj, args);
162 return result.GetJ();
163}
164
165// Handler for invocation on proxy methods. On entry a frame will exist for the proxy object method
166// which is responsible for recording callee save registers. We explicitly place into jobjects the
167// incoming reference arguments (so they survive GC). We invoke the invocation handler, which is a
168// field within the proxy object, which will box the primitive arguments and deal with error cases.
169extern "C" uint64_t artQuickProxyInvokeHandler(mirror::AbstractMethod* proxy_method,
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800170 mirror::Object* receiver,
171 Thread* self, mirror::AbstractMethod** sp)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700172 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogersf58dffd2013-01-13 09:25:49 -0800173 // Ensure we don't get thread suspension until the object arguments are safely in jobjects.
174 const char* old_cause =
175 self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments");
176 // Register the top of the managed stack, making stack crawlable.
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800177 DCHECK_EQ(*sp, proxy_method);
178 self->SetTopOfStack(sp, 0);
179 DCHECK_EQ(proxy_method->GetFrameSizeInBytes(),
180 Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
Ian Rogersf58dffd2013-01-13 09:25:49 -0800181 self->VerifyStack();
182 // Start new JNI local reference state.
Ian Rogers57b86d42012-03-27 16:05:41 -0700183 JNIEnvExt* env = self->GetJniEnv();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700184 ScopedObjectAccessUnchecked soa(env);
Ian Rogers57b86d42012-03-27 16:05:41 -0700185 ScopedJniEnvLocalRefState env_state(env);
Ian Rogersf58dffd2013-01-13 09:25:49 -0800186 // Create local ref. copies of proxy method and the receiver.
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700187 jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver);
Ian Rogers57b86d42012-03-27 16:05:41 -0700188
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800189 // Placing arguments into args vector and remove the receiver.
Ian Rogers57b86d42012-03-27 16:05:41 -0700190 MethodHelper proxy_mh(proxy_method);
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800191 std::vector<jvalue> args;
Jeff Hao5fa60c32013-04-04 17:57:01 -0700192 BuildQuickArgumentVisitor local_ref_visitor(proxy_mh, sp, soa, args);
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800193 local_ref_visitor.VisitArguments();
194 args.erase(args.begin());
Ian Rogersf58dffd2013-01-13 09:25:49 -0800195
Ian Rogersf58dffd2013-01-13 09:25:49 -0800196 // Convert proxy method into expected interface method.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800197 mirror::AbstractMethod* interface_method = proxy_method->FindOverriddenMethod();
Ian Rogers57b86d42012-03-27 16:05:41 -0700198 DCHECK(interface_method != NULL);
199 DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800200 jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method);
201
202 // All naked Object*s should now be in jobjects, so its safe to go into the main invoke code
203 // that performs allocations.
204 self->EndAssertNoThreadSuspension(old_cause);
205 JValue result = InvokeProxyInvocationHandler(soa, proxy_mh.GetShorty(),
206 rcvr_jobj, interface_method_jobj, args);
207 return result.GetJ();
Ian Rogers57b86d42012-03-27 16:05:41 -0700208}
209
210} // namespace art