1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Target-specific optimization and run-time hints
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "libdex/DexClass.h"
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stddef.h>
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/stat.h>
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class loader will associate with each method a 32-bit info word
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (jniArgInfo) to support JNI calls.  The high order 4 bits of this word
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * are the same for all targets, while the lower 28 are used for hints to
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * allow accelerated JNI bridge transfers.
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * jniArgInfo (32-bit int) layout:
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *    SRRRHHHH HHHHHHHH HHHHHHHH HHHHHHHH
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *    S - if set, ignore the hints and do things the hard way (scan signature)
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *    R - return-type enumeration
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *    H - target-specific hints (see below for details)
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This function produces arm-specific hints - specifically a description
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of padding required to keep all 64-bit parameters properly aligned.
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ARM JNI hint format
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *       LLLL FFFFFFFF FFFFFFFF FFFFFFFF
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   L - number of double-words of storage required on the stack (0-30 words)
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   F - pad flag -- if set, write a pad word to the stack before copying
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *       the next 32 bits
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If there are too many arguments to construct valid hints, this function will
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return a result with the S bit set.
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectu4 dvmPlatformInvokeHints(const DexProto* proto)
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* sig = dexProtoGetShorty(proto);
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int padFlags, jniHints;
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char sigByte;
62e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro    int stackOffset, padMask;
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackOffset = padFlags = 0;
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    padMask = 0x00000001;
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Skip past the return type */
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sig++;
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (true) {
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sigByte = *(sig++);
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (sigByte == '\0')
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (sigByte == 'D' || sigByte == 'J') {
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ((stackOffset & 1) != 0) {
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                padFlags |= padMask;
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                stackOffset++;
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                padMask <<= 1;
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            stackOffset += 2;
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            padMask <<= 2;
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            stackOffset++;
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            padMask <<= 1;
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    jniHints = 0;
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (stackOffset > DALVIK_JNI_COUNT_SHIFT) {
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* too big for "fast" version */
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jniHints = DALVIK_JNI_NO_ARG_INFO;
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert((padFlags & (0xffffffff << DALVIK_JNI_COUNT_SHIFT)) == 0);
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        stackOffset -= 2;           // r2/r3 holds first two items
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (stackOffset < 0)
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            stackOffset = 0;
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jniHints |= ((stackOffset+1) / 2) << DALVIK_JNI_COUNT_SHIFT;
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jniHints |= padFlags;
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return jniHints;
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
106