blob: 5bf3cde374ce0a68feafd350e75be7906458df8a [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 Rogers57b86d42012-03-27 16:05:41 -070018#include "object.h"
19#include "object_utils.h"
20#include "reflection.h"
TDYa1275bb86012012-04-11 05:57:28 -070021#include "runtime_support.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070022#include "scoped_thread_state_change.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070023#include "thread.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070024#include "well_known_classes.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070025
26#include "ScopedLocalRef.h"
27
28namespace art {
29
Ian Rogersaf6e67a2013-01-16 08:38:37 -080030// Visits arguments on the stack placing them into the args vector, Object* arguments are converted
31// to jobjects.
32class BuildArgumentVisitor : public ArgumentVisitor {
33 public:
34 BuildArgumentVisitor(MethodHelper& caller_mh, AbstractMethod** sp,
35 ScopedObjectAccessUnchecked& soa, std::vector<jvalue>& args) :
36 ArgumentVisitor(caller_mh, sp), soa_(soa), args_(args) {}
37
38 virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
39 jvalue val;
40 Primitive::Type type = GetParamPrimitiveType();
41 switch (type) {
42 case Primitive::kPrimNot: {
43 Object* obj = *reinterpret_cast<Object**>(GetParamAddress());
44 val.l = soa_.AddLocalReference<jobject>(obj);
45 break;
46 }
47 case Primitive::kPrimLong: // Fall-through.
48 case Primitive::kPrimDouble:
49 if (IsSplitLongOrDouble()) {
50 val.j = ReadSplitLongParam();
51 } else {
52 val.j = *reinterpret_cast<jlong*>(GetParamAddress());
53 }
54 break;
55 case Primitive::kPrimBoolean:
56 case Primitive::kPrimByte:
57 case Primitive::kPrimChar:
58 case Primitive::kPrimShort:
59 case Primitive::kPrimInt:
60 case Primitive::kPrimFloat:
61 val.i = *reinterpret_cast<jint*>(GetParamAddress());
62 break;
63 case Primitive::kPrimVoid:
64 LOG(FATAL) << "UNREACHABLE";
65 val.j = 0;
66 break;
67 }
68 args_.push_back(val);
69 }
70
71 private:
72 ScopedObjectAccessUnchecked& soa_;
73 std::vector<jvalue>& args_;
74};
75
Ian Rogers57b86d42012-03-27 16:05:41 -070076// Handler for invocation on proxy methods. On entry a frame will exist for the proxy object method
Ian Rogersaf6e67a2013-01-16 08:38:37 -080077// which is responsible for recording callee save registers. We explicitly place into jobjects the
78// incoming reference arguments (so they survive GC). We invoke the invocation handler, which is a
79// field within the proxy object, which will box the primitive arguments and deal with error cases.
80extern "C" uint64_t artProxyInvokeHandler(AbstractMethod* proxy_method, Object* receiver,
81 Thread* self, AbstractMethod** sp)
Ian Rogersb726dcb2012-09-05 08:57:23 -070082 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogersf58dffd2013-01-13 09:25:49 -080083 // Ensure we don't get thread suspension until the object arguments are safely in jobjects.
84 const char* old_cause =
85 self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments");
86 // Register the top of the managed stack, making stack crawlable.
Ian Rogersaf6e67a2013-01-16 08:38:37 -080087 DCHECK_EQ(*sp, proxy_method);
88 self->SetTopOfStack(sp, 0);
89 DCHECK_EQ(proxy_method->GetFrameSizeInBytes(),
90 Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
Ian Rogersf58dffd2013-01-13 09:25:49 -080091 self->VerifyStack();
92 // Start new JNI local reference state.
Ian Rogers57b86d42012-03-27 16:05:41 -070093 JNIEnvExt* env = self->GetJniEnv();
Ian Rogers00f7d0e2012-07-19 15:28:27 -070094 ScopedObjectAccessUnchecked soa(env);
Ian Rogers57b86d42012-03-27 16:05:41 -070095 ScopedJniEnvLocalRefState env_state(env);
Ian Rogersf58dffd2013-01-13 09:25:49 -080096 // Create local ref. copies of proxy method and the receiver.
Ian Rogers00f7d0e2012-07-19 15:28:27 -070097 jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver);
Ian Rogers57b86d42012-03-27 16:05:41 -070098
Ian Rogersaf6e67a2013-01-16 08:38:37 -080099 // Placing arguments into args vector and remove the receiver.
Ian Rogers57b86d42012-03-27 16:05:41 -0700100 MethodHelper proxy_mh(proxy_method);
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800101 std::vector<jvalue> args;
102 BuildArgumentVisitor local_ref_visitor(proxy_mh, sp, soa, args);
103 local_ref_visitor.VisitArguments();
104 args.erase(args.begin());
Ian Rogersf58dffd2013-01-13 09:25:49 -0800105
Ian Rogersf58dffd2013-01-13 09:25:49 -0800106 // Convert proxy method into expected interface method.
Mathieu Chartier66f19252012-09-18 08:57:04 -0700107 AbstractMethod* interface_method = proxy_method->FindOverriddenMethod();
Ian Rogers57b86d42012-03-27 16:05:41 -0700108 DCHECK(interface_method != NULL);
109 DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800110 jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method);
111
112 // All naked Object*s should now be in jobjects, so its safe to go into the main invoke code
113 // that performs allocations.
114 self->EndAssertNoThreadSuspension(old_cause);
115 JValue result = InvokeProxyInvocationHandler(soa, proxy_mh.GetShorty(),
116 rcvr_jobj, interface_method_jobj, args);
117 return result.GetJ();
Ian Rogers57b86d42012-03-27 16:05:41 -0700118}
119
120} // namespace art