diff options
Diffstat (limited to 'vm/compiler/codegen/x86/NcgHelper.cpp')
-rw-r--r-- | vm/compiler/codegen/x86/NcgHelper.cpp | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/vm/compiler/codegen/x86/NcgHelper.cpp b/vm/compiler/codegen/x86/NcgHelper.cpp new file mode 100644 index 000000000..f9192dbdb --- /dev/null +++ b/vm/compiler/codegen/x86/NcgHelper.cpp @@ -0,0 +1,118 @@ +/* + * 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 +} |