summaryrefslogtreecommitdiffstats
path: root/vm/compiler/codegen/x86/NcgHelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vm/compiler/codegen/x86/NcgHelper.cpp')
-rw-r--r--vm/compiler/codegen/x86/NcgHelper.cpp118
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
+}