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
172c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers#include "calling_convention_x86.h"
1857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
1907ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
203e0acf673ce1fbb3932d288d7b52a6dc551a920fMathieu Chartier#include "handle_scope-inl.h"
21166db04e259ca51838c311891598664deeed85adIan Rogers#include "utils/x86/managed_register_x86.h"
22b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
23b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersnamespace art {
242c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogersnamespace x86 {
25b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
262c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers// Calling convention
272c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
282c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersManagedRegister X86ManagedRuntimeCallingConvention::InterproceduralScratchRegister() {
292c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  return X86ManagedRegister::FromCpuRegister(ECX);
30b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
31b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
322c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersManagedRegister X86JniCallingConvention::InterproceduralScratchRegister() {
332c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  return X86ManagedRegister::FromCpuRegister(ECX);
34b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
35b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
36dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian RogersManagedRegister X86JniCallingConvention::ReturnScratchRegister() const {
37dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers  return ManagedRegister::NoRegister();  // No free regs, so assembler uses push/pop
38dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers}
39dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers
40b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogersstatic ManagedRegister ReturnRegisterForShorty(const char* shorty, bool jni) {
41169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  if (shorty[0] == 'F' || shorty[0] == 'D') {
42b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    if (jni) {
43b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      return X86ManagedRegister::FromX87Register(ST0);
44b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    } else {
45b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      return X86ManagedRegister::FromXmmRegister(XMM0);
46b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    }
47169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  } else if (shorty[0] == 'J') {
482c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers    return X86ManagedRegister::FromRegisterPair(EAX_EDX);
49169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  } else if (shorty[0] == 'V') {
5045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    return ManagedRegister::NoRegister();
51b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  } else {
522c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers    return X86ManagedRegister::FromCpuRegister(EAX);
53b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  }
54b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
55b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
562c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersManagedRegister X86ManagedRuntimeCallingConvention::ReturnRegister() {
57b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  return ReturnRegisterForShorty(GetShorty(), false);
582c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers}
592c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
602c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersManagedRegister X86JniCallingConvention::ReturnRegister() {
61b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  return ReturnRegisterForShorty(GetShorty(), true);
622c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers}
632c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
6400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan RogersManagedRegister X86JniCallingConvention::IntReturnRegister() {
6500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  return X86ManagedRegister::FromCpuRegister(EAX);
6600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}
6700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
68b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Managed runtime calling convention
69b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
702c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersManagedRegister X86ManagedRuntimeCallingConvention::MethodRegister() {
7167375acd9fec74cc2054554fe1ed0a7d213e1e47Ian Rogers  return X86ManagedRegister::FromCpuRegister(EAX);
722c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers}
732c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
742c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogersbool X86ManagedRuntimeCallingConvention::IsCurrentParamInRegister() {
75b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  return false;  // Everything is passed by stack
76b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
77b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
782c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogersbool X86ManagedRuntimeCallingConvention::IsCurrentParamOnStack() {
79966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell  // We assume all parameters are on stack, args coming via registers are spilled as entry_spills.
80966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell  return true;
81b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
82b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
832c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersManagedRegister X86ManagedRuntimeCallingConvention::CurrentParamRegister() {
84966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell  ManagedRegister res = ManagedRegister::NoRegister();
85966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell  if (!IsCurrentParamAFloatOrDouble()) {
86966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    switch (gpr_arg_count_) {
873e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell      case 0:
883e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell        res = X86ManagedRegister::FromCpuRegister(ECX);
893e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell        break;
903e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell      case 1:
913e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell        res = X86ManagedRegister::FromCpuRegister(EDX);
923e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell        break;
933e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell      case 2:
943e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell        // Don't split a long between the last register and the stack.
953e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell        if (IsCurrentParamALong()) {
963e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell          return ManagedRegister::NoRegister();
973e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell        }
983e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell        res = X86ManagedRegister::FromCpuRegister(EBX);
993e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell        break;
100966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    }
101966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell  } else if (itr_float_and_doubles_ < 4) {
102966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    // First four float parameters are passed via XMM0..XMM3
103966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    res = X86ManagedRegister::FromXmmRegister(
104966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell                                 static_cast<XmmRegister>(XMM0 + itr_float_and_doubles_));
105966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell  }
106966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell  return res;
107966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell}
108966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
109966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P MendellManagedRegister X86ManagedRuntimeCallingConvention::CurrentParamHighLongRegister() {
110966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell  ManagedRegister res = ManagedRegister::NoRegister();
111966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell  DCHECK(IsCurrentParamALong());
112966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell  switch (gpr_arg_count_) {
113966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    case 0: res = X86ManagedRegister::FromCpuRegister(EDX); break;
114966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    case 1: res = X86ManagedRegister::FromCpuRegister(EBX); break;
115966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell  }
116966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell  return res;
117b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
118b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
1192c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersFrameOffset X86ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
120cdd1d2d3fee0711b8b11db99f2dfb80113520100Ian Rogers  return FrameOffset(displacement_.Int32Value() +   // displacement
121790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers                     kFramePointerSize +                 // Method*
122790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers                     (itr_slots_ * kFramePointerSize));  // offset into in args
123b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
124b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
125fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenkoconst ManagedRegisterEntrySpills& X86ManagedRuntimeCallingConvention::EntrySpills() {
126b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  // We spill the argument registers on X86 to free them up for scratch use, we then assume
127b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  // all arguments are on the stack.
128b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  if (entry_spills_.size() == 0) {
129966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    ResetIterator(FrameOffset(0));
130966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell    while (HasNext()) {
131966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell      ManagedRegister in_reg = CurrentParamRegister();
1323e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell      bool is_long = IsCurrentParamALong();
133966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell      if (!in_reg.IsNoRegister()) {
134966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell        int32_t size = IsParamADouble(itr_args_) ? 8 : 4;
135966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell        int32_t spill_offset = CurrentParamStackOffset().Uint32Value();
136966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell        ManagedRegisterSpill spill(in_reg, size, spill_offset);
137966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell        entry_spills_.push_back(spill);
1383e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell        if (is_long) {
1393e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell          // special case, as we need a second register here.
140966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell          in_reg = CurrentParamHighLongRegister();
1413e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell          DCHECK(!in_reg.IsNoRegister());
1423e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell          // We have to spill the second half of the long.
1433e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell          ManagedRegisterSpill spill2(in_reg, size, spill_offset + 4);
1443e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell          entry_spills_.push_back(spill2);
145966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell        }
146966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell
147966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell        // Keep track of the number of GPRs allocated.
148966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell        if (!IsCurrentParamAFloatOrDouble()) {
1493e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell          if (is_long) {
1503e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell            // Long was allocated in 2 registers.
1513e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell            gpr_arg_count_ += 2;
1523e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell          } else {
1533e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell            gpr_arg_count_++;
1543e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell          }
155b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers        }
1563e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell      } else if (is_long) {
1573e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell        // We need to skip the unused last register, which is empty.
1583e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell        // If we are already out of registers, this is harmless.
1593e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell        gpr_arg_count_ += 2;
160b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
161966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell      Next();
162b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    }
163b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
164b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  return entry_spills_;
165b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers}
166b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers
167b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// JNI calling convention
168b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
169703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhaoX86JniCallingConvention::X86JniCallingConvention(bool is_static, bool is_synchronized,
170703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao                                                 const char* shorty)
171790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers    : JniCallingConvention(is_static, is_synchronized, shorty, kFramePointerSize) {
172703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao  callee_save_regs_.push_back(X86ManagedRegister::FromCpuRegister(EBP));
173703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao  callee_save_regs_.push_back(X86ManagedRegister::FromCpuRegister(ESI));
174703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao  callee_save_regs_.push_back(X86ManagedRegister::FromCpuRegister(EDI));
175703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao}
176703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao
177703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhaouint32_t X86JniCallingConvention::CoreSpillMask() const {
178703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao  return 1 << EBP | 1 << ESI | 1 << EDI | 1 << kNumberOfCpuRegisters;
179703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao}
180bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers
1812c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogerssize_t X86JniCallingConvention::FrameSize() {
182703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao  // Method*, return address and callee save area size, local reference segment state
183e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  size_t frame_data_size = kX86PointerSize +
184cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe      (2 + CalleeSaveRegisters().size()) * kFramePointerSize;
185eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  // References plus 2 words for HandleScope header
186cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe  size_t handle_scope_size = HandleScope::SizeOf(kFramePointerSize, ReferenceCount());
1870d666d8769714dcbc2acc4dd5b06f0deffa6e0a1Ian Rogers  // Plus return value spill area size
188eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  return RoundUp(frame_data_size + handle_scope_size + SizeOfReturnValue(), kStackAlignment);
1890d666d8769714dcbc2acc4dd5b06f0deffa6e0a1Ian Rogers}
1900d666d8769714dcbc2acc4dd5b06f0deffa6e0a1Ian Rogers
1912c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogerssize_t X86JniCallingConvention::OutArgSize() {
192790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers  return RoundUp(NumberOfOutgoingStackArgs() * kFramePointerSize, kStackAlignment);
1937a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers}
1947a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers
1952c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogersbool X86JniCallingConvention::IsCurrentParamInRegister() {
196b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  return false;  // Everything is passed by stack.
197b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
198b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
1992c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogersbool X86JniCallingConvention::IsCurrentParamOnStack() {
200b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  return true;  // Everything is passed by stack.
201b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
202b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
2032c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersManagedRegister X86JniCallingConvention::CurrentParamRegister() {
204b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  LOG(FATAL) << "Should not reach here";
205b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers  return ManagedRegister::NoRegister();
206b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
207b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
2082c8f653c98d658419f464b6147c10e11a664d2e6Ian RogersFrameOffset X86JniCallingConvention::CurrentParamStackOffset() {
209790a6b7312979513710c366b411ba6791ddf78c2Ian Rogers  return FrameOffset(displacement_.Int32Value() - OutArgSize() + (itr_slots_ * kFramePointerSize));
210b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
211b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
2122c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogerssize_t X86JniCallingConvention::NumberOfOutgoingStackArgs() {
213169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  size_t static_args = IsStatic() ? 1 : 0;  // count jclass
2147a99c11d220ec68c208b507570e3a78c2c18a7a1Ian Rogers  // regular argument parameters and this
215169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  size_t param_args = NumArgs() + NumLongOrDoubleArgs();
21600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // count JNIEnv* and return pc (pushed after Method*)
21700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  size_t total_args = static_args + param_args + 2;
21800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  return total_args;
219b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}
220b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers
2212c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers}  // namespace x86
222b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}  // namespace art
223