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