/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "Dalvik.h" #include "NcgHelper.h" #include "interp/InterpDefs.h" /* * Find the matching case. Returns the offset to the handler instructions. * * Returns 3 if we don't find a match (it's the size of the packed-switch * instruction). */ s4 dvmNcgHandlePackedSwitch(const s4* entries, s4 firstKey, u2 size, s4 testVal) { //skip add_reg_reg (ADD_REG_REG_SIZE) and jump_reg (JUMP_REG_SIZE) const int kInstrLen = 4; //default to next bytecode if (testVal < firstKey || testVal >= firstKey + size) { LOGVV("Value %d not found in switch (%d-%d)", testVal, firstKey, firstKey+size-1); return kInstrLen; } assert(testVal - firstKey >= 0 && testVal - firstKey < size); LOGVV("Value %d found in slot %d (goto 0x%02x)", testVal, testVal - firstKey, s4FromSwitchData(&entries[testVal - firstKey])); return s4FromSwitchData(&entries[testVal - firstKey]); } /* return the number of bytes to increase the bytecode pointer by */ s4 dvmJitHandlePackedSwitch(const s4* entries, s4 firstKey, u2 size, s4 testVal) { if (testVal < firstKey || testVal >= firstKey + size) { LOGVV("Value %d not found in switch (%d-%d)", testVal, firstKey, firstKey+size-1); return 2*3;//bytecode packed_switch is 6(2*3) bytes long } LOGVV("Value %d found in slot %d (goto 0x%02x)", testVal, testVal - firstKey, s4FromSwitchData(&entries[testVal - firstKey])); return 2*s4FromSwitchData(&entries[testVal - firstKey]); //convert from u2 to byte } /* * Find the matching case. Returns the offset to the handler instructions. * * Returns 3 if we don't find a match (it's the size of the sparse-switch * instruction). */ s4 dvmNcgHandleSparseSwitch(const s4* keys, u2 size, s4 testVal) { const int kInstrLen = 4; //CHECK const s4* entries = keys + size; int i; for (i = 0; i < size; i++) { s4 k = s4FromSwitchData(&keys[i]); if (k == testVal) { LOGVV("Value %d found in entry %d (goto 0x%02x)", testVal, i, s4FromSwitchData(&entries[i])); return s4FromSwitchData(&entries[i]); } else if (k > testVal) { break; } } LOGVV("Value %d not found in switch", testVal); return kInstrLen; } /* return the number of bytes to increase the bytecode pointer by */ s4 dvmJitHandleSparseSwitch(const s4* keys, u2 size, s4 testVal) { const s4* entries = keys + size; int i; for (i = 0; i < size; i++) { s4 k = s4FromSwitchData(&keys[i]); if (k == testVal) { LOGVV("Value %d found in entry %d (goto 0x%02x)", testVal, i, s4FromSwitchData(&entries[i])); return 2*s4FromSwitchData(&entries[i]); //convert from u2 to byte } else if (k > testVal) { break; } } LOGVV("Value %d not found in switch", testVal); return 2*3; //bytecode sparse_switch is 6(2*3) bytes long } /* * Look up an interface on a class using the cache. */ /*INLINE*/ Method* dvmFindInterfaceMethodInCache2(ClassObject* thisClass, u4 methodIdx, const Method* method, DvmDex* methodClassDex) { #define ATOMIC_CACHE_CALC \ dvmInterpFindInterfaceMethod(thisClass, methodIdx, method, methodClassDex) return (Method*) ATOMIC_CACHE_LOOKUP(methodClassDex->pInterfaceCache, DEX_INTERFACE_CACHE_SIZE, thisClass, methodIdx); #undef ATOMIC_CACHE_CALC }