• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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 /*
18  * JNI method invocation.  This is used to call a C/C++ JNI method.  The
19  * argument list has to be pushed onto the native stack according to
20  * local calling conventions.
21  *
22  * This version supports the MIPS O32 ABI.
23  */
24 
25 /* TODO: this is candidate for consolidation of similar code from ARM. */
26 
27 #include "Dalvik.h"
28 #include "libdex/DexClass.h"
29 
30 #include <stdlib.h>
31 #include <stddef.h>
32 #include <sys/stat.h>
33 
34 
35 /*
36  * The class loader will associate with each method a 32-bit info word
37  * (jniArgInfo) to support JNI calls.  The high order 4 bits of this word
38  * are the same for all targets, while the lower 28 are used for hints to
39  * allow accelerated JNI bridge transfers.
40  *
41  * jniArgInfo (32-bit int) layout:
42  *
43  *    SRRRHHHH HHHHHHHH HHHHHHHH HHHHHHHH
44  *
45  *    S - if set, ignore the hints and do things the hard way (scan signature)
46  *    R - return-type enumeration
47  *    H - target-specific hints (see below for details)
48  *
49  * This function produces mips-specific hints - specifically a description
50  * of padding required to keep all 64-bit parameters properly aligned.
51  *
52  * MIPS JNI hint format(Same as ARM)
53  *
54  *       LLLL FFFFFFFF FFFFFFFF FFFFFFFF
55  *
56  *   L - number of double-words of storage required on the stack (0-30 words)
57  *   F - pad flag -- if set, the stack increases 8 bytes, else the stack increases 4 bytes
58  *                   after copying 32 bits args into stack. (little different from ARM)
59  *
60  * If there are too many arguments to construct valid hints, this function will
61  * return a result with the S bit set.
62  */
dvmPlatformInvokeHints(const DexProto * proto)63 u4 dvmPlatformInvokeHints(const DexProto* proto)
64 {
65 
66     const char* sig = dexProtoGetShorty(proto);
67     int padFlags, jniHints;
68     char sigByte;
69     int stackOffset, padMask, hints;
70 
71     stackOffset = padFlags = 0;
72     padMask = 0x00000001;
73 
74     /* Skip past the return type */
75     sig++;
76 
77     while (true) {
78         sigByte = *(sig++);
79 
80         if (sigByte == '\0')
81             break;
82 
83         if (sigByte == 'D' || sigByte == 'J') {
84             if ((stackOffset & 1) != 0) {
85                 padFlags |= padMask;
86                 stackOffset++;
87                 padMask <<= 1;
88             }
89             stackOffset += 2;
90             padMask <<= 2;
91         } else {
92             stackOffset++;
93             padMask <<= 1;
94         }
95     }
96 
97     jniHints = 0;
98 
99     if (stackOffset > DALVIK_JNI_COUNT_SHIFT) {
100         /* too big for "fast" version */
101         jniHints = DALVIK_JNI_NO_ARG_INFO;
102     } else {
103         assert((padFlags & (0xffffffff << DALVIK_JNI_COUNT_SHIFT)) == 0);
104         /*
105          * StackOffset includes the space for a2/a3. However we have reserved
106          * 16 bytes on stack in CallO32.S, so we should subtract 2 from stackOffset.
107          */
108         stackOffset -= 2;
109         if (stackOffset < 0)
110             stackOffset = 0;
111         jniHints |= ((stackOffset+1) / 2) << DALVIK_JNI_COUNT_SHIFT;
112         jniHints |= padFlags;
113     }
114 
115     return jniHints;
116 }
117