calling_convention.cc revision 2faa5f1271587cda765f26bcf2951065300a01ff
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
16b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
17578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "calling_convention.h"
182c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
192c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers#include "calling_convention_arm.h"
202c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers#include "calling_convention_x86.h"
21578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "logging.h"
22578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "utils.h"
23b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
24b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersnamespace art {
25b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
26e2d373e6e09c1df9a47e73a26254048adb31ce82Carl Shapiro// Offset of Method within the frame
27e2d373e6e09c1df9a47e73a26254048adb31ce82Carl ShapiroFrameOffset CallingConvention::MethodStackOffset() {
28e2d373e6e09c1df9a47e73a26254048adb31ce82Carl Shapiro  return displacement_;
29e2d373e6e09c1df9a47e73a26254048adb31ce82Carl Shapiro}
30e2d373e6e09c1df9a47e73a26254048adb31ce82Carl Shapiro
31df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers// Managed runtime calling convention
32df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers
332c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersManagedRuntimeCallingConvention* ManagedRuntimeCallingConvention::Create(
34169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    bool is_static, bool is_synchronized, const char* shorty, InstructionSet instruction_set) {
352c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  if (instruction_set == kX86) {
36169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    return new x86::X86ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
372c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  } else {
382c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers    CHECK(instruction_set == kArm || instruction_set == kThumb2);
39169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    return new arm::ArmManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
402c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  }
412c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers}
422c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
43b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersbool ManagedRuntimeCallingConvention::HasNext() {
44169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  return itr_args_ < NumArgs();
45b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
46b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
47b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersvoid ManagedRuntimeCallingConvention::Next() {
48b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  CHECK(HasNext());
497a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers  if (IsCurrentArgExplicit() &&  // don't query parameter type of implicit args
50169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers      IsParamALongOrDouble(itr_args_)) {
51b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    itr_longs_and_doubles_++;
525381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao    itr_slots_++;
53b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
54668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao  if (IsCurrentParamAReference()) {
55668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao    itr_refs_++;
56668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao  }
575381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao  itr_args_++;
585381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao  itr_slots_++;
59b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
60b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
617a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogersbool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
627a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers  // Static methods have no implicit arguments, others implicitly pass this
63169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  return IsStatic() || (itr_args_ != 0);
647a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers}
657a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers
667a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogersbool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
677a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers  return IsCurrentArgExplicit();  // any user parameter may be null
68b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
69b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
70df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogerssize_t ManagedRuntimeCallingConvention::CurrentParamSize() {
71169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  return ParamSize(itr_args_);
72b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
73b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
74b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersbool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
75169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  return IsParamAReference(itr_args_);
76b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
77b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
78df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers// JNI calling convention
79b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
80169c9a7f46776b235d0a37d5e0ff27682deffe06Ian RogersJniCallingConvention* JniCallingConvention::Create(bool is_static, bool is_synchronized,
81169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers                                                   const char* shorty,
82169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers                                                   InstructionSet instruction_set) {
832c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  if (instruction_set == kX86) {
84169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    return new x86::X86JniCallingConvention(is_static, is_synchronized, shorty);
852c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  } else {
862c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers    CHECK(instruction_set == kArm || instruction_set == kThumb2);
87169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    return new arm::ArmJniCallingConvention(is_static, is_synchronized, shorty);
882c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  }
892c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers}
902c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
91dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogerssize_t JniCallingConvention::ReferenceCount() const {
92169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  return NumReferenceArgs() + (IsStatic() ? 1 : 0);
93b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
94b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
955a7a74a042e73a355f5cedffa0d2faf5340028faIan RogersFrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
96408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  size_t start_of_sirt = SirtLinkOffset().Int32Value() +  kPointerSize;
97408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  size_t references_size = kPointerSize * ReferenceCount();  // size excluding header
98408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  return FrameOffset(start_of_sirt + references_size);
99df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers}
100df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers
101dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian RogersFrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
102dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers  // Segment state is 4 bytes long
1035a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers  return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4);
104dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers}
105dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers
106b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersbool JniCallingConvention::HasNext() {
1075381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao  if (itr_args_ <= kObjectOrClass) {
108b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return true;
109b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  } else {
110169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
111169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    return arg_pos < NumArgs();
112b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
113b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
114b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
115b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersvoid JniCallingConvention::Next() {
116b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  CHECK(HasNext());
1175381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao  if (itr_args_ > kObjectOrClass) {
118169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
119169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    if (IsParamALongOrDouble(arg_pos)) {
120b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers      itr_longs_and_doubles_++;
1215381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao      itr_slots_++;
122b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    }
123b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
124668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao  if (IsCurrentParamAReference()) {
125668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao    itr_refs_++;
126668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao  }
1275381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao  itr_args_++;
1285381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao  itr_slots_++;
129b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
130b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
131b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersbool JniCallingConvention::IsCurrentParamAReference() {
1325381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao  switch (itr_args_) {
133b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    case kJniEnv:
134b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers      return false;  // JNIEnv*
135b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    case kObjectOrClass:
136b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers      return true;   // jobject or jclass
137b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    default: {
138169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers      int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
139169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers      return IsParamAReference(arg_pos);
140b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    }
141b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
142b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
143b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
144408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers// Return position of SIRT entry holding reference at the current iterator
145408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers// position
146408f79aeb676251ba35667a64e86c20638d7cb0bIan RogersFrameOffset JniCallingConvention::CurrentParamSirtEntryOffset() {
147b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  CHECK(IsCurrentParamAReference());
148408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  CHECK_GT(SirtLinkOffset(), SirtNumRefsOffset());
149408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  // Address of 1st SIRT entry
150408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  int result = SirtLinkOffset().Int32Value() + kPointerSize;
151668512afd0d9b3772a0abc589208b729ee16bc61Shih-wei Liao  result += itr_refs_ * kPointerSize;
152408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers  CHECK_GT(result, SirtLinkOffset().Int32Value());
153b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  return FrameOffset(result);
154b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
155b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
156df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogerssize_t JniCallingConvention::CurrentParamSize() {
1575381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao  if (itr_args_ <= kObjectOrClass) {
158b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers    return kPointerSize;  // JNIEnv or jobject/jclass
159b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  } else {
160169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
161169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    return ParamSize(arg_pos);
162b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
163b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
164b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
165169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogerssize_t JniCallingConvention::NumberOfExtraArgumentsForJni() {
1665381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao  // The first argument is the JNIEnv*.
1675381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao  // Static methods have an extra argument which is the jclass.
168169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  return IsStatic() ? 2 : 1;
1695381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao}
1705381cf941d26030199fcdbe61a614ff01e55a27cShih-wei Liao
171b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}  // namespace art
172