calling_convention.cc revision 7940e44f4517de5e2634a7e07d58d0fb26160513
1/*
2 * Copyright (C) 2011 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#include "calling_convention.h"
18
19#include "base/logging.h"
20#include "jni/quick/arm/calling_convention_arm.h"
21#include "jni/quick/mips/calling_convention_mips.h"
22#include "jni/quick/x86/calling_convention_x86.h"
23#include "utils.h"
24
25namespace art {
26
27// Offset of Method within the frame
28FrameOffset CallingConvention::MethodStackOffset() {
29  return displacement_;
30}
31
32// Managed runtime calling convention
33
34ManagedRuntimeCallingConvention* ManagedRuntimeCallingConvention::Create(
35    bool is_static, bool is_synchronized, const char* shorty, InstructionSet instruction_set) {
36  switch (instruction_set) {
37    case kArm:
38    case kThumb2:
39      return new arm::ArmManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
40    case kMips:
41      return new mips::MipsManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
42    case kX86:
43      return new x86::X86ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
44    default:
45      LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
46      return NULL;
47  }
48}
49
50bool ManagedRuntimeCallingConvention::HasNext() {
51  return itr_args_ < NumArgs();
52}
53
54void ManagedRuntimeCallingConvention::Next() {
55  CHECK(HasNext());
56  if (IsCurrentArgExplicit() &&  // don't query parameter type of implicit args
57      IsParamALongOrDouble(itr_args_)) {
58    itr_longs_and_doubles_++;
59    itr_slots_++;
60  }
61  if (IsCurrentParamAReference()) {
62    itr_refs_++;
63  }
64  itr_args_++;
65  itr_slots_++;
66}
67
68bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
69  // Static methods have no implicit arguments, others implicitly pass this
70  return IsStatic() || (itr_args_ != 0);
71}
72
73bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
74  return IsCurrentArgExplicit();  // any user parameter may be null
75}
76
77size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
78  return ParamSize(itr_args_);
79}
80
81bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
82  return IsParamAReference(itr_args_);
83}
84
85// JNI calling convention
86
87JniCallingConvention* JniCallingConvention::Create(bool is_static, bool is_synchronized,
88                                                   const char* shorty,
89                                                   InstructionSet instruction_set) {
90  switch (instruction_set) {
91    case kArm:
92    case kThumb2:
93      return new arm::ArmJniCallingConvention(is_static, is_synchronized, shorty);
94    case kMips:
95      return new mips::MipsJniCallingConvention(is_static, is_synchronized, shorty);
96    case kX86:
97      return new x86::X86JniCallingConvention(is_static, is_synchronized, shorty);
98    default:
99      LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
100      return NULL;
101  }
102}
103
104size_t JniCallingConvention::ReferenceCount() const {
105  return NumReferenceArgs() + (IsStatic() ? 1 : 0);
106}
107
108FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
109  size_t start_of_sirt = SirtLinkOffset().Int32Value() +  kPointerSize;
110  size_t references_size = kPointerSize * ReferenceCount();  // size excluding header
111  return FrameOffset(start_of_sirt + references_size);
112}
113
114FrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
115  // Segment state is 4 bytes long
116  return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4);
117}
118
119bool JniCallingConvention::HasNext() {
120  if (itr_args_ <= kObjectOrClass) {
121    return true;
122  } else {
123    unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
124    return arg_pos < NumArgs();
125  }
126}
127
128void JniCallingConvention::Next() {
129  CHECK(HasNext());
130  if (itr_args_ > kObjectOrClass) {
131    int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
132    if (IsParamALongOrDouble(arg_pos)) {
133      itr_longs_and_doubles_++;
134      itr_slots_++;
135    }
136  }
137  if (IsCurrentParamAReference()) {
138    itr_refs_++;
139  }
140  itr_args_++;
141  itr_slots_++;
142}
143
144bool JniCallingConvention::IsCurrentParamAReference() {
145  switch (itr_args_) {
146    case kJniEnv:
147      return false;  // JNIEnv*
148    case kObjectOrClass:
149      return true;   // jobject or jclass
150    default: {
151      int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
152      return IsParamAReference(arg_pos);
153    }
154  }
155}
156
157// Return position of SIRT entry holding reference at the current iterator
158// position
159FrameOffset JniCallingConvention::CurrentParamSirtEntryOffset() {
160  CHECK(IsCurrentParamAReference());
161  CHECK_GT(SirtLinkOffset(), SirtNumRefsOffset());
162  // Address of 1st SIRT entry
163  int result = SirtLinkOffset().Int32Value() + kPointerSize;
164  result += itr_refs_ * kPointerSize;
165  CHECK_GT(result, SirtLinkOffset().Int32Value());
166  return FrameOffset(result);
167}
168
169size_t JniCallingConvention::CurrentParamSize() {
170  if (itr_args_ <= kObjectOrClass) {
171    return kPointerSize;  // JNIEnv or jobject/jclass
172  } else {
173    int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
174    return ParamSize(arg_pos);
175  }
176}
177
178size_t JniCallingConvention::NumberOfExtraArgumentsForJni() {
179  // The first argument is the JNIEnv*.
180  // Static methods have an extra argument which is the jclass.
181  return IsStatic() ? 2 : 1;
182}
183
184}  // namespace art
185