NcgHelper.cpp revision 0c2dc522d0e120f346cf0a40c8cf0c93346131c2
1/*
2 * Copyright (C) 2012 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#include "Dalvik.h"
19#include "NcgHelper.h"
20#include "interp/InterpDefs.h"
21
22
23/*
24 * Find the matching case.  Returns the offset to the handler instructions.
25 *
26 * Returns 3 if we don't find a match (it's the size of the packed-switch
27 * instruction).
28 */
29s4 dvmNcgHandlePackedSwitch(const s4* entries, s4 firstKey, u2 size, s4 testVal)
30{
31    //skip add_reg_reg (ADD_REG_REG_SIZE) and jump_reg (JUMP_REG_SIZE)
32    const int kInstrLen = 4; //default to next bytecode
33    if (testVal < firstKey || testVal >= firstKey + size) {
34        LOGVV("Value %d not found in switch (%d-%d)",
35            testVal, firstKey, firstKey+size-1);
36        return kInstrLen;
37    }
38
39    assert(testVal - firstKey >= 0 && testVal - firstKey < size);
40    LOGVV("Value %d found in slot %d (goto 0x%02x)",
41        testVal, testVal - firstKey,
42        s4FromSwitchData(&entries[testVal - firstKey]));
43    return s4FromSwitchData(&entries[testVal - firstKey]);
44
45}
46/* return the number of bytes to increase the bytecode pointer by */
47s4 dvmJitHandlePackedSwitch(const s4* entries, s4 firstKey, u2 size, s4 testVal)
48{
49    if (testVal < firstKey || testVal >= firstKey + size) {
50        LOGVV("Value %d not found in switch (%d-%d)",
51            testVal, firstKey, firstKey+size-1);
52        return 2*3;//bytecode packed_switch is 6(2*3) bytes long
53    }
54
55    LOGVV("Value %d found in slot %d (goto 0x%02x)",
56        testVal, testVal - firstKey,
57        s4FromSwitchData(&entries[testVal - firstKey]));
58    return 2*s4FromSwitchData(&entries[testVal - firstKey]); //convert from u2 to byte
59
60}
61/*
62 * Find the matching case.  Returns the offset to the handler instructions.
63 *
64 * Returns 3 if we don't find a match (it's the size of the sparse-switch
65 * instruction).
66 */
67s4 dvmNcgHandleSparseSwitch(const s4* keys, u2 size, s4 testVal)
68{
69    const int kInstrLen = 4; //CHECK
70    const s4* entries = keys + size;
71    int i;
72    for (i = 0; i < size; i++) {
73        s4 k = s4FromSwitchData(&keys[i]);
74        if (k == testVal) {
75            LOGVV("Value %d found in entry %d (goto 0x%02x)",
76                testVal, i, s4FromSwitchData(&entries[i]));
77            return s4FromSwitchData(&entries[i]);
78        } else if (k > testVal) {
79            break;
80        }
81    }
82
83    LOGVV("Value %d not found in switch", testVal);
84    return kInstrLen;
85}
86/* return the number of bytes to increase the bytecode pointer by */
87s4 dvmJitHandleSparseSwitch(const s4* keys, u2 size, s4 testVal)
88{
89    const s4* entries = keys + size;
90    int i;
91    for (i = 0; i < size; i++) {
92        s4 k = s4FromSwitchData(&keys[i]);
93        if (k == testVal) {
94            LOGVV("Value %d found in entry %d (goto 0x%02x)",
95                testVal, i, s4FromSwitchData(&entries[i]));
96            return 2*s4FromSwitchData(&entries[i]); //convert from u2 to byte
97        } else if (k > testVal) {
98            break;
99        }
100    }
101
102    LOGVV("Value %d not found in switch", testVal);
103    return 2*3; //bytecode sparse_switch is 6(2*3) bytes long
104}
105/*
106 * Look up an interface on a class using the cache.
107 */
108/*INLINE*/ Method* dvmFindInterfaceMethodInCache2(ClassObject* thisClass,
109    u4 methodIdx, const Method* method, DvmDex* methodClassDex)
110{
111#define ATOMIC_CACHE_CALC \
112    dvmInterpFindInterfaceMethod(thisClass, methodIdx, method, methodClassDex)
113
114    return (Method*) ATOMIC_CACHE_LOOKUP(methodClassDex->pInterfaceCache,
115                DEX_INTERFACE_CACHE_SIZE, thisClass, methodIdx);
116
117#undef ATOMIC_CACHE_CALC
118}
119